home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <dos.h>
- #include <dir.h>
- #include <string.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;
-
- arena * ap;
-
- union REGS regs;
- struct SREGS sregs;
-
- #define arena_size 16
- #define NORMAL_ATYPE 0x4D
- #define LAST_ATYPE 0x5A
-
-
- arena * get_next_arena (arena * ap) {
- return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
- }
-
- 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 ( 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(ap);
- }
- return(NULL);
- }
-
-
- 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;
- char * ad;
-
- /* 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 */
- pspc = MK_FP( FP_SEG(pspp->prev_crit_error), 0);
-
- #ifdef DEBUG
- printf("comm.com=%p\n",pspc);
- #endif
-
- 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)) {
- ad = &ap->arena_data;
- while ( (*ad) &&
- ((ad-(char *)ap)>>4 < ap->num_segments) ) {
- if (strnicmp(ad, "COMSPEC=", 8)==0) return(ap);
- ad += strlen(ad) + 1;
- }
- }
- ap = get_next_arena(ap);
- }
- } return(NULL); }
-
- /*****************************************************************************/
-
- char setenv(char * symbol, char * val) {
- int total_size,
- needed_size=0,
- strlength;
- char * sp, *op, *envir;
- char symb_len=strlen(symbol);
- char found=0;
-
- strupr(symbol);
-
- /* first, can the COMMAND.COM 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);
- }
-
- /*****************************************************************************/
-
- void display_help() {
- puts("\nSETENV 1.1 by Richard Marks\n");
- puts(" Sets environment variables to a user response (for BAT files)\n");
- puts(" SETENV <envirn vbl name> <prompt message>\n");
- puts("Example:");
- puts(" setenv drv ""PLEASE ENTER DRIVE TO USE : "" ");
- puts("the message PLEASE ENTER DRIVE TO USE : is displayed on the console,");
- puts("the response is set into variable drv for use by the rest of the BAT file\n");
- puts("If there is a keyword instead of a <message>, SETENV will fill certain system");
- puts("values into the environment variable:\n");
- puts(" SETENV <envirn vbl name> %cwd - get current working directory");
- puts(" %drive- get default drive");
- puts(" %dosv - get dos major version");
- puts("Use %% to represent a single % in BAT files\n");
- puts("Multiple sets of arguments can be supplied:");
- puts(" SETENV <vbl> <msg> <vbl> <msg> . . .");
- }
-
- char get_default_drive () {
- regs.h.ah = 0x19;
- intdos(®s, ®s);
- return (regs.h.al);
- }
-
- char get_special_param(char *val, char *arg) {
- /* plugs the system parmeter specified in the arg into val
- %cwd = current directory path
- %drive= default drive
- %dosv = dos major version */
-
- if (stricmp(arg,"%CWD")==0) {
- getcwd(val, 128);
-
- } else if (stricmp(arg,"%DRIVE")==0) {
- val[0] = get_default_drive() + 'A';
- val[1] = 0;
-
- } else if (stricmp(arg,"%DOSV")==0) {
- val[0] = _osmajor+'0';
- val[1] = 0;
-
- } else
- return(1);
-
- return(0);
- }
-
-
- char get_user_input(char *val, char *msg) {
- /* solicits user for a value (val) by displaying the message (msg).
- then validates the message using criteria in arg. Criteria are:
- <null> no criteria test for now */
-
- do {
- printf("%s",msg);
- gets(val);
- } while (0);
- return(0);
- }
-
-
- char main(int argc, char *argv[]) {
- int argbase;
- char symbol[16], val[128];
-
- if (argc<3)
- { display_help(); return(0); }
-
- for (argbase=1; argbase<argc; argbase+=2) {
-
- if ( strlen(argv[argbase])>16 ) goto ERROR_RET;
- strcpy(symbol, argv[argbase]); strupr(symbol);
-
- if (argv[argbase+1][0]=='%') {
- if ( get_special_param(val, argv[argbase+1]) ) goto ERROR_RET;
- } else {
- if ( get_user_input(val, argv[argbase+1]) ) goto ERROR_RET;
- }
-
- if ( setenv(symbol, val) ) goto ERROR_RET;
- }
-
- return(0);
-
- ERROR_RET:
- #ifdef DEBUG
- puts("SETENV failed");
- #endif
- return(1);
- }