home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / ma.setp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  14.2 KB  |  614 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.  *
  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. #include "sh.h"
  85. RCSID("$Id: ma.setp.c,v 1.7 1992/11/20 08:56:38 christos Exp $")
  86.  
  87. #ifdef MACH
  88.  
  89. #define MAXDIRS 64        /* max directories on a path */
  90. #ifndef NULL
  91. # define NULL 0
  92. #endif
  93.  
  94. static int npaths;        /* # pathlist arguments */
  95.  
  96. static struct pelem {
  97.     struct pelem *pnext;    /* pointer to next path */
  98.     char *pname;        /* name of pathlist */
  99.     char *psuf;            /* suffix for pathlist */
  100.     char *pdef;            /* default for pathlist */
  101.     int pdirs;            /* # directories on each pathlist */
  102.     char *pdir[MAXDIRS];    /* directory names for each pathlist */
  103. } *pathhead = NULL;
  104.  
  105. static struct {
  106.     char *name;
  107.     char *suffix;
  108.     char *defalt;
  109. } syspath[] = {
  110.     "PATH",    "/bin",        ":/usr/ucb:/bin:/usr/bin",
  111.     "CPATH",    "/include",    ":/usr/include",
  112.     "LPATH",    "/lib",        ":/lib:/usr/lib",
  113.     "MPATH",    "/man",        ":/usr/man",
  114.     "EPATH",    "/maclib",    "",
  115.     0, 0, 0
  116. };
  117.  
  118. static int sflag;
  119. static int eflag;
  120.  
  121. #define INVALID { \
  122.     if (eflag) xprintf("setpath: invalid command '%s'.\n", cmd); \
  123.     freepaths(); \
  124.     return(-1); \
  125. }
  126.  
  127. #define TOOFEW { \
  128.     if (eflag) xprintf("setpath: insufficient arguments to command '%s'.\n", cmd); \
  129.     freepaths(); \
  130.     return(-1); \
  131. }
  132.  
  133. static int initpaths    __P((char **));
  134. static void savepaths    __P((char **));
  135. static void freepaths    __P((void));
  136. static void rcmd    __P((char *));
  137. static void icmd    __P((char *, char *));
  138. static void iacmd    __P((char *, char *));
  139. static void ibcmd    __P((char *, char *));
  140. static void incmd    __P((char *, int));
  141. static void insert    __P((struct pelem *, int, char *));
  142. static void dcmd    __P((char *));
  143. static void dncmd    __P((int));
  144. static void delete    __P((struct pelem *, int));
  145. static void ccmd    __P((char *, char *));
  146. static void cncmd    __P((char *, int));
  147. static void change    __P((struct pelem *, int, char *));
  148. static int locate    __P((struct pelem *, char *));
  149.  
  150.  
  151.  
  152. int
  153. setpath(paths, cmds, localsyspath, dosuffix, printerrors)
  154. register char **paths, **cmds, *localsyspath;
  155. int dosuffix, printerrors;
  156. {
  157.     register char *cmd, *cmd1, *cmd2;
  158.     register int ncmd;
  159.  
  160.     sflag = dosuffix;
  161.     eflag = printerrors;
  162.     if (initpaths(paths) < 0)
  163.     return(-1);
  164.     if (npaths == 0)
  165.     return(0);
  166.     for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) {
  167.     if (cmd[0] != '-')
  168.         INVALID;
  169.     cmd1 = cmds[ncmd+1];
  170.     cmd2 = cmds[ncmd+2];
  171.     switch (cmd[1]) {
  172.     case 'r':
  173.         if (cmd[2] != '\0')
  174.         INVALID;
  175.         rcmd(localsyspath);
  176.         break;
  177.     case 'i':
  178.         if (cmd[2] == '\0') {
  179.         ncmd++;
  180.         if (cmd1 == NULL) TOOFEW;
  181.         icmd(cmd1, localsyspath);
  182.         } else if (isdigit(cmd[2])) {
  183.         ncmd++;
  184.         if (cmd1 == NULL) TOOFEW;
  185.         incmd(cmd1, atoi(cmd+2));
  186.         } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) {
  187.         INVALID;
  188.         } else {
  189.         ncmd += 2;
  190.         if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
  191.         if (cmd[2] == 'a')
  192.             iacmd(cmd1, cmd2);
  193.         else
  194.             ibcmd(cmd1, cmd2);
  195.         }
  196.         break;
  197.     case 'd':
  198.         if (cmd[2] == '\0') {
  199.         ncmd++;
  200.         if (cmd1 == NULL) TOOFEW;
  201.         dcmd(cmd1);
  202.         } else if (isdigit(cmd[2]))
  203.         dncmd(atoi(cmd+2));
  204.         else {
  205.         INVALID;
  206.         }
  207.         break;
  208.     case 'c':
  209.         if (cmd[2] == '\0') {
  210.         ncmd += 2;
  211.         if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
  212.         ccmd(cmd1, cmd2);
  213.         } else if (isdigit(cmd[2])) {
  214.         ncmd++;
  215.         if (cmd1 == NULL) TOOFEW;
  216.         cncmd(cmd1, atoi(cmd+2));
  217.         } else {
  218.         INVALID;
  219.         }
  220.         break;
  221.     default:
  222.         INVALID;
  223.     }
  224.     }
  225.     savepaths(paths);
  226.     freepaths();
  227.     return(0);
  228. }
  229.  
  230. static int
  231. initpaths(paths)
  232. register char **paths;
  233. {
  234.     register char *path, *val, *p, *q;
  235.     register int i, done;
  236.     register struct pelem *pe, *pathend;
  237.  
  238.     freepaths();
  239.     for (npaths = 0; path = paths[npaths]; npaths++) {
  240.     val = index(path, '=');
  241.     if (val == NULL) {
  242.         if (eflag)
  243.         xprintf("setpath: value missing in path '%s'\n", path);
  244.         freepaths();
  245.         return(-1);
  246.     }
  247.     *val++ = '\0';
  248.     pe = (struct pelem *)xmalloc((unsigned)(sizeof(struct pelem)));
  249.     setzero((char *) pe, sizeof(struct pelem));
  250.     if (pathhead == NULL)
  251.         pathhead = pathend = pe;
  252.     else {
  253.         pathend->pnext = pe;
  254.         pathend = pe;
  255.     }
  256.     p = strsave(path);
  257.     pe->pname = p;
  258.     pe->psuf = "";
  259.     pe->pdef = "";
  260.     for (i = 0; syspath[i].name; i++)
  261.         if (strcmp(pe->pname, syspath[i].name) == 0) {
  262.         pe->psuf = syspath[i].suffix;
  263.         pe->pdef = syspath[i].defalt;
  264.         break;
  265.         }
  266.     q = val;
  267.     for (;;) {
  268.         q = index(p = q, ':');
  269.         done = (q == NULL);
  270.         if (!done)
  271.         *q++ = '\0';
  272.         p = strsave(p);
  273.         pe->pdir[pe->pdirs] = p;
  274.         pe->pdirs++;
  275.         if (done)
  276.         break;
  277.     }
  278.     }
  279.     return(0);
  280. }
  281.  
  282. static void
  283. savepaths(paths)
  284. register char **paths;
  285. {
  286.     register char *p, *q;
  287.     register int npath, i, len;
  288.     register struct pelem *pe;
  289.  
  290.     for (npath = 0, pe = pathhead; pe; npath++, pe = pe->pnext) {
  291.     len = strlen(pe->pname) + 1;
  292.     if (pe->pdirs == 0)
  293.         len++;
  294.     else for (i = 0; i < pe->pdirs; i++)
  295.         len += strlen(pe->pdir[i]) + 1;
  296.     p = xmalloc((unsigned)len);
  297.     paths[npath] = p;
  298.     for (q = pe->pname; *p = *q; p++, q++);
  299.     *p++ = '=';
  300.     if (pe->pdirs != 0) {
  301.         for (i = 0; i < pe->pdirs; i++) {
  302.         for (q = pe->pdir[i]; *p = *q; p++, q++);
  303.         *p++ = ':';
  304.         }
  305.         p--;
  306.     }
  307.     *p = '\0';
  308.     }
  309. }
  310.  
  311. static void
  312. freepaths()
  313. {
  314.     register char *p;
  315.     register int i;
  316.     register struct pelem *pe;
  317.  
  318.     if (npaths == 0 || pathhead == NULL)
  319.     return;
  320.     while (pe = pathhead) {
  321.     if (pe->pname) {
  322.         for (i = 0; i < pe->pdirs; i++) {
  323.         if (pe->pdir[i] == NULL)
  324.             continue;
  325.         p = pe->pdir[i];
  326.         pe->pdir[i] = NULL;
  327.         xfree(p);
  328.         }
  329.         pe->pdirs = 0;
  330.         p = pe->pname;
  331.         pe->pname = NULL;
  332.         xfree(p);
  333.     }
  334.     pathhead = pe->pnext;
  335.     xfree((char *)pe);
  336.     }
  337.     npaths = 0;
  338. }
  339.  
  340. /***********************************************
  341.  ***    R E S E T   A   P A T H N A M E    ***
  342.  ***********************************************/
  343.  
  344. static void
  345. rcmd(localsyspath)        /* reset path with localsyspath */
  346. char *localsyspath;
  347. {
  348.     register int n, done;
  349.     register char *new, *p;
  350.     register struct pelem *pe;
  351.     char newbuf[MAXPATHLEN+1];
  352.  
  353.     for (pe = pathhead; pe; pe = pe->pnext) {
  354.     new = newbuf;
  355.     *new = '\0';
  356.     if (localsyspath != NULL) {
  357.         *new = ':';
  358.         strcpy(new + 1, localsyspath);
  359.         strcat(new, pe->psuf);
  360.     }
  361.     strcat(new, pe->pdef);
  362.     for (n = 0; n < pe->pdirs; n++) {
  363.         if (pe->pdir[n] == NULL)
  364.         continue;
  365.         p = pe->pdir[n];
  366.         pe->pdir[n] = NULL;
  367.         xfree(p);
  368.     }
  369.     pe->pdirs = 0;
  370.     for (;;) {
  371.         new = index(p = new, ':');
  372.         done = (new == NULL);
  373.         if (!done)
  374.         *new++ = '\0';
  375.         p = strsave(p);
  376.         pe->pdir[pe->pdirs] = p;
  377.         pe->pdirs++;
  378.         if (done)
  379.         break;
  380.     }
  381.     }
  382. }
  383.  
  384. /***********************************************
  385.  ***    I N S E R T   A   P A T H N A M E    ***
  386.  ***********************************************/
  387.  
  388. static void
  389. icmd(path, localsyspath)    /* insert path before localsyspath */
  390. char *path, *localsyspath;
  391. {
  392.     register int n;
  393.     register char *new;
  394.     register struct pelem *pe;
  395.     char newbuf[MAXPATHLEN+1];
  396.  
  397.     for (pe = pathhead; pe; pe = pe->pnext) {
  398.     if (sflag)
  399.         new = localsyspath;
  400.     else {
  401.         new = newbuf;
  402.         strcpy(new, localsyspath);
  403.         strcat(new, pe->psuf);
  404.     }
  405.     n = locate(pe, new);
  406.     if (n >= 0)
  407.         insert(pe, n, path);
  408.     else
  409.         insert(pe, 0, path);
  410.     }
  411. }
  412.  
  413. static void
  414. iacmd(inpath, path)        /* insert path after inpath */
  415. char *inpath, *path;
  416. {
  417.     register int n;
  418.     register struct pelem *pe;
  419.  
  420.     for (pe = pathhead; pe; pe = pe->pnext) {
  421.     n = locate(pe, inpath);
  422.     if (n >= 0)
  423.         insert(pe, n + 1, path);
  424.     else
  425.         xprintf("setpath: %s not found in %s\n",
  426.             inpath, pe->pname);
  427.     }
  428. }
  429.  
  430. static void
  431. ibcmd(inpath, path)        /* insert path before inpath */
  432. char *inpath, *path;
  433. {
  434.     register int n;
  435.     register struct pelem *pe;
  436.  
  437.     for (pe = pathhead; pe; pe = pe->pnext) {
  438.     n = locate(pe, inpath);
  439.     if (n >= 0)
  440.         insert(pe, n, path);
  441.     else
  442.         xprintf("setpath: %s not found in %s\n",
  443.             inpath, pe->pname);
  444.     }
  445. }
  446.  
  447. static void
  448. incmd(path, n)            /* insert path at position n */
  449. char *path;
  450. int n;
  451. {
  452.     register struct pelem *pe;
  453.  
  454.     for (pe = pathhead; pe; pe = pe->pnext)
  455.     insert(pe, n, path);
  456. }
  457.  
  458. static void
  459. insert(pe, loc, key)
  460. register struct pelem *pe;
  461. register int loc;
  462. register char *key;
  463. {
  464.     register int i;
  465.     register char *new;
  466.     char newbuf[2000];
  467.  
  468.     if (sflag) {        /* add suffix */
  469.     new = newbuf;
  470.     strcpy(new, key);
  471.     strcat(new, pe->psuf);
  472.     } else
  473.     new = key;
  474.     new = strsave(new);
  475.     for (i = pe->pdirs; i > loc; --i)
  476.     pe->pdir[i] = pe->pdir[i-1];
  477.     if (loc > pe->pdirs)
  478.     loc = pe->pdirs;
  479.     pe->pdir[loc] = new;
  480.     pe->pdirs++;
  481. }
  482.  
  483. /***********************************************
  484.  ***    D E L E T E   A   P A T H N A M E    ***
  485.  ***********************************************/
  486.  
  487. static void
  488. dcmd(path)            /* delete path */
  489. char *path;
  490. {
  491.     register int n;
  492.     register struct pelem *pe;
  493.  
  494.     for (pe = pathhead; pe; pe = pe->pnext) {
  495.     n = locate(pe, path);
  496.     if (n >= 0)
  497.         delete(pe, n);
  498.     else
  499.         xprintf("setpath: %s not found in %s\n",
  500.             path, pe->pname);
  501.     }
  502. }
  503.  
  504. static void
  505. dncmd(n)            /* delete at position n */
  506. int n;
  507. {
  508.     register struct pelem *pe;
  509.  
  510.     for (pe = pathhead; pe; pe = pe->pnext) {
  511.     if (n < pe->pdirs)
  512.         delete(pe, n);
  513.     else
  514.         xprintf("setpath: %d not valid position in %s\n",
  515.             n, pe->pname);
  516.     }
  517. }
  518.  
  519. static void
  520. delete(pe, n)
  521. register struct pelem *pe;
  522. int n;
  523. {
  524.     register int d;
  525.  
  526.     xfree(pe->pdir[n]);
  527.     for (d = n; d < pe->pdirs - 1; d++)
  528.     pe->pdir[d] = pe->pdir[d+1];
  529.     --pe->pdirs;
  530. }
  531.  
  532. /***********************************************
  533.  ***    C H A N G E   A   P A T H N A M E    ***
  534.  ***********************************************/
  535.  
  536. static void
  537. ccmd(inpath, path)        /* change inpath to path */
  538. char *inpath, *path;
  539. {
  540.     register int n;
  541.     register struct pelem *pe;
  542.  
  543.     for (pe = pathhead; pe; pe = pe->pnext) {
  544.     n = locate(pe, inpath);
  545.     if (n >= 0)
  546.         change(pe, n, path);
  547.     else
  548.         xprintf("setpath: %s not found in %s\n",
  549.             inpath, pe->pname);
  550.     }
  551. }
  552.  
  553. static void
  554. cncmd(path, n)        /* change at position n to path */
  555. char *path;
  556. int n;
  557. {
  558.     register struct pelem *pe;
  559.  
  560.     for (pe = pathhead; pe; pe = pe->pnext) {
  561.     if (n < pe->pdirs)
  562.         change(pe, n, path);
  563.     else
  564.         xprintf("setpath: %d not valid position in %s\n",
  565.             n, pe->pname);
  566.     }
  567. }
  568.  
  569. static void
  570. change(pe, loc, key)
  571. register struct pelem *pe;
  572. register int loc;
  573. register char *key;
  574. {
  575.     register char *new;
  576.     char newbuf[MAXPATHLEN+1];
  577.  
  578.     if (sflag) {        /* append suffix */
  579.     new = newbuf;
  580.     strcpy(new, key);
  581.     strcat(new, pe->psuf);
  582.     } else
  583.     new = key;
  584.     new = strsave(new);
  585.     xfree(pe->pdir[loc]);
  586.     pe->pdir[loc] = new;
  587. }
  588.  
  589. /***************************************
  590.  ***    F I N D   P A T H N A M E    ***
  591.  ***************************************/
  592.  
  593. static int
  594. locate(pe, key)
  595. register struct pelem *pe;
  596. register char *key;
  597. {
  598.     register int i;
  599.     register char *realkey;
  600.     char keybuf[MAXPATHLEN+1];
  601.  
  602.     if (sflag) {
  603.     realkey = keybuf;
  604.     strcpy(realkey, key);
  605.     strcat(realkey, pe->psuf);
  606.     } else
  607.     realkey = key;
  608.     for (i = 0; i < pe->pdirs; i++)
  609.     if (strcmp(pe->pdir[i], realkey) == 0)
  610.         break;
  611.     return((i < pe->pdirs) ? i : -1);
  612. }
  613. #endif
  614.