source: trunk/third/tcsh/ma.setp.c @ 9006

Revision 9006, 14.2 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9005, which included commits to RCS files with non-trunk default branches.
Line 
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"
85RCSID("$Id: ma.setp.c,v 1.1.1.1 1996-10-02 06:09:24 ghudson 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
94static int npaths;              /* # pathlist arguments */
95
96static 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
105static 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
118static int sflag;
119static 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
133static int initpaths    __P((char **));
134static void savepaths   __P((char **));
135static void freepaths   __P((void));
136static void rcmd        __P((char *));
137static void icmd        __P((char *, char *));
138static void iacmd       __P((char *, char *));
139static void ibcmd       __P((char *, char *));
140static void incmd       __P((char *, int));
141static void insert      __P((struct pelem *, int, char *));
142static void dcmd        __P((char *));
143static void dncmd       __P((int));
144static void delete      __P((struct pelem *, int));
145static void ccmd        __P((char *, char *));
146static void cncmd       __P((char *, int));
147static void change      __P((struct pelem *, int, char *));
148static int locate       __P((struct pelem *, char *));
149
150
151
152int
153setpath(paths, cmds, localsyspath, dosuffix, printerrors)
154register char **paths, **cmds, *localsyspath;
155int 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
230static int
231initpaths(paths)
232register 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
282static void
283savepaths(paths)
284register 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
311static void
312freepaths()
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
344static void
345rcmd(localsyspath)              /* reset path with localsyspath */
346char *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
388static void
389icmd(path, localsyspath)        /* insert path before localsyspath */
390char *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
413static void
414iacmd(inpath, path)             /* insert path after inpath */
415char *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
430static void
431ibcmd(inpath, path)             /* insert path before inpath */
432char *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
447static void
448incmd(path, n)                  /* insert path at position n */
449char *path;
450int n;
451{
452    register struct pelem *pe;
453
454    for (pe = pathhead; pe; pe = pe->pnext)
455        insert(pe, n, path);
456}
457
458static void
459insert(pe, loc, key)
460register struct pelem *pe;
461register int loc;
462register 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
487static void
488dcmd(path)                      /* delete path */
489char *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
504static void
505dncmd(n)                        /* delete at position n */
506int 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
519static void
520delete(pe, n)
521register struct pelem *pe;
522int 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
536static void
537ccmd(inpath, path)              /* change inpath to path */
538char *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
553static void
554cncmd(path, n)          /* change at position n to path */
555char *path;
556int 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
569static void
570change(pe, loc, key)
571register struct pelem *pe;
572register int loc;
573register 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
593static int
594locate(pe, key)
595register struct pelem *pe;
596register 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
Note: See TracBrowser for help on using the repository browser.