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

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