Mail Archives: djgpp/1998/01/05/14:49:22
From: | "Edison M. Castro" <edison_castro AT ml DOT com>
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | Changing Parent environment
|
Date: | Mon, 5 Jan 1998 14:14:35 -0500
|
Organization: | Merrill Lynch
|
Lines: | 199
|
Message-ID: | <68rbl0$prq$1@news.ml.com>
|
NNTP-Posting-Host: | 165.177.116.168
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
I have some functions written in visual C that change the parent environment
of a program, it make use of some source code found previously in the
internet . I would like for someone to translate it to DJGPP because of its
use of _MK_FP and other Visual C macros
int get_env_index(char *var, char **env_var)
{
/*
* Find the index into the env_var array of the variable <var>. 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);
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);
}
/* Getting enviroment variable */
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;
struct _SREGS segregs;
unsigned _DS;
_segread( &segregs );
_DS = segregs.ds;
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;
struct _SREGS segregs;
unsigned _DS;
_segread( &segregs );
_DS = segregs.ds;
/*
* 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));
}
/* Setting enviroment variable */
int set_env_var(char * variable, char * val)
{
unsigned env_addr, seglen;
int index, i, count;
char *value, **env_var;
if ( !getenvseg(&env_addr))
fatal ("Cannot locate environment\n",2);
seglen = get_env_var( env_addr, &env_var, &count );
index = get_env_index( variable, env_var );
if (index == count) env_var[index+1] = (char *)NULL;
/* set the value of the variable to the rest of the arguments */
value = (char *) malloc(strlen(variable) + 2);
strcpy(value,variable);
strcat(value,"=");
value = (char *) realloc(value, strlen(value) + strlen(val) + 2);
strcat(value,val);
strcpy(value-1,'\0');
env_var[index] = value;
put_env_var(env_addr, seglen, env_var);
return(0);
}
- Raw text -