From: "Edison M. Castro" 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 Precedence: bulk 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 . 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); }