home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / XP.ZIP / XP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-01-27  |  10.5 KB  |  265 lines

  1. /* Program to change the environment path string. This program only
  2.    changes the environment of the first copy of command.com and not
  3.    subsequent ones (the actual active one). This situation can
  4.    be easily remedied by modifying the assembly function findEnv().
  5.    For further reference on how to find the master environment and
  6.    memory control block, refer to Dr Dobb's Journal #145 Nov, 1988
  7.    "Mapping DOS Memory Allocations", page 56, by Robert J. Moore.
  8.    This program has been tested under PC-DOS 3.2 and compiled with
  9.    Turbo C 2.0, (small/tiny model). Assembly support routines has
  10.    been tested with Turbo Assembler 1.0.
  11.    Written by Goh King Hwa, 19 Dec 1989.
  12.    Bug Fix : 27 Jan 1990
  13. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <dos.h>
  17. #include <dir.h>
  18. #include <alloc.h>
  19. #include <ctype.h>
  20.  
  21. #define TRUE    1
  22. #define FALSE   0
  23.  
  24. /* ------ function prototype for assembly support routines ------- */
  25. /* locate and find the size of the master environment block */
  26. char far *findEnv(unsigned int *);
  27. /* locate a string in the master environment block ("PATH") */
  28. char far *findstr(char far *, char *);
  29. /* locate the existence of a pathname in the path string */
  30. char *findNstr(char *, char *);
  31. /* check for the actual presence of a drive */
  32. int drivePresent(int);
  33. /* move or shuffle data in the master environment block */
  34. void movLblk(char far *, char far *, int);
  35. /* copy a string into the master environment block */
  36. void strXcpy(char far *, char *);
  37.  
  38. /* check for the physical presence of a pathname */
  39. int pathPresent(char *);
  40. void exit(int);
  41.  
  42. /* global variables */
  43. char far *envAddr;     /* the starting address of the master environment */
  44. unsigned int envSize;  /* the size of the master environment */
  45. char *path;            /* scrap string for working on the path */
  46.  
  47. main(int argc, char** argv)
  48. {
  49.     register int i;
  50.     unsigned int envUsed = 0; /* size of environment space actually used */
  51.     char *endOfPath;          /* trace the end of variable path */
  52.     char far *pathEStart = 0; /* start of path string in environment */
  53.     char far *pathEEnd = 0;   /* end of path string in environment   */
  54.     int pathNotFound = TRUE;  /* did we find "PATH=" in the environment? */
  55.     int fFirstPath = FALSE;   /* the very first pathname to be added */
  56.     int fPathChange = FALSE;  /* indicate that path has been changed */
  57.     int movSize;              /* size of path string if present */
  58.     char *scrap, *hit;
  59.     int pLen;
  60.  
  61.     /* make sure we have sufficient number of parameters */
  62.     if (argc < 3)
  63.     {
  64.         printf("xp a [pathname] [pathname]...\t"
  65.                "Add new path to environment.\n"
  66.                "xp r [pathname] [pathname]...\t"
  67.                "Delete path from environment.\n");
  68.         exit(1);
  69.     }
  70.  
  71.     /* check to see the correct option is used */
  72.     i = *argv[1] = toupper(*argv[1]);
  73.     if (i != 'A' && i != 'D' && i != 'R')
  74.     {
  75.         printf("Illegal options [Use a/r/d].\n");
  76.         exit(2);
  77.     }
  78.  
  79.     /* convert subsequent parameters (pathnames) entered into upcase
  80.        and strip of any terminating '\' character */
  81.     for (i = 2; i < argc; i++)
  82.     {
  83.         for (path = argv[i]; *path; path++)
  84.             *path = toupper(*path);        /* find the end of string  */
  85.         --path;                            /* go back one character */
  86.         /* dump the last '\' so that findfirst can work */
  87.         if (*path == '\\') *path = 0;      /* does string end with '\' ? */
  88.     }
  89.  
  90.     /* locate the master environment address and size */
  91.     envAddr = findEnv(&envSize);
  92.  
  93.     /* allocate enough scrap space to work on the path string */
  94.     path = malloc(envSize);
  95.     if (!path)
  96.     {
  97.         printf("Not enough memory!\n");
  98.         exit(3);
  99.     }
  100.  
  101.     /* The environment is arranged as a series of ASCIIZ strings.
  102.        It is terminated by a null string. The next section of code
  103.        will attempt to do a couple of things.
  104.        1. Find the path string in the master environment (if it is
  105.           present) and copy it into the path variable for easily
  106.           manipulation later on.
  107.        2. Indicate the presence of a path string by pathNotFound.
  108.        3. Count the number of bytes actually used in the environment.
  109.        4. Note down the starting and ending address [pathEStart, pathEEnd]
  110.           of the path string in the master environment (if it is present).
  111.        5. Make sure path is in uppercase.
  112.     */
  113.     endOfPath = path;   /* trace the end of path variable */
  114.     /* we will exit when we hit 2 consecutive zeros */
  115.     while(envAddr[envUsed])
  116.     {
  117.         /* at beginning of each environment string, check to see
  118.            whether it's the "PATH=" string we want */
  119.         if (pathNotFound && (pathEStart=findstr(&envAddr[envUsed],"PATH")))
  120.         {
  121.             pathNotFound = FALSE;     /* indicate "PATH= has been found */
  122.             while (envAddr[envUsed])  /* copy it into path */
  123.                 *endOfPath++ = envAddr[envUsed++];
  124.             pathEEnd = &envAddr[envUsed+1];
  125.         }
  126.         while (envAddr[envUsed++]);   /* goto the next environment string */
  127.     }
  128.     /* If "PATH=" is found, movSize = length of the path string
  129.        else movSize = size of the master environment - 1 */
  130.     movSize = (unsigned) (&envAddr[envUsed] - pathEEnd);
  131.     envUsed++;       /* remember to count the last zero */
  132.     *endOfPath = 0;  /* close the string */
  133.     strupr(path);    /* convert the path into uppercase */
  134.  
  135.     /* ------- this is the path adding part --------- */
  136.     if (*argv[1] == 'A')
  137.     {
  138.         /* if there is no "PATH=" in the environment, we must
  139.            add in ourselves */
  140.         if (pathNotFound)
  141.         {
  142.             *endOfPath++ = 'P'; *endOfPath++ = 'A';
  143.             *endOfPath++ = 'T'; *endOfPath++ = 'H';
  144.             *endOfPath++ = '='; *endOfPath = 0;
  145.             fFirstPath = TRUE;
  146.         }
  147.  
  148.         /* next block of code reads in the pathnames entered
  149.            on the command-line, verify it and start building
  150.            the environment path string */
  151.         for (i = 2; i < argc; i++)   /* for each pathname entered */
  152.         {
  153.             if (findNstr(path,argv[i]))
  154.                 printf("%s is already defined.\n", argv[i]);
  155.             else if (!pathPresent(argv[i]))
  156.                 printf("%s does not exist.\n", argv[i]);
  157.             else
  158.             {
  159.                 /* find the length of the path, plus 1 for ';' added */
  160.                 pLen = strlen(argv[i]) + 1;
  161.                 /* make sure the path will fit the environment */
  162.                 if (pLen + envUsed > envSize)
  163.                     printf("%s is too large for the environment space.\n",
  164.                             argv[i]);
  165.                 else  /* all else checks out, so add to path */
  166.                 {
  167.                     fPathChange = TRUE;  /* flag path has been changed */
  168.                     envUsed += pLen;     /* indicate the amount used   */
  169.                     scrap = argv[i];
  170.                     if (fFirstPath)          /* the very first pathname */
  171.                         fFirstPath = FALSE;  /* no need to add a ';'    */
  172.                     else
  173.                         *endOfPath++ = ';';  /* add ';' to path         */
  174.                     while (*scrap)    /* copy pathname into variable path */
  175.                         *endOfPath++ = *scrap++;
  176.                }
  177.             }
  178.         }
  179.         *endOfPath = 0;  /* end the path string */
  180.  
  181.         /* if there is any changes in path, the path string
  182.            is then copied into the actual environment space */
  183.         if (fPathChange)
  184.         {
  185.             /* did we find the "PATH=" in the environment? */
  186.             if (pathNotFound)
  187.                 /* no, copy path to the end of the environment */
  188.                 pathEStart = envAddr + movSize;
  189.             else
  190.             {
  191.                 /* yes, destroy current path string in environment */
  192.                 movLblk(pathEStart, pathEEnd, movSize);
  193.                 /* get ready to copy path to the end of the environment */
  194.                 pathEStart += movSize;
  195.             }
  196.  
  197.             strXcpy(pathEStart,path);
  198.             printf("\nEnvironment has been changed.\n");
  199.         }
  200.     }
  201.  
  202.     /* -------- this is the path deletion part ---------- */
  203.     if (*argv[1] == 'D' || *argv[1] == 'R')
  204.     {
  205.         if (pathNotFound)    /* if the no path has been defined before */
  206.         {
  207.             printf("There is no path to delete.\n");
  208.             exit(4);
  209.         }
  210.  
  211.         /* next block of code reads in the pathname from the
  212.            command-line, verify it and delete the unwanted
  213.            pathname from path */
  214.         for (i = 2; i < argc; i++)   /* for each pathname entered */
  215.         {
  216.             if (!(hit = findNstr(path,argv[i])))
  217.                 printf("%s has not been defined.\n", argv[i]);
  218.             else
  219.             {
  220.                 scrap = hit;  /* start from the current match point */
  221.                 while (*scrap != 0 && *scrap != ';')
  222.                     scrap++;  /* find the start of the next pathname */
  223.                 /* pathname is sandwiched between 2 pathnames */
  224.                 if (*scrap == ';') scrap++;
  225.                 /* pathname is found right at the end */
  226.                 if (*scrap == 0 && *(hit-1) == ';') hit--;
  227.                 strcpy(hit,scrap);  /* overlay the unwanted path */
  228.                 fPathChange = TRUE;
  229.             }
  230.         }
  231.  
  232.         /* if there is any changes in path, the path string
  233.            is then copied into the actual environment space */
  234.         if (fPathChange)
  235.         {
  236.             /* rub out the existence of the old path from the environment */
  237.             movLblk(pathEStart, pathEEnd, movSize);
  238.             pathEStart += movSize;
  239.  
  240.             if (path[5] == 0)    /* did we delete all the pathnames? */
  241.                 *pathEStart = 0; /* yes, just terminated the environment */
  242.             else
  243.                 strXcpy(pathEStart,path); /* no, copy in the new path */
  244.  
  245.             printf("\nEnvironment has been changed.\n");
  246.         }
  247.     }
  248. }
  249.  
  250. /* check the physical existence of a pathname */
  251. int pathPresent(char *path)
  252. {
  253.     struct ffblk ffblk;
  254.  
  255.     /* drive specification: check to see whether drive is present */
  256.     if (path[1] == ':' && path[2] == 0)
  257.         return(drivePresent(path[0]-'A'));
  258.  
  259.     /* find the path, must be a directory type */
  260.     if (!findfirst(path,&ffblk,FA_DIREC) && (ffblk.ff_attrib & FA_DIREC))
  261.         return(TRUE);
  262.     else
  263.         return(FALSE);
  264. }
  265.