PUTDENV, a routine to put a string to the environment
Bernie Roehl
broehl at watale.UUCP
Sun Aug 24 12:10:59 AEST 1986
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 at 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-/
More information about the Comp.sources.unix
mailing list