home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / pcmag / vol7n14.arc / PATHSUB.C < prev    next >
C/C++ Source or Header  |  1988-06-30  |  12KB  |  342 lines

  1. /*- PATHSUB - Substitute strings in environment variables (default: PATH) 
  2.  
  3.      Usage: PATHSUB [/var] pat sub 
  4.  
  5.      PATHSUB will substitute the 1st occurrance of 'pat' in the environment 
  6.      variable 'var' with the replacement string 'sub'.  Both 'pat' and 'sub' 
  7.      are required.  The default environment variable is "PATH". 
  8.  
  9.      If 'var' is specified, it is converted to uppercase.  Both 'pat' and 
  10.      'sub' are case sensitive. 
  11.  
  12.      There are two special values for the parameter 'pat'.  If 'pat' is "^" 
  13.      then 'sub' will be placed at the head of the environment variable (after 
  14.      the '=' seperating the variable name from the value).  If 'pat' is "$" 
  15.      then 'sub' will be placed at the end of the environment.  Note that 
  16.      this is not full regular expression matching.  The pattern "^C:\BIN" 
  17.      will NOT attempt to find "C:\BIN" at the head of the path, but will 
  18.      search for "^C:\BIN" anywhere in the path. 
  19.  
  20.      If you wish to delete something from the path, overspecify the pattern 
  21.      and make the replacement match the extra e.g.: 
  22.  
  23.           PATHSUB ;C:\UTILS; ; 
  24.  
  25.      Exit codes: 
  26.           4 - Program could not run, not enough parameters 
  27.           3 - Program could not locate environment variable 
  28.           2 - Pattern not found in environment variable 
  29.           1 - Program could not update environment, substitution too big 
  30.           0 - Success 
  31.  
  32. */ 
  33.  
  34. #include <stdio.h> 
  35. #include <stdlib.h> 
  36. #include <process.h> 
  37. #include <memory.h> 
  38. #include <ctype.h> 
  39. #include <dos.h> 
  40. #include <string.h> 
  41.  
  42. #ifndef TRUE 
  43. #define TRUE 1 
  44. #endif 
  45.  
  46. #ifndef FALSE 
  47. #define FALSE 0 
  48. #endif 
  49.  
  50. #ifndef NULL 
  51. #define NULL 0 
  52. #endif 
  53.  
  54. #define Lastchar(string) string[strlen(string)-1] 
  55.  
  56. #define DEBUG       TRUE 
  57. #define VERBOSE     TRUE 
  58.  
  59. #define ENV_OFF 0x2C          /* environment segment */ 
  60. #define PPSP_OFF 0x16         /* parent PSP */ 
  61.      /* PSP of copy of COMMAND.COM that invoked current process */ 
  62. #define RPSP_OFF 0x10 
  63.  
  64. /* Maximum memory block we will try to deal with is 255 Paragraphs long */ 
  65. #define MAXLEN 0xFF0 
  66.  
  67. extern unsigned _psp;         /* from MSC: PSP segment for this task */ 
  68.  
  69. unsigned _rpsp;               /* "root" PSP segment */ 
  70. unsigned _cpsp;               /* current PSP segment */ 
  71. unsigned _env_seg;            /* environment segment */ 
  72. unsigned _ctrl_seg;           /* memory control block segment */ 
  73. unsigned _mem_seg;            /* memory block segment */ 
  74.  
  75. struct _ctrl_block 
  76.      char type;          /* 'M' more memory follows, 'Z' zero more blocks */ 
  77.      unsigned owner;     /* PSP of task which owns this memory */ 
  78.      unsigned length;    /* # of segments in this block of memory */ 
  79. } ctrl_block; 
  80.  
  81. unsigned char mem_block[MAXLEN]; 
  82.  
  83. main(argc, argv) 
  84. int argc; 
  85. char *argv[]; 
  86.      unsigned _showds(); 
  87.  
  88.      static char cmdpath[256]; 
  89.      static char path[256]; 
  90.      static char target[100] = { "PATH=" }; 
  91.      char *comspec,*pos; 
  92.      int i, done; 
  93.      int ppos, off; 
  94.      unsigned ds; 
  95.      int firstarg; 
  96.  
  97.      firstarg=1; 
  98.  
  99.      /* if alternate environment var specified */ 
  100.      if (argv[firstarg][0] == '/') 
  101.      { 
  102.           strcpy(target, argv[firstarg++]+1); /* copy from arg (after '/') */ 
  103.           strcat(target, "=");                /* append an '=' */ 
  104.           strupr(target);                     /* convert to uppercase */ 
  105.      } 
  106.  
  107.      if (argc < firstarg+2) 
  108.      { 
  109.           fprintf(stderr, "\nPATHSUB: Usage - PATHSUB [/var] pat sub"); 
  110.           exit(4); 
  111.      } 
  112.  
  113.      ds = _showds();               /* get our data segment */ 
  114.      _rpsp = _psp;                 /* start w/ our own PSP segment */ 
  115.      _cpsp = _rpsp ^ 0xFFFF;       /* Dummy value to start with */ 
  116.  
  117.      while (_cpsp != _rpsp)        /* while haven't found PSP of 1st COMMAND */ 
  118.      { 
  119.           _cpsp = _rpsp;           /* up another layer */ 
  120.                                    /* get "root" PSP segment */ 
  121.           movedata(_cpsp, RPSP_OFF, ds, (unsigned)&_rpsp, 2); 
  122.      } 
  123.  
  124.           /* get the memory control block from the root PSP */ 
  125.      _mem_seg = _cpsp;             /* start with the PSP segment */ 
  126.      _ctrl_seg = _cpsp - 1;        /* and back up by one segment */ 
  127.  
  128.           /* copy it to where we can use it */ 
  129.      movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block, sizeof(ctrl_block)); 
  130.  
  131.      done = FALSE; 
  132.      ppos = -1; 
  133.      while (!done) 
  134.      { 
  135.                /* find next control block */ 
  136.           _ctrl_seg = _mem_seg + ctrl_block.length; 
  137.                /* & next block of memory */ 
  138.           _mem_seg = _ctrl_seg + 1; 
  139.                /* load control block */ 
  140.           movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block.type, 5); 
  141.  
  142.           done = (ctrl_block.type != 'M'); 
  143.           if(!done) 
  144.                     /* examine mem block, if not too big */ 
  145.           if(ctrl_block.length < MAXLEN) 
  146.              { 
  147.                      /* Load the block */ 
  148.                movedata(_mem_seg, 0, ds, (unsigned)mem_block, 
  149.                               ctrl_block.length*16); 
  150.  
  151.                     /* find the first occurance of our pattern in the block */ 
  152.                     /* if it does not appear, result will be -1 */ 
  153.  
  154.                     /* search the block      */ 
  155.                     for(ppos = off = 0;  !done && off != -1; ppos++) 
  156.                     { 
  157.                          /* if found */ 
  158.                          if( (off = memsrch(&mem_block[ppos], target, 
  159.                               (ctrl_block.length*16)-off )) != -1) 
  160.                          { 
  161.                               ppos+=off; 
  162.                                                        /* and if valid */ 
  163.                               if(ppos == 0 || mem_block[ppos-1] == NULL) 
  164.                               { 
  165.                                    done = TRUE;   /* set to break main loop */ 
  166.                                    break;         /* get out of for loop */ 
  167.                               } 
  168.                          } 
  169.                     } 
  170.                } /* end: look through this memory block */ 
  171.      } /* end: look through all memory blocks */ 
  172.  
  173.      if((ppos == -1) || (ctrl_block.type != 'M')) 
  174.      { 
  175.           Lastchar(target); 
  176.           fprintf(stderr, 
  177.                "\nPATHSUB: Could not locate environment variable [%s].", 
  178.                 target); 
  179.           exit(3); 
  180.      } 
  181.  
  182.      strcpy(path, &mem_block[ppos]);    /* copy our current "PATH=" string */ 
  183.  
  184.      if(!strcmp(argv[firstarg],"^"))              /* Insert at head of path */ 
  185.           sprintf(cmdpath,"%s%s%s", target, argv[firstarg+1], 
  186.                     path+strlen(target)); 
  187.      else if (!strcmp(argv[firstarg], "$"))  /* Append to tail of path */ 
  188.           sprintf(cmdpath, "%s%s",path,argv[firstarg+1]); 
  189.      else                                         /* Substitute into path */ 
  190.      { 
  191.           strcpy(cmdpath,path); 
  192.           i = strsub(cmdpath+strlen(target), argv[firstarg], 
  193.                          argv[firstarg+1], 1); 
  194.           if(i == 0) 
  195.           { 
  196.                target[strlen(target)-1] = NULL; 
  197.                fprintf(stderr, 
  198.           "PATHSUB: pattern [%s] not found in environment variable [%s].\n", 
  199.                argv[firstarg], target); 
  200.                exit(2); 
  201.           } 
  202.      } 
  203.  
  204.           /* Remove old entry FROM OUR COPY of environment block */ 
  205.      delete(mem_block, ppos); 
  206.  
  207.      /* Make new entry in OUR COPY of environment block.  If the addition */ 
  208.      /* fits, THEN copy entire block back where it came from */ 
  209.      if(append(mem_block, cmdpath, ctrl_block.length*16)) 
  210.      { 
  211.           movedata(ds, (unsigned)mem_block, _mem_seg, 0, ctrl_block.length*16); 
  212.           exit(0); 
  213.      } 
  214.  
  215.           /* if it did not get successfully added, just leave */ 
  216.      fprintf(stderr, 
  217.           "PATHSUB: Not enough environment space -- environment unchanged\n"); 
  218.      exit(1); 
  219.  
  220. /* ===================== String handling routines ========================= */ 
  221. /*  Purpose:  this routine will substitute up to "num" occurances of the     * 
  222. *            pattern "pat" in the string "s" with the replacement "sub".     * 
  223. *            the actual number of substitutions performed is returned.       * 
  224. *            if "num" is -1, then all occurances of "pat" are changed.       * 
  225. */ 
  226. int strsub(s, pat, sub, num) 
  227. char *s, *pat, *sub; 
  228. int num; 
  229.      int     idx, i, ii, count, off; 
  230.      char    news[161]; 
  231.  
  232.      for( count = off = 0; TRUE; count++) 
  233.      { 
  234.                /* we only need to check string past end of last substitution */ 
  235.           idx = stridx(&s[off], pat); 
  236.                /* if count is over the limit and limit specified, 
  237.                      or pattern not found */ 
  238.           if( ((count >= num) && (num != -1)) || (idx == -1)) 
  239.                return count+1; 
  240.  
  241.                /* idx + off is now the offset to the beginning of pat in s */ 
  242.                /* copy from up to pattern in string to local buffer */ 
  243.      for (i = off; i < idx+off; i++)  /* only need to cp from last chg */ 
  244.                news[i] = s[i]; 
  245.  
  246.                /* ad the substitution   */ 
  247.           for (ii = 0; ii < strlen(sub); ii++) 
  248.                news[i+ii] = sub[ii]; 
  249.  
  250.                 /* finish copying the rest of the string */ 
  251.           ii = idx+off + strlen(sub);             /* where src picks up */ 
  252.           i = idx+off + strlen(pat);              /* where need end on dest */ 
  253.           off = ii;                               /* remember for next cycle */ 
  254.           while(s[i]) 
  255.                news[ii++] = s[i++]; 
  256.           news[ii] = NULL; 
  257.           strcpy(s, news); 
  258.      } 
  259.      return count;  /* return number of subs done */ 
  260.  
  261.  
  262. int  stridx(s,p) 
  263. char *s,*p; 
  264.      char *p2; 
  265.  
  266.      if( p2 = strstr(s,p))                   /* if p found in s,      */ 
  267.           return p2-s;                       /* return offset into s  */ 
  268.      return -1;                              /* else return -1        */ 
  269.  
  270.  
  271. unsigned _showds() 
  272.      struct SREGS segregs; 
  273.  
  274.      segread(&segregs);                      /* read the segment registers */ 
  275.      return(segregs.ds);                     /* return DS */ 
  276.  
  277. int memsrch(mem,str,len) 
  278. char *mem, *str; 
  279. int len; 
  280.      int       i, j; 
  281.  
  282.      len -= strlen(str); 
  283.                                              /* for each character of mem */ 
  284.      for( j = 0; j <= len; j++) 
  285.      { 
  286.                                              /* compare the following chars */ 
  287.           for( i = 0 ; (mem[j+i] == str[i]) && str[i]; i++); 
  288.           if(!str[i])                        /* if at end of string */ 
  289.                return j;                     /* return the index */ 
  290.      } 
  291.      return -1; 
  292.  
  293. delete(block, index) 
  294. char *block; 
  295. int index; 
  296.      int size, end; 
  297.  
  298.           /* find end of environment (2nd of 2 NULLs in a row) */ 
  299.      for( end = 1; block[end-1] || block[end]; end++); 
  300.  
  301.           /* get length of entry being deleted */ 
  302.      size = strlen(&block[index])+1; 
  303.  
  304.           /* shift the remaining block down on top of string being deleted */ 
  305.      for(index += size; index <= end; index++) 
  306.           block[index-size] = block[index]; 
  307.  
  308. append(block, string, maxlen) 
  309. char *block, *string; 
  310. unsigned int maxlen; 
  311.      int end, size, i; 
  312.  
  313.                               /* find starting point for string to be added */ 
  314.      for( end = 1; block[end-1] || block[end]; end++); 
  315.  
  316.      size = strlen(string) + 2;    /* measure length of new string + 2 NULLs */ 
  317.  
  318.           /* check to see where last (proposed) byte falls in block */ 
  319.      if((end+size) > maxlen) 
  320.           return(FALSE); 
  321.                                    /* copy it -- we have enough room */ 
  322.      for( i = 0; string[i]; block[end++] = string[i++]); 
  323.      block[end++] = NULL; 
  324.      block[end++] = NULL; 
  325.  
  326.      return TRUE; 
  327.