home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / util2 / withlist.lzh / SETENV.ZIP / SETENV.C < prev    next >
Text File  |  1988-05-18  |  6KB  |  235 lines

  1. #include <stdio.h>
  2. #include <dos.h>
  3. #include <dir.h>
  4. #include <string.h>
  5.  
  6. typedef struct {
  7.     char fill1[0x0A];
  8.     int *prev_term_handler;
  9.     int *prev_ctrl_c;
  10.     int *prev_crit_error;
  11.     char fill2[0x16];
  12.     int  envir_seg;
  13.     } psp;
  14.  
  15. typedef struct {
  16.     char  type;
  17.     int   psp_segment;
  18.     int   num_segments;
  19.         char  fill[11];
  20.         char  arena_data;
  21.     } arena;
  22.  
  23. arena * ap;
  24.  
  25. union  REGS  regs;
  26. struct SREGS sregs;
  27.  
  28. #define arena_size 16
  29. #define NORMAL_ATYPE 0x4D
  30. #define LAST_ATYPE   0x5A
  31.  
  32.  
  33. arena * get_next_arena (arena * ap) {
  34.     return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
  35.     }
  36.  
  37. arena * get_first_arena () {
  38. /* return pointer to the first arena.
  39.  * scan memory for a 0x4D on a segment start,
  40.  * see if this points to another two levels of arena
  41.  */
  42.         arena * ap, * ap1;
  43.     int * temp;
  44.         int segment;
  45.         for (segment=0; segment<_CS;  segment++) {
  46.             ap = MK_FP(segment, 0);
  47.             if (   ap->type == NORMAL_ATYPE  &&
  48.                    (ap1=get_next_arena(ap ))->type == NORMAL_ATYPE  &&
  49.                  ( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE  ||
  50.                        ap1->type == LAST_ATYPE) )
  51.                        return(ap);
  52.     }
  53.     return(NULL);
  54. }
  55.  
  56.  
  57. arena * get_arena_of_environment () {
  58. /* to get the arena of first environment block:
  59.    First get segment of COMMAND.COM from segment of previous critical err code.
  60.    Then scan all the arenas for an environment block with a matching PSP
  61.    segment */
  62.  
  63. arena * ap;
  64. psp   * pspp, * pspc;
  65. char  * ad;
  66.  
  67. /* set pspp to psp of this program */
  68. pspp = MK_FP(_psp,0);
  69.  
  70. #ifdef DEBUG
  71. printf("prog psp=%p\n",pspp);
  72. #endif
  73.  
  74. /* set pspc to psp of COMMAND.COM */
  75. pspc = MK_FP( FP_SEG(pspp->prev_crit_error), 0);
  76.  
  77. #ifdef DEBUG
  78. printf("comm.com=%p\n",pspc);
  79. #endif
  80.  
  81. if ( (ap=get_first_arena()) != NULL ) {
  82.     while (ap->type != LAST_ATYPE) {
  83. #ifdef DEBUG
  84.         printf("%p\n",ap);
  85. #endif
  86.                 if (ap->psp_segment == FP_SEG(pspc)) {
  87.                     ad = &ap->arena_data;
  88.             while ( (*ad) &&
  89.                 ((ad-(char *)ap)>>4 < ap->num_segments) ) {
  90.                     if (strnicmp(ad, "COMSPEC=", 8)==0)  return(ap);
  91.                     ad += strlen(ad) + 1;
  92.                     }
  93.         }
  94.         ap = get_next_arena(ap);
  95.     }
  96. } return(NULL); }
  97.  
  98. /*****************************************************************************/
  99.  
  100. char setenv(char * symbol, char * val) {                
  101. int total_size,
  102.     needed_size=0,
  103.     strlength;
  104. char * sp, *op, *envir;
  105. char symb_len=strlen(symbol);
  106. char found=0;
  107.  
  108. strupr(symbol);
  109.  
  110. /* first, can the COMMAND.COM envir block be found ? */
  111. if ( (ap=get_arena_of_environment()) == NULL)
  112.     return(1);
  113.  
  114. /* search to end of the envir block, get sizes */
  115. total_size = 16 * ap->num_segments;
  116. envir = &ap->arena_data;
  117. op=sp=envir;
  118. while (*sp) {
  119.     strlength = strlen(sp)+1;
  120.     if ( *(sp+symb_len)=='='  &&
  121.          strnicmp(sp,symbol,symb_len)==0 )
  122.         found=1;
  123.     else {
  124.         needed_size += strlength;
  125.         if (found) strcpy(op,sp);
  126.         op = &op[strlength];
  127.     }
  128.     sp += strlength;
  129. }
  130. *op=0;
  131. if (strlen(val) > 0) {
  132.     needed_size += 3 + strlen(symbol) + strlen(val);
  133.     if (needed_size > total_size)
  134.         return(1);  /* could mess with environment expansion here */
  135.  
  136.     strcpy(op, symbol); strcat(op, "="); strcat(op, val);
  137.     op += strlen(op)+1;
  138.     *op = 0;
  139. }
  140. return(0);
  141. }
  142.  
  143. /*****************************************************************************/
  144.  
  145. void display_help() {
  146. puts("\nSETENV 1.1  by Richard Marks\n");
  147. puts("     Sets environment variables to a user response (for BAT files)\n");
  148. puts("     SETENV  <envirn vbl name>  <prompt message>\n");
  149. puts("Example:");
  150. puts("     setenv drv ""PLEASE ENTER DRIVE TO USE : "" ");
  151. puts("the message PLEASE ENTER DRIVE TO USE : is displayed on the console,");
  152. puts("the response is set into variable drv for use by the rest of the BAT file\n");
  153. puts("If there is a keyword instead of a <message>, SETENV will fill certain system");
  154. puts("values into the environment variable:\n");
  155. puts("     SETENV  <envirn vbl name>  %cwd  -  get current working directory");
  156. puts("                                %drive-  get default drive");
  157. puts("                                %dosv -  get dos major version");
  158. puts("Use %% to represent a single % in BAT files\n");
  159. puts("Multiple sets of arguments can be supplied:");
  160. puts("     SETENV <vbl> <msg> <vbl> <msg> . . .");
  161. }
  162.  
  163. char get_default_drive () {
  164.     regs.h.ah = 0x19;
  165.     intdos(®s, ®s);
  166.     return (regs.h.al);
  167. }
  168.  
  169. char get_special_param(char *val, char *arg) {
  170. /* plugs the system parmeter specified in the arg into val
  171.    %cwd  = current directory path
  172.    %drive= default drive
  173.    %dosv = dos major version */
  174.  
  175.     if (stricmp(arg,"%CWD")==0) {
  176.         getcwd(val, 128);
  177.  
  178.     } else if (stricmp(arg,"%DRIVE")==0) {
  179.         val[0] = get_default_drive() + 'A';
  180.         val[1] = 0;
  181.  
  182.     } else if (stricmp(arg,"%DOSV")==0) {
  183.         val[0] = _osmajor+'0';
  184.         val[1] = 0;
  185.  
  186.     } else
  187.         return(1);
  188.  
  189.     return(0);
  190. }
  191.  
  192.  
  193. char get_user_input(char *val, char *msg) {
  194. /* solicits user for a value (val) by displaying the message (msg).
  195.    then validates the message using criteria in arg.  Criteria are:
  196.    <null>  no criteria test for now */
  197.  
  198.     do {
  199.        printf("%s",msg);
  200.        gets(val);
  201.        } while (0);
  202.     return(0);
  203.     }
  204.  
  205.  
  206. char main(int argc, char *argv[]) {
  207. int argbase;
  208. char symbol[16], val[128];
  209.  
  210. if (argc<3)
  211.     { display_help(); return(0); }
  212.  
  213. for (argbase=1; argbase<argc;  argbase+=2) {
  214.  
  215.     if ( strlen(argv[argbase])>16 ) goto ERROR_RET;
  216.     strcpy(symbol, argv[argbase]);  strupr(symbol);
  217.  
  218.     if (argv[argbase+1][0]=='%') {
  219.         if ( get_special_param(val, argv[argbase+1]) ) goto ERROR_RET;
  220.     } else {
  221.         if ( get_user_input(val, argv[argbase+1]) ) goto ERROR_RET;
  222.     }
  223.  
  224.     if ( setenv(symbol, val) ) goto ERROR_RET;
  225.     }
  226.  
  227. return(0);
  228.  
  229. ERROR_RET:
  230. #ifdef DEBUG
  231. puts("SETENV failed");
  232. #endif
  233. return(1);
  234. }
  235.