broehl@watale.UUCP (Bernie Roehl) (08/24/86)
This routine can be used to put a string into the DOS environment from any subprogram. called like this. putdenv("VARIABLE=value"); Have Fun!!!! # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by watale!broehl on Sat Aug 23 22:08:56 EDT 1986 # Contents: putdenv.c echo x - putdenv.c sed 's/^@//' > "putdenv.c" <<'@//E*O*F putdenv.c//' /* Set an environment variable in the DOS environment ** ** Author: ** uucp: ihnp4!watmath!watdcsu!broehl Bernie Roehl ** ** Based on Code and techniques written by: ** uucp: ..{ihnp4|seismo|ucbvax|harvard|allegra}!uwvax!uwmacc!pwu ** arpa: uwmacc!pwu@uwvax.ARPA ** ** Modified for MicroSoft `C': ** uucp: ihnp4!watmath!watale!broehl Michael Shiels */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos.h> static unsigned orig_env; static unsigned orig_size; unsigned char peekb(seg,offset) short seg,offset; { char far *fptr; /* far pointer (segment + offset) to character */ /* if you forgot to use /ze option when you compile you'll get an ** error here about the '*' */ FP_SEG(fptr) = seg; FP_OFF(fptr) = offset; return *fptr; } void pokeb(seg,offset,what) short seg,offset; char what; { char far *fptr; /* far pointer (segment + offset) to character */ FP_SEG(fptr) = seg; FP_OFF(fptr) = offset; *fptr = what; } unsigned short peekw(seg,offset) short seg,offset; { unsigned far *fptr; /* far pointer (segment + offset) to short */ FP_SEG(fptr) = seg; FP_OFF(fptr) = offset; return *fptr; } static match(s, p, env) char *s, *p; unsigned env; { while (peekb( env, p )) { if( *s != peekb( env, p++ ) ) return 0; /* mismatch ! */ if( *s++ == '=' ) /* hit the = sign */ return 1; /* match up to = */ if( *s == '\0' && peekb( env, p) == '=' ) return 1; } return *s == '\0'; /* if *s is also null, match => return 1 */ } static nextenv(s) char *s; { while (peekb( orig_env, s++ )) ; return s; } static find_orig() { unsigned pspv, header; pspv = _psp; while (pspv != peekw( pspv, 0x0C )) pspv = peekw( pspv, 0x0C ); /* we now take advantage of the undocumented structure of MSDOS memory allocation blocks */ header = pspv - 1; /* the paragraph *before* an allocated block is a header */ if (peekb( header, 0 ) != 'M') /* something's wrong, somewhere */ return -1; if (peekw( header, 1 ) != pspv) /* something else is wrong, somewhere */ return -2; /* Really arcane magic: address of oldest pspv, plus its size, plus 1, happens to point to the DOS environment. I sense evil spirits... */ orig_env = peekw( header, 1 ) + peekw( header, 3 ) + 1; header = orig_env - 1; /* get its memory allocation block */ if (peekb( header, 0 ) != 'M') /* something's wrong, somewhere */ return -3; orig_size = peekw( header, 3 ); /* and get the environment size from it */ return 0; /* all is well with the world */ } static set_var(s) char *s; { short p, src; for (p = 0; peekb( orig_env, p ); p = nextenv(p, orig_env)) if (match(s, p, orig_env)) break; if (peekb( orig_env, p )) { /* it was there; p points to it */ if (peekb( orig_env, src = nextenv(p, orig_env) )) { /* there's stuff after it */ while (peekb( orig_env, src ) || peekb(orig_env, src + 1 )) pokeb( orig_env, p++, peekb( orig_env, src++ ) ); pokeb( orig_env, p++, '\0' ); } /* else p points to the last envvar, which is we;re losing anyway */ } /* p now points to the end of the living environment */ /* the inner + 2 below may not be necessary, but why take the chance? */ if ((p + strlen(s) + 2) / 16 + 1 >= orig_size) return -1; /* no room */ if (src = strcspn(s, '=')) /* is there an '=' in it? */ { while (*s) pokeb( orig_env, p++, *s++ ); pokeb( orig_env, p++, '\0' ); /* terminate the string */ pokeb( orig_env, p++, '\0' ); /* and the environment */ return 0; /* string added */ } else { pokeb( orig_env, p++, '\0' ); /* terminate the string */ pokeb( orig_env, p++, '\0' ); /* and the environment */ return 0; /* string added */ } } putdenv(s) char *s; { if (find_orig()) /* find the original environment */ return -1; return set_var(s); } /* For the record, an MSDOS memory block header looks like this: */ struct _mb { char flag; /* M for normal, Z for last one */ unsigned owner; /* Segment address of owner's pspv */ unsigned size; /* size of the block in paragraphs */ }; @//E*O*F putdenv.c// chmod u=rw,g=r,o=r putdenv.c echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 157 711 4099 putdenv.c !!! wc putdenv.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0 -- Michael A. Shiels clyde-\ decvax-\\ ihnp4-\\\ +++-----> watmath!watale!broehl tektronix-/// ubc-vision-// utzoo-/