home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hall of Fame
/
HallofFameCDROM.cdr
/
util2
/
withlist.lzh
/
SETENV.ZIP
/
SETENV.C
< prev
next >
Wrap
Text File
|
1988-05-18
|
6KB
|
235 lines
#include <stdio.h>
#include <dos.h>
#include <dir.h>
#include <string.h>
typedef struct {
char fill1[0x0A];
int *prev_term_handler;
int *prev_ctrl_c;
int *prev_crit_error;
char fill2[0x16];
int envir_seg;
} psp;
typedef struct {
char type;
int psp_segment;
int num_segments;
char fill[11];
char arena_data;
} arena;
arena * ap;
union REGS regs;
struct SREGS sregs;
#define arena_size 16
#define NORMAL_ATYPE 0x4D
#define LAST_ATYPE 0x5A
arena * get_next_arena (arena * ap) {
return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
}
arena * get_first_arena () {
/* return pointer to the first arena.
* scan memory for a 0x4D on a segment start,
* see if this points to another two levels of arena
*/
arena * ap, * ap1;
int * temp;
int segment;
for (segment=0; segment<_CS; segment++) {
ap = MK_FP(segment, 0);
if ( ap->type == NORMAL_ATYPE &&
(ap1=get_next_arena(ap ))->type == NORMAL_ATYPE &&
( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE ||
ap1->type == LAST_ATYPE) )
return(ap);
}
return(NULL);
}
arena * get_arena_of_environment () {
/* to get the arena of first environment block:
First get segment of COMMAND.COM from segment of previous critical err code.
Then scan all the arenas for an environment block with a matching PSP
segment */
arena * ap;
psp * pspp, * pspc;
char * ad;
/* set pspp to psp of this program */
pspp = MK_FP(_psp,0);
#ifdef DEBUG
printf("prog psp=%p\n",pspp);
#endif
/* set pspc to psp of COMMAND.COM */
pspc = MK_FP( FP_SEG(pspp->prev_crit_error), 0);
#ifdef DEBUG
printf("comm.com=%p\n",pspc);
#endif
if ( (ap=get_first_arena()) != NULL ) {
while (ap->type != LAST_ATYPE) {
#ifdef DEBUG
printf("%p\n",ap);
#endif
if (ap->psp_segment == FP_SEG(pspc)) {
ad = &ap->arena_data;
while ( (*ad) &&
((ad-(char *)ap)>>4 < ap->num_segments) ) {
if (strnicmp(ad, "COMSPEC=", 8)==0) return(ap);
ad += strlen(ad) + 1;
}
}
ap = get_next_arena(ap);
}
} return(NULL); }
/*****************************************************************************/
char setenv(char * symbol, char * val) {
int total_size,
needed_size=0,
strlength;
char * sp, *op, *envir;
char symb_len=strlen(symbol);
char found=0;
strupr(symbol);
/* first, can the COMMAND.COM envir block be found ? */
if ( (ap=get_arena_of_environment()) == NULL)
return(1);
/* search to end of the envir block, get sizes */
total_size = 16 * ap->num_segments;
envir = &ap->arena_data;
op=sp=envir;
while (*sp) {
strlength = strlen(sp)+1;
if ( *(sp+symb_len)=='=' &&
strnicmp(sp,symbol,symb_len)==0 )
found=1;
else {
needed_size += strlength;
if (found) strcpy(op,sp);
op = &op[strlength];
}
sp += strlength;
}
*op=0;
if (strlen(val) > 0) {
needed_size += 3 + strlen(symbol) + strlen(val);
if (needed_size > total_size)
return(1); /* could mess with environment expansion here */
strcpy(op, symbol); strcat(op, "="); strcat(op, val);
op += strlen(op)+1;
*op = 0;
}
return(0);
}
/*****************************************************************************/
void display_help() {
puts("\nSETENV 1.1 by Richard Marks\n");
puts(" Sets environment variables to a user response (for BAT files)\n");
puts(" SETENV <envirn vbl name> <prompt message>\n");
puts("Example:");
puts(" setenv drv ""PLEASE ENTER DRIVE TO USE : "" ");
puts("the message PLEASE ENTER DRIVE TO USE : is displayed on the console,");
puts("the response is set into variable drv for use by the rest of the BAT file\n");
puts("If there is a keyword instead of a <message>, SETENV will fill certain system");
puts("values into the environment variable:\n");
puts(" SETENV <envirn vbl name> %cwd - get current working directory");
puts(" %drive- get default drive");
puts(" %dosv - get dos major version");
puts("Use %% to represent a single % in BAT files\n");
puts("Multiple sets of arguments can be supplied:");
puts(" SETENV <vbl> <msg> <vbl> <msg> . . .");
}
char get_default_drive () {
regs.h.ah = 0x19;
intdos(®s, ®s);
return (regs.h.al);
}
char get_special_param(char *val, char *arg) {
/* plugs the system parmeter specified in the arg into val
%cwd = current directory path
%drive= default drive
%dosv = dos major version */
if (stricmp(arg,"%CWD")==0) {
getcwd(val, 128);
} else if (stricmp(arg,"%DRIVE")==0) {
val[0] = get_default_drive() + 'A';
val[1] = 0;
} else if (stricmp(arg,"%DOSV")==0) {
val[0] = _osmajor+'0';
val[1] = 0;
} else
return(1);
return(0);
}
char get_user_input(char *val, char *msg) {
/* solicits user for a value (val) by displaying the message (msg).
then validates the message using criteria in arg. Criteria are:
<null> no criteria test for now */
do {
printf("%s",msg);
gets(val);
} while (0);
return(0);
}
char main(int argc, char *argv[]) {
int argbase;
char symbol[16], val[128];
if (argc<3)
{ display_help(); return(0); }
for (argbase=1; argbase<argc; argbase+=2) {
if ( strlen(argv[argbase])>16 ) goto ERROR_RET;
strcpy(symbol, argv[argbase]); strupr(symbol);
if (argv[argbase+1][0]=='%') {
if ( get_special_param(val, argv[argbase+1]) ) goto ERROR_RET;
} else {
if ( get_user_input(val, argv[argbase+1]) ) goto ERROR_RET;
}
if ( setenv(symbol, val) ) goto ERROR_RET;
}
return(0);
ERROR_RET:
#ifdef DEBUG
puts("SETENV failed");
#endif
return(1);
}