/* envircat.c | | $Header: E:/mark/envircat/envircat.c_v 1.2 27 Nov 1990 20:48:06 Mark_Gardner $ | | environment string concatenation | c1990 Mark Gardner, EEmergent Consulting, Acton, CA 805-269-1433 | */ /* | | compiled and assembled with Turbo C++ and Turbo Assembler: | | ... tcc -ml envircat env_adrs.asm | */ /* | inspired by 'LONGEST', a program downloaded from CompuServe, | by McLean, but which did not work on my computer (Scott Robert | Ladd says, in the article 'Locating The Master Environment' | [MS-DOS System Programming, c1990 R&D Publications, Lawrence, KS], | that later versions of DOS have an extra level of indirection; | this may be what has fooled 'LONGEST'). | | The program will find trigger words in the environment that | represent continuations of the previous defined string in the | environment. The trigger word must start with a + sign, have | the same name as the previous string to be extended, and the | name must be followed by any character(s) to distinguish the | name from all previous names. | | For example, if the PATH string was to be extended, the following | sequence of commands should be executed: | | PATH=C:\UTILS;C:\DOS;C:\; | SET +PATH1=D:\;D:\TEST;D:\TC\BIN | SET +PATH2=;D:\TD;D:\TP | | (Note, as for 'LONGEST' operating on a path, the preceding line must | anticipate the concatenation by terminating with a semicolon, or the | continuation line must, by beginning with a semicolon. The base rule | is that ENVIRCAT will not add any characters, only link strings. | | When executed, ENVIRCAT will remove the trigger tokens from the | enviroment and leave the master token assigned to the concatenated | string. The remainder of the environment will be moved up to occupy | the space that was vacated by the trigger tokens. | | This removes what seemed to be a constraint on the operation of | 'LONGEST'. This program need not be used as soon as the triggered | string is put in the environment, and it can be used while there are | multiple different trigger sets waiting for concatenation. | | Note, in the spirit of my personal bias, I have named this routine | with a long semi-mnemonic. For those that don't like such things, | the use of a batch file, EC.BAT, is recommended. | */ /* structured program design ; signon ; find the environment (call to assembly routine) ; if the first element in the environment is not 'COMSPEC' ; abort with error level 1 ; else ; report found ; end_if ; for each element ; if the next element is a trigger word ; count the occurrence ; remove the trigger word ; move the remainder of the environment down ; reset to subject element ; end_if ; end_for ; report occurrences */ #include #include #define TRUE 1 #define FALSE 0 #define NO_ERROR 0 #define ERRLEVEL1 1 char far *findmenv (void) ; #define SEARCHLIM 2 char far *environment ; char far *position ; char far *mid_position ; char element[40] ; char master_element[40] ; main () { char c ; int i ; int j ; int success ; int pluscount = { 0 } ; printf ( "environment string concatenation : ENVIRCAT v1.2\n" ) ; printf ( "c1990 Mark Gardner (placed in public domain)\n\n" ) ; environment = findmenv() ; i = 0 ; while ( i < SEARCHLIM ) if ( check_comspec() ) break ; else { i++ ; environment = environment + 16 ; end_if } end_while if ( i == SEARCHLIM ) { printf ( "\nenvircat can't find environment\n" ) ; return(ERRLEVEL1) ; end_if } printf ( "envircat found environment at %p\n", environment ) ; position = environment ; while ( find_element ( position ) ) if (element[0] != '+') { strcpy ( master_element, element ) ; mid_position = position ; } else { pluscount++ ; success = TRUE ; for ( i=0,j=1 ; i < strlen ( master_element ) ; i++,j++ ) if ( master_element[i] != element[j] ) { success = FALSE ; break ; end_if } end_for if ( success == TRUE ) { position = mid_position-- ; i = 0 ; while ( position[i++] != '=' ) ; end_while position = &position[i] ; i = j = 0 ; while ( j<2 ) { mid_position[i] = c = position[i] ; i++ ; if ( c == 0 ) j = j + 1 ; else j = 0 ; end_if end_while } position = environment ; end_if } end_if } end_while printf ( "envircat found %d continuations\n", pluscount ) ; return(NO_ERROR) ; } int function find_element ( char far *p ) { /* | stores element at current position in 'element', adjusts position to | point to beginning of next element, returns 0 if can't find element | at current position (end of environment). */ int i = { 0 } ; int j = { 0 } ; if ( p[0]==0 ) return(FALSE) ; end_if while ( p[i] != '=' ) element[j++] = p[i++] ; end_while element[j] = 0 ; while ( p[i++] != 0 ) ; end_while position = &p[i] ; return(TRUE) ; } int function check_comspec ( void ) { /* | verifies that the environment has been correctly located | by checking that the contents are 'reasonable'. The original | check was that the first characters spell "COMSPEC", but this | was not adequate, since some people redefine it, and it moves | away from the environment top. Hence, this routine searches | the forward string and assumes the environment is correctly | located if at least two equal signs precede the double nul. | Any other constraint is not too reasonable, as it is possible | to put any PC graphic character into the environment. | */ /* | determine max search to closing double nul in environment... | few indeed who have environments this big, I suppose and hope. */ #define MAX_EXPECTED 2048 int nul_count, eq_count, i ; i = eq_count = nul_count = 0 ; while ( ___ ( nul_count < 2 ) ___ && ( i < MAX_EXPECTED ) ___ ) { switch ( environment[i++] ) { case 0 : nul_count++ ; break ; end_case case '=' : eq_count++ ; con_case default : nul_count = 0 ; end_case end_switch } end_while } if ( ___ ( eq_count > 1 ) ___ && ( nul_count == 2 ) ___ ) return ( TRUE ) ; else return ( FALSE ) ; end_if }