/* subroutine to put a value string into an environment symbol. Uses the controling command.com environment, not the programs. This means that the env variable is set so other routines in a .BAT file may use it. call: settheenv (char * symbol, char * val); symbol is an asciiz string containing the env variable name, val is an asciiz string containing the value to assign to this vbl. returns: 0 = OK, 1 = failure. failure is not unlikely. The env block may be full. Or on some systems the env block might not be found SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>. */ #include <stdio.h> #include <dos.h> #include <string.h> #include <stdlib.h> typedef struct { char fill1[0x0A]; int *prev_term_handler; int *prev_ctrl_c; int *prev_crit_error; char fill2[0x16]; int envir_seg; } psp; typedef struct { char type; int psp_segment; int num_segments; char fill[11]; char arena_data; } arena; #define NORMAL_ATYPE 0x4D #define LAST_ATYPE 0x5A static arena * get_next_arena (arena * ap) { return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) ); } /* returns 0 if passed pointer is to an arena, else returns 1 */ static int is_valid_arena (arena * ap) { arena * ap1; if (ap->type == NORMAL_ATYPE && (ap1=get_next_arena(ap))->type == NORMAL_ATYPE && ( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE || ap1->type == LAST_ATYPE) ) return(0); return (1); } static arena * get_first_arena () { /* return pointer to the first arena. * scan memory for a 0x4D on a segment start, * see if this points to another two levels of arena */ arena * ap, * ap1; int * temp; int segment; for (segment=0; segment<_CS; segment++) { ap = MK_FP(segment, 0); if ( is_valid_arena (ap) == 0) return (ap); } return(NULL); } /* end get_first_arena */ static int is_valid_env (char * ad, int num_segs) { char * base_ad; base_ad = ad; while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) { if (strnicmp(ad, "COMSPEC=", 8)==0) return(0); ad += strlen(ad) + 1; } return (1); } static arena * get_arena_of_environment () { /* to get the arena of first environment block: First get segment of COMMAND.COM from segment of previous critical err code. Then scan all the arenas for an environment block with a matching PSP segment */ arena * ap; psp * pspp, * pspc; unsigned int i, ccseg; /* set pspp to psp of this program */ pspp = MK_FP(_psp,0); #ifdef DEBUG printf("prog psp=%p\n",pspp); #endif /* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */ ccseg = FP_SEG (pspp->prev_crit_error); if ( (i=ccseg-32) < 60) i=60; while (ccseg>i) { pspc = MK_FP (ccseg, 0); if ( is_valid_arena((arena *) pspc) == 0) goto L1; ccseg--; } return (NULL); L1: pspc = MK_FP (++ccseg, 0); #ifdef DEBUG printf("comm.com=%p\n",pspc); #endif /* first see if env seg in command.com points to valid env block if env seg is in a valid arena, then arena must point to this command.com else assume env block is fabricated like for 4DOS, use 128 bytes */ ap = MK_FP (pspc->envir_seg-1, 0); i = ap->num_segments; if (is_valid_arena (ap) == 0) { if (ap->psp_segment != FP_SEG(pspc)) goto L2; } else { i = 9; } if ( is_valid_env (&ap->arena_data, i) == 0 ) return (ap); /* command.com did not so point, search thru all env blocks */ L2: if ( (ap=get_first_arena()) != NULL ) { while (ap->type != LAST_ATYPE) { #ifdef DEBUG printf("%p\n",ap); #endif if (ap->psp_segment == FP_SEG(pspc) && is_valid_env (&ap->arena_data, ap->num_segments)==0 ) return (ap); ap = get_next_arena(ap); } } return(NULL); } /* end get_arena_of_environment */ /*****************************************************************************/ int settheenv(char * symbol, char * val) { int total_size, needed_size=0, strlength; char * sp, *op, *envir; char symb_len=strlen(symbol); char found=0; arena * ap; strupr(symbol); /* first, can COMMAND.COM's envir block be found ? */ if ( (ap=get_arena_of_environment()) == NULL) return(1); /* search to end of the envir block, get sizes */ total_size = 16 * ap->num_segments; envir = &ap->arena_data; op=sp=envir; while (*sp) { strlength = strlen(sp)+1; if ( *(sp+symb_len)=='=' && strnicmp(sp,symbol,symb_len)==0 ) found=1; else { needed_size += strlength; if (found) strcpy(op,sp); op = &op[strlength]; } sp += strlength; } *op=0; if (strlen(val) > 0) { needed_size += 3 + strlen(symbol) + strlen(val); if (needed_size > total_size) return(1); /* could mess with environment expansion here */ strcpy(op, symbol); strcat(op, "="); strcat(op, val); op += strlen(op)+1; *op = 0; } return(0); } /* end setheenv subroutine */