Category : Batch File Utilities - mostly for DOS
Archive   : RBSETENV.ZIP
Filename : ENVFUNCS.C
* envfuncs.c - manipulate parent environment
*
* Author: R. Brittain 4/11/90
*
* This code placed in the public domain
*
*/
#include
#include
#include
#include
#include
#define MEMCHECK(x) if ((x) == NULL) fatal("Out of memory",1)
#ifdef UNIXCOMPAT
#define strupr(x) (x) /* disable upper-casing env-vars */
#endif
/* prototypes */
int get_env_index(char *var, char **env_var);
int getenvseg(unsigned *envseg);
unsigned get_env_var(unsigned env_addr, char ***env_var, int *count);
void put_env_var(unsigned env_addr, unsigned seglen, char **env_var);
void fatal(char *msg, int status);
extern unsigned _psp;
int get_env_index(char *var, char **env_var)
{
/*
* Find the index into the env_var array of the variable . If not
* found, returns the index of the terminating null entry
*/
register int i;
char *temp;
MEMCHECK(temp = (char *)malloc(strlen(var)+2)) ;
strcpy( temp, var);
strupr(strcat(temp,"="));
for( i = 0; env_var[i]; i++ ) {
if(strstr(env_var[i], temp) == env_var[i]) break;
}
free(temp);
return(i);
}
int getenvseg(unsigned *envseg )
{
/*
* Try to locate the parent environment and fill in the segment address
* This routine has some OS version dependencies
* Returns 1 if environment found
* 0 if environment not found
*/
unsigned ppsp;
union REGS regs;
int status ;
regs.x.ax = 0xD44D; /* 4dos signature value */
regs.x.bx = 0;
int86(0x2F, ®s, ®s); /* TSR multiplex interrput */
ppsp = regs.x.cx; /* psp of immediate parent shell */
if( regs.x.ax == 0x44dd && ppsp == *(unsigned far *)MK_FP(_psp,0x16) ) {
/*
* good, we are running 4dos - AND it is our parent
* in this case we don't care about dos version
*/
*envseg = *(unsigned far *)MK_FP(ppsp,0x2C);
} else {
/*
* Follow the pointers back to our parent psp and from there get the
* parent environment segment address
* With early command.com (pre 3.3) the lowest level shell did not fill
* in the environment segment (it is 0) but we can still find the
* environment since it always follows the lowest level shell directly
*/
ppsp = *(unsigned far *)MK_FP(_psp,0x16);
*envseg = *(unsigned far *)MK_FP(ppsp,0x2C);
if ((*envseg == 0) &&
(_osmajor <= 2 || (_osmajor == 3 && _osminor <= 20))) {
/*
* we have the pre 3.3 master command.com - have to assume that the
* environment segment directly follows the program segment
* so get the length from the MCB and add it to ppsp
*/
*envseg = ppsp + *(unsigned far *)MK_FP(ppsp - 1, 3) + 1;
}
}
/*
* Verify that the owner of the envseg matches the ppsp we got above
* - just to be a little paranoid
*/
if ( *(unsigned far *)MK_FP((*envseg)-1, 1) != ppsp) {
*envseg = 0 ; /* something wrong 🙁 */
status = 0;
} else {
status = 1 ;
}
return(status);
}
unsigned get_env_var(unsigned env_addr, char ***env_var, int *count)
{
/*
* Copy the parent environment from the segment address given in env_addr, into
* the memory block pointed to by env_blk.
* Extract pointers to the start of each variable and build array env_var.
* Return the length of the environment block, (bytes, always a multiple of 16)
*/
static char *env_blk;
unsigned i, len, offset;
unsigned seglen;
seglen = *(unsigned far *)MK_FP(env_addr - 1, 3) * 16;
if ((env_blk = (char *)malloc(seglen)) == (char *)NULL)
fatal ("Cannot allocate memory for environment block", 5);
movedata(env_addr, 0, _DS, (unsigned)&env_blk[0], seglen);
/*
* make one pass through, counting variables, and allocate space for the
* env_var array. Allow for two extra entries - one to add a new variable
* and a terminating null.
*/
i = 0; offset = 0;
do {
offset += strlen(env_blk+offset) + 1;
i++;
} while(*(env_blk+offset));
MEMCHECK (*env_var = (char **)malloc((i+2)*sizeof(char **))) ;
*count = i;
/* load pointers to each of the strings in the array env_var[] */
i = 0; offset = 0;
do {
len = strlen(env_blk+offset);
(*env_var)[i] = env_blk+offset;
offset += len+1;
i++;
} while(*(env_blk+offset));
(*env_var)[i] = NULL; /* terminate with an extra null */
return (seglen);
}
void put_env_var(unsigned env_addr, unsigned seglen, char **env_var)
{
/*
* Copy the modified environment from the allocated data area, using the
* env_var array of pointers, into the memory block pointed to by env_addr.
*/
char *var_addr;
unsigned offset, len, i;
unsigned zero = 0;
/*
* Cycle through once to test for environment overflow. If overflow,
* nothing is copied to the old environment block
*/
for( i=0, offset=0, len=0; env_var[i]; offset+=len, i++) {
len = strlen(env_var[i]) + 1;
if (offset+len >= seglen-2) /* overflow */
fatal ("Environment overflow - not modified\n",4);
}
/*
* Now actually copy the strings
*/
for( i=0, offset=0, len=0; env_var[i]; offset+=len, i++) {
len = strlen(env_var[i]) + 1;
if (len == 1) {
/* this entry was null - skip it */
len = 0;
continue;
}
var_addr = env_var[i];
movedata(_DS, (unsigned)var_addr, env_addr, offset, len);
}
/* stuff a zero word at the end of the environment block */
movedata(_DS, (unsigned)&zero, env_addr, offset, sizeof(unsigned));
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/