home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / libcs / setpath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-11  |  14.3 KB  |  639 lines

  1. /*
  2.  * Copyright (c) 1990 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
  12.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  13.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT
  14.  * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
  15.  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  17.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * Users of this software agree to return to Carnegie Mellon any
  21.  * improvements or extensions that they make and grant Carnegie the
  22.  * rights to redistribute these changes.
  23.  *
  24.  * Export of this software is permitted only after complying with the
  25.  * regulations of the U.S. Deptartment of Commerce relating to the
  26.  * Export of Technical Data.
  27.  */
  28. /*
  29.  *  setpath --- smart interface for setting path variables
  30.  *
  31.  *  usage:    setpath(paths, cmds, localsyspath, dosuffix, printerrors)
  32.  *        char **paths, **cmds, *localsyspath;
  33.  *        int dosuffix, printerrors;
  34.  *
  35.  *  The 'paths' argument is a list of pointers to path lists of the
  36.  *  form "name=value" where name is the name of the path and value
  37.  *  is a colon separated list of directories.  There can never be
  38.  *  more than MAXDIRS (64) directories in a path.
  39.  *
  40.  *  The 'cmds' argument may be a sequence of any of the following:
  41.  *    -r            reset path to default
  42.  *    -i newpath        insert newpath before localsyspath
  43.  *    -ia oldpath newpath    insert newpath after oldpath
  44.  *    -ib oldpath newpath    insert newpath before oldpath
  45.  *    -i# newpath        insert newpath at position #
  46.  *    -d oldpath        delete oldpath
  47.  *    -d#            delete path at position #
  48.  *    -c oldpath newpath    change oldpath to newpath
  49.  *    -c# newpath        change position # to newpath
  50.  *
  51.  *  The "-i newpath" command is equivilent to "-ib 'localsyspath' newpath".
  52.  *
  53.  *  If 'dosuffix' is true, the appropriate suffix will be added to
  54.  *  all command operands for any system path in 'paths'.
  55.  *
  56.  *  Both of the 'paths' and 'cmds' lists are terminated by a NULL
  57.  *  entry.
  58.  *
  59.  *  if 'printerrors' is true, setpath will printf error diagnostics.
  60.  *
  61.  *  WARNING !!!: Under no circumstances should anyone change this
  62.  *  module without fully understanding the impact on the C shell.
  63.  *  The C shell has it's own malloc and printf routines and this
  64.  *  module was carefully written taking that into account.  Do not
  65.  *  use any stdio routines from this module except printf.
  66.  *
  67.  **********************************************************************
  68.  * HISTORY
  69.  * $Log:    setpath.c,v $
  70.  * Revision 1.4  90/12/11  17:58:44  mja
  71.  *     Add copyright/disclaimer for distribution.
  72.  * 
  73.  * 05-Jun-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
  74.  *    Make all non-entry points static.
  75.  *
  76.  * 30-Apr-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
  77.  *    Added -r switch to reset paths to their default values.
  78.  *
  79.  * 06-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  80.  *    Created from old setpath program for the shell.
  81.  *
  82.  **********************************************************************
  83.  */
  84.  
  85. #include <libc.h>
  86. #include <sys/param.h>
  87. #include <setjmp.h>
  88.  
  89. #define MAXDIRS 64        /* max directories on a path */
  90. #define NULL 0
  91. #define isdigit(c)    ((c) >= '0' && (c) <= '9')
  92.  
  93. static int npaths;        /* # pathlist arguments */
  94.  
  95. static struct pelem {
  96.     struct pelem *pnext;    /* pointer to next path */
  97.     char *pname;        /* name of pathlist */
  98.     char *psuf;            /* suffix for pathlist */
  99.     char *pdef;            /* default for pathlist */
  100.     int pdirs;            /* # directories on each pathlist */
  101.     char *pdir[MAXDIRS];    /* directory names for each pathlist */
  102. } *pathhead = NULL;
  103.  
  104. static struct {
  105.     char *name;
  106.     char *suffix;
  107.     char *defalt;
  108. } syspath[] = {
  109.     "PATH",    "/bin",        ":/usr/ucb:/bin:/usr/bin",
  110.     "CPATH",    "/include",    ":/usr/include",
  111.     "LPATH",    "/lib",        ":/lib:/usr/lib",
  112.     "MPATH",    "/man",        ":/usr/man",
  113.     "EPATH",    "/maclib",    "",
  114.     0, 0, 0
  115. };
  116.  
  117. static int sflag;
  118. static int eflag;
  119. static jmp_buf jmpbuf;
  120.  
  121. #define INVALID { \
  122.     if (eflag) printf("setpath: invalid command '%s'.\n", cmd); \
  123.     freepaths(); \
  124.     return(-1); \
  125. }
  126.  
  127. #define TOOFEW { \
  128.     if (eflag) printf("setpath: insufficient arguments to command '%s'.\n", cmd); \
  129.     freepaths(); \
  130.     return(-1); \
  131. }
  132.  
  133. setpath(paths, cmds, localsyspath, dosuffix, printerrors)
  134. register char **paths, **cmds, *localsyspath;
  135. int dosuffix, printerrors;
  136. {
  137.     register char *cmd, *cmd1, *cmd2;
  138.     register int ncmd;
  139.  
  140.     sflag = dosuffix;
  141.     eflag = printerrors;
  142.     if (initpaths(paths) < 0)
  143.     return(-1);
  144.     if (npaths == 0)
  145.     return(0);
  146.     if (setjmp(jmpbuf) != 0)
  147.     return(-1);
  148.     for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) {
  149.     if (cmd[0] != '-')
  150.         INVALID;
  151.     cmd1 = cmds[ncmd+1];
  152.     cmd2 = cmds[ncmd+2];
  153.     switch (cmd[1]) {
  154.     case 'r':
  155.         if (cmd[2] != '\0')
  156.         INVALID;
  157.         rcmd(localsyspath);
  158.         break;
  159.     case 'i':
  160.         if (cmd[2] == '\0') {
  161.         ncmd++;
  162.         if (cmd1 == NULL) TOOFEW;
  163.         icmd(cmd1, localsyspath);
  164.         } else if (isdigit(cmd[2])) {
  165.         ncmd++;
  166.         if (cmd1 == NULL) TOOFEW;
  167.         incmd(cmd1, atoi(cmd+2));
  168.         } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) {
  169.         INVALID;
  170.         } else {
  171.         ncmd += 2;
  172.         if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
  173.         if (cmd[2] == 'a')
  174.             iacmd(cmd1, cmd2);
  175.         else
  176.             ibcmd(cmd1, cmd2);
  177.         }
  178.         break;
  179.     case 'd':
  180.         if (cmd[2] == '\0') {
  181.         ncmd++;
  182.         if (cmd1 == NULL) TOOFEW;
  183.         dcmd(cmd1);
  184.         } else if (isdigit(cmd[2]))
  185.         dncmd(atoi(cmd+2));
  186.         else {
  187.         INVALID;
  188.         }
  189.         break;
  190.     case 'c':
  191.         if (cmd[2] == '\0') {
  192.         ncmd += 2;
  193.         if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
  194.         ccmd(cmd1, cmd2);
  195.         } else if (isdigit(cmd[2])) {
  196.         ncmd++;
  197.         if (cmd1 == NULL) TOOFEW;
  198.         cncmd(cmd1, atoi(cmd+2));
  199.         } else {
  200.         INVALID;
  201.         }
  202.         break;
  203.     default:
  204.         INVALID;
  205.     }
  206.     }
  207.     if (savepaths(paths) < 0)
  208.     return(-1);
  209.     freepaths();
  210.     return(0);
  211. }
  212.  
  213. static
  214. initpaths(paths)
  215. register char **paths;
  216. {
  217.     register char *path, *value, *p, *q;
  218.     register int i, done;
  219.     register struct pelem *pe, *pathend;
  220.  
  221.     freepaths();
  222.     for (npaths = 0; path = paths[npaths]; npaths++) {
  223.     value = index(path, '=');
  224.     if (value == NULL) {
  225.         if (eflag)
  226.         printf("setpath: value missing in path '%s'\n", path);
  227.         freepaths();
  228.         return(-1);
  229.     }
  230.     *value++ = '\0';
  231.     pe = (struct pelem *)malloc((unsigned)(sizeof(struct pelem)));
  232.     if (pe == NULL) {
  233.         if (eflag)
  234.         printf("setpath: not enough core\n");
  235.         freepaths();
  236.         return(-1);
  237.     }
  238.     bzero(pe, sizeof(struct pelem));
  239.     if (pathhead == NULL)
  240.         pathhead = pathend = pe;
  241.     else {
  242.         pathend->pnext = pe;
  243.         pathend = pe;
  244.     }
  245.     p = salloc(path);
  246.     if (p == NULL) {
  247.         if (eflag)
  248.         printf("setpath: not enough core\n");
  249.         freepaths();
  250.         return(-1);
  251.     }
  252.     pe->pname = p;
  253.     pe->psuf = "";
  254.     pe->pdef = "";
  255.     for (i = 0; syspath[i].name; i++)
  256.         if (strcmp(pe->pname, syspath[i].name) == 0) {
  257.         pe->psuf = syspath[i].suffix;
  258.         pe->pdef = syspath[i].defalt;
  259.         break;
  260.         }
  261.     q = value;
  262.     for (;;) {
  263.         q = skipto(p = q, ":");
  264.         done = (*q == '\0');
  265.         if (!done)
  266.         *q++ = '\0';
  267.         p = salloc(p);
  268.         if (p == NULL) {
  269.         if (eflag)
  270.             printf("setpath: not enough core\n");
  271.         freepaths();
  272.         return(-1);
  273.         }
  274.         pe->pdir[pe->pdirs] = p;
  275.         pe->pdirs++;
  276.         if (done)
  277.         break;
  278.     }
  279.     }
  280.     return(0);
  281. }
  282.  
  283. static
  284. savepaths(paths)
  285. register char **paths;
  286. {
  287.     register char *p, *q;
  288.     register int npath, i, len;
  289.     register struct pelem *pe;
  290.  
  291.     for (npath = 0, pe = pathhead; pe; npath++, pe = pe->pnext) {
  292.     len = strlen(pe->pname) + 1;
  293.     if (pe->pdirs == 0)
  294.         len++;
  295.     else for (i = 0; i < pe->pdirs; i++)
  296.         len += strlen(pe->pdir[i]) + 1;
  297.     p = malloc((unsigned)len);
  298.     if (p == NULL) {
  299.         if (eflag)
  300.         printf("setpath: not enough core\n");
  301.         freepaths();
  302.         return(-1);
  303.     }
  304.     paths[npath] = p;
  305.     for (q = pe->pname; *p = *q; p++, q++);
  306.     *p++ = '=';
  307.     if (pe->pdirs != 0) {
  308.         for (i = 0; i < pe->pdirs; i++) {
  309.         for (q = pe->pdir[i]; *p = *q; p++, q++);
  310.         *p++ = ':';
  311.         }
  312.         p--;
  313.     }
  314.     *p = '\0';
  315.     }
  316.     return(0);
  317. }
  318.  
  319. static
  320. freepaths()
  321. {
  322.     register char *p;
  323.     register int i;
  324.     register struct pelem *pe;
  325.  
  326.     if (npaths == 0 || pathhead == NULL)
  327.     return;
  328.     while (pe = pathhead) {
  329.     if (pe->pname) {
  330.         for (i = 0; i < pe->pdirs; i++) {
  331.         if (pe->pdir[i] == NULL)
  332.             continue;
  333.         p = pe->pdir[i];
  334.         pe->pdir[i] = NULL;
  335.         free(p);
  336.         }
  337.         pe->pdirs = 0;
  338.         p = pe->pname;
  339.         pe->pname = NULL;
  340.         free(p);
  341.     }
  342.     pathhead = pe->pnext;
  343.     free((char *)pe);
  344.     }
  345.     npaths = 0;
  346. }
  347.  
  348. /***********************************************
  349.  ***    R E S E T   A   P A T H N A M E    ***
  350.  ***********************************************/
  351.  
  352. static
  353. rcmd(localsyspath)        /* reset path with localsyspath */
  354. char *localsyspath;
  355. {
  356.     register int n, done;
  357.     register char *new, *p;
  358.     register struct pelem *pe;
  359.     char newbuf[MAXPATHLEN+1];
  360.  
  361.     for (pe = pathhead; pe; pe = pe->pnext) {
  362.     new = newbuf;
  363.     *new = '\0';
  364.     if (localsyspath != NULL) {
  365.         *new = ':';
  366.         strcpy(new + 1, localsyspath);
  367.         strcat(new, pe->psuf);
  368.     }
  369.     strcat(new, pe->pdef);
  370.     for (n = 0; n < pe->pdirs; n++) {
  371.         if (pe->pdir[n] == NULL)
  372.         continue;
  373.         p = pe->pdir[n];
  374.         pe->pdir[n] = NULL;
  375.         free(p);
  376.     }
  377.     pe->pdirs = 0;
  378.     for (;;) {
  379.         new = skipto(p = new, ":");
  380.         done = (*new == '\0');
  381.         if (!done)
  382.         *new++ = '\0';
  383.         p = salloc(p);
  384.         if (p == NULL) {
  385.         if (eflag)
  386.             printf("setpath: not enough core\n");
  387.         freepaths();
  388.         return;
  389.         }
  390.         pe->pdir[pe->pdirs] = p;
  391.         pe->pdirs++;
  392.         if (done)
  393.         break;
  394.     }
  395.     }
  396. }
  397.  
  398. /***********************************************
  399.  ***    I N S E R T   A   P A T H N A M E    ***
  400.  ***********************************************/
  401.  
  402. static
  403. icmd(path, localsyspath)    /* insert path before localsyspath */
  404. char *path, *localsyspath;
  405. {
  406.     register int n;
  407.     register char *new;
  408.     register struct pelem *pe;
  409.     char newbuf[MAXPATHLEN+1];
  410.  
  411.     for (pe = pathhead; pe; pe = pe->pnext) {
  412.     if (sflag)
  413.         new = localsyspath;
  414.     else {
  415.         new = newbuf;
  416.         strcpy(new, localsyspath);
  417.         strcat(new, pe->psuf);
  418.     }
  419.     n = locate(pe, new);
  420.     if (n >= 0)
  421.         insert(pe, n, path);
  422.     else
  423.         insert(pe, 0, path);
  424.     }
  425. }
  426.  
  427. static
  428. iacmd(inpath, path)        /* insert path after inpath */
  429. char *inpath, *path;
  430. {
  431.     register int n;
  432.     register struct pelem *pe;
  433.  
  434.     for (pe = pathhead; pe; pe = pe->pnext) {
  435.     n = locate(pe, inpath);
  436.     if (n >= 0)
  437.         insert(pe, n + 1, path);
  438.     else
  439.         printf("setpath: %s not found in %s\n",
  440.             inpath, pe->pname);
  441.     }
  442. }
  443.  
  444. static
  445. ibcmd(inpath, path)        /* insert path before inpath */
  446. char *inpath, *path;
  447. {
  448.     register int n;
  449.     register struct pelem *pe;
  450.  
  451.     for (pe = pathhead; pe; pe = pe->pnext) {
  452.     n = locate(pe, inpath);
  453.     if (n >= 0)
  454.         insert(pe, n, path);
  455.     else
  456.         printf("setpath: %s not found in %s\n",
  457.             inpath, pe->pname);
  458.     }
  459. }
  460.  
  461. static
  462. incmd(path, n)            /* insert path at position n */
  463. char *path;
  464. int n;
  465. {
  466.     register struct pelem *pe;
  467.  
  468.     for (pe = pathhead; pe; pe = pe->pnext)
  469.     insert(pe, n, path);
  470. }
  471.  
  472. static
  473. insert(pe, loc, key)
  474. register struct pelem *pe;
  475. register int loc;
  476. register char *key;
  477. {
  478.     register int i;
  479.     register char *new;
  480.     char newbuf[2000];
  481.  
  482.     if (sflag) {        /* add suffix */
  483.     new = newbuf;
  484.     strcpy(new, key);
  485.     strcat(new, pe->psuf);
  486.     } else
  487.     new = key;
  488.     new = salloc(new);
  489.     if (new == NULL) {
  490.     if (eflag)
  491.         printf("setpath: not enough core\n");
  492.     freepaths();
  493.     longjmp(jmpbuf, -1);
  494.     }
  495.     for (i = pe->pdirs; i > loc; --i)
  496.     pe->pdir[i] = pe->pdir[i-1];
  497.     if (loc > pe->pdirs)
  498.     loc = pe->pdirs;
  499.     pe->pdir[loc] = new;
  500.     pe->pdirs++;
  501. }
  502.  
  503. /***********************************************
  504.  ***    D E L E T E   A   P A T H N A M E    ***
  505.  ***********************************************/
  506.  
  507. static
  508. dcmd(path)            /* delete path */
  509. char *path;
  510. {
  511.     register int n;
  512.     register struct pelem *pe;
  513.  
  514.     for (pe = pathhead; pe; pe = pe->pnext) {
  515.     n = locate(pe, path);
  516.     if (n >= 0)
  517.         delete(pe, n);
  518.     else
  519.         printf("setpath: %s not found in %s\n",
  520.             path, pe->pname);
  521.     }
  522. }
  523.  
  524. static
  525. dncmd(n)            /* delete at position n */
  526. int n;
  527. {
  528.     register struct pelem *pe;
  529.  
  530.     for (pe = pathhead; pe; pe = pe->pnext) {
  531.     if (n < pe->pdirs)
  532.         delete(pe, n);
  533.     else
  534.         printf("setpath: %d not valid position in %s\n",
  535.             n, pe->pname);
  536.     }
  537. }
  538.  
  539. static
  540. delete(pe, n)
  541. register struct pelem *pe;
  542. int n;
  543. {
  544.     register int d;
  545.  
  546.     free(pe->pdir[n]);
  547.     for (d = n; d < pe->pdirs - 1; d++)
  548.     pe->pdir[d] = pe->pdir[d+1];
  549.     --pe->pdirs;
  550. }
  551.  
  552. /***********************************************
  553.  ***    C H A N G E   A   P A T H N A M E    ***
  554.  ***********************************************/
  555.  
  556. static
  557. ccmd(inpath, path)        /* change inpath to path */
  558. char *inpath, *path;
  559. {
  560.     register int n;
  561.     register struct pelem *pe;
  562.  
  563.     for (pe = pathhead; pe; pe = pe->pnext) {
  564.     n = locate(pe, inpath);
  565.     if (n >= 0)
  566.         change(pe, n, path);
  567.     else
  568.         printf("setpath: %s not found in %s\n",
  569.             inpath, pe->pname);
  570.     }
  571. }
  572.  
  573. static
  574. int cncmd(path, n)        /* change at position n to path */
  575. char *path;
  576. int n;
  577. {
  578.     register struct pelem *pe;
  579.  
  580.     for (pe = pathhead; pe; pe = pe->pnext) {
  581.     if (n < pe->pdirs)
  582.         change(pe, n, path);
  583.     else
  584.         printf("setpath: %d not valid position in %s\n",
  585.             n, pe->pname);
  586.     }
  587. }
  588.  
  589. static
  590. change(pe, loc, key)
  591. register struct pelem *pe;
  592. register int loc;
  593. register char *key;
  594. {
  595.     register char *new;
  596.     char newbuf[MAXPATHLEN+1];
  597.  
  598.     if (sflag) {        /* append suffix */
  599.     new = newbuf;
  600.     strcpy(new, key);
  601.     strcat(new, pe->psuf);
  602.     } else
  603.     new = key;
  604.     new = salloc(new);
  605.     if (new == NULL) {
  606.     if (eflag)
  607.         printf("setpath: not enough core\n");
  608.     freepaths();
  609.     longjmp(jmpbuf, -1);
  610.     }
  611.     free(pe->pdir[loc]);
  612.     pe->pdir[loc] = new;
  613. }
  614.  
  615. /***************************************
  616.  ***    F I N D   P A T H N A M E    ***
  617.  ***************************************/
  618.  
  619. static
  620. int locate(pe, key)
  621. register struct pelem *pe;
  622. register char *key;
  623. {
  624.     register int i;
  625.     register char *realkey;
  626.     char keybuf[MAXPATHLEN+1];
  627.  
  628.     if (sflag) {
  629.     realkey = keybuf;
  630.     strcpy(realkey, key);
  631.     strcat(realkey, pe->psuf);
  632.     } else
  633.     realkey = key;
  634.     for (i = 0; i < pe->pdirs; i++)
  635.     if (strcmp(pe->pdir[i], realkey) == 0)
  636.         break;
  637.     return((i < pe->pdirs) ? i : -1);
  638. }
  639.