2 * Copyright (c) 1990 Carnegie Mellon University
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.
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.
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.
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.
29 * setpath --- smart interface for setting path variables
31 * usage: setpath(paths, cmds, localsyspath, dosuffix, printerrors)
32 * char **paths, **cmds, *localsyspath;
33 * int dosuffix, printerrors;
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.
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
51 * The "-i newpath" command is equivilent to "-ib 'localsyspath' newpath".
53 * If 'dosuffix' is true, the appropriate suffix will be added to
54 * all command operands for any system path in 'paths'.
56 * Both of the 'paths' and 'cmds' lists are terminated by a NULL
59 * if 'printerrors' is true, setpath will printf error diagnostics.
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.
67 **********************************************************************
70 * Revision 1.4 90/12/11 17:58:44 mja
71 * Add copyright/disclaimer for distribution.
73 * 05-Jun-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
74 * Make all non-entry points static.
76 * 30-Apr-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
77 * Added -r switch to reset paths to their default values.
79 * 06-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
80 * Created from old setpath program for the shell.
82 **********************************************************************
85 RCSID("$tcsh: ma.setp.c,v 1.19 2007/11/20 20:03:51 christos Exp $")
89 #define MAXDIRS 64 /* max directories on a path */
94 static int npaths; /* # pathlist arguments */
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 */
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", "",
122 if (eflag) xprintf(CGETS(10, 1, \
123 "setpath: invalid command '%s'.\n"), cmd); \
129 if (eflag) xprintf(CGETS(10, 2, \
130 "setpath: insufficient arguments to command '%s'.\n"), cmd); \
135 static int initpaths (char **);
136 static void savepaths (char **);
137 static void freepaths (void);
138 static void tcsh_rcmd (char *);
139 static void icmd (char *, char *);
140 static void iacmd (char *, char *);
141 static void ibcmd (char *, char *);
142 static void incmd (char *, int);
143 static void insert (struct pelem *, int, char *);
144 static void dcmd (char *);
145 static void dncmd (int);
146 static void delete (struct pelem *, int);
147 static void ccmd (char *, char *);
148 static void cncmd (char *, int);
149 static void change (struct pelem *, int, char *);
150 static int locate (struct pelem *, char *);
155 setpath(char **paths, char **cmds, char *localsyspath, int dosuffix,
158 char *cmd, *cmd1, *cmd2;
163 if (initpaths(paths) < 0)
167 for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) {
176 tcsh_rcmd(localsyspath);
179 if (cmd[2] == '\0') {
181 if (cmd1 == NULL) TOOFEW;
182 icmd(cmd1, localsyspath);
183 } else if (isdigit(cmd[2])) {
185 if (cmd1 == NULL) TOOFEW;
186 incmd(cmd1, atoi(cmd+2));
187 } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) {
191 if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
199 if (cmd[2] == '\0') {
201 if (cmd1 == NULL) TOOFEW;
203 } else if (isdigit(cmd[2]))
210 if (cmd[2] == '\0') {
212 if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
214 } else if (isdigit(cmd[2])) {
216 if (cmd1 == NULL) TOOFEW;
217 cncmd(cmd1, atoi(cmd+2));
232 initpaths(char **paths)
234 char *path, *val, *p, *q;
236 struct pelem *pe, *pathend;
239 for (npaths = 0; path = paths[npaths]; npaths++) {
240 val = index(path, '=');
244 "setpath: value missing in path '%s'\n"), path);
249 pe = xmalloc(sizeof(struct pelem));
250 setzero(pe, sizeof(struct pelem));
251 if (pathhead == NULL)
252 pathhead = pathend = pe;
261 for (i = 0; syspath[i].name; i++)
262 if (strcmp(pe->pname, syspath[i].name) == 0) {
263 pe->psuf = syspath[i].suffix;
264 pe->pdef = syspath[i].defalt;
269 q = index(p = q, ':');
274 pe->pdir[pe->pdirs] = p;
284 savepaths(char **paths)
290 for (npath = 0, pe = pathhead; pe; npath++, pe = pe->pnext) {
291 len = strlen(pe->pname) + 1;
294 else for (i = 0; i < pe->pdirs; i++)
295 len += strlen(pe->pdir[i]) + 1;
296 p = xmalloc((unsigned)len);
298 for (q = pe->pname; *p = *q; p++, q++);
300 if (pe->pdirs != 0) {
301 for (i = 0; i < pe->pdirs; i++) {
302 for (q = pe->pdir[i]; *p = *q; p++, q++);
318 if (npaths == 0 || pathhead == NULL)
320 while (pe = pathhead) {
322 for (i = 0; i < pe->pdirs; i++) {
323 if (pe->pdir[i] == NULL)
334 pathhead = pe->pnext;
340 /***********************************************
341 *** R E S E T A P A T H N A M E ***
342 ***********************************************/
345 tcsh_rcmd(char *localsyspath) /* reset path with localsyspath */
350 char newbuf[MAXPATHLEN+1];/*FIXBUF*/
352 for (pe = pathhead; pe; pe = pe->pnext) {
355 if (localsyspath != NULL) {
357 (void) strcpy(new + 1, localsyspath);
358 (void) strcat(new, pe->psuf);
360 (void) strcat(new, pe->pdef);
361 for (n = 0; n < pe->pdirs; n++) {
362 if (pe->pdir[n] == NULL)
370 new = index(p = new, ':');
371 done = (new == NULL);
375 pe->pdir[pe->pdirs] = p;
383 /***********************************************
384 *** I N S E R T A P A T H N A M E ***
385 ***********************************************/
388 icmd(char *path, char *localsyspath) /* insert path before localsyspath */
393 char newbuf[MAXPATHLEN+1];/*FIXBUF*/
395 for (pe = pathhead; pe; pe = pe->pnext) {
400 (void) strcpy(new, localsyspath);
401 (void) strcat(new, pe->psuf);
412 iacmd(char *inpath, char *path) /* insert path after inpath */
417 for (pe = pathhead; pe; pe = pe->pnext) {
418 n = locate(pe, inpath);
420 insert(pe, n + 1, path);
422 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
428 ibcmd(char *inpath, char *path) /* insert path before inpath */
433 for (pe = pathhead; pe; pe = pe->pnext) {
434 n = locate(pe, inpath);
438 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
444 incmd(char *path, int n) /* insert path at position n */
448 for (pe = pathhead; pe; pe = pe->pnext)
453 insert(struct pelem *pe, int loc, char *key)
457 char newbuf[2000];/*FIXBUF*/
459 if (sflag) { /* add suffix */
461 (void) strcpy(new, key);
462 (void) strcat(new, pe->psuf);
466 for (i = pe->pdirs; i > loc; --i)
467 pe->pdir[i] = pe->pdir[i-1];
474 /***********************************************
475 *** D E L E T E A P A T H N A M E ***
476 ***********************************************/
479 dcmd(char *path) /* delete path */
484 for (pe = pathhead; pe; pe = pe->pnext) {
485 n = locate(pe, path);
489 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
495 dncmd(int n) /* delete at position n */
499 for (pe = pathhead; pe; pe = pe->pnext) {
504 "setpath: %d not valid position in %s\n"),
510 delete(struct pelem *pe, int n)
514 xfree((ptr_t) (pe->pdir[n]));
515 for (d = n; d < pe->pdirs - 1; d++)
516 pe->pdir[d] = pe->pdir[d+1];
520 /***********************************************
521 *** C H A N G E A P A T H N A M E ***
522 ***********************************************/
525 ccmd(char *inpath, char *path) /* change inpath to path */
530 for (pe = pathhead; pe; pe = pe->pnext) {
531 n = locate(pe, inpath);
535 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
541 cncmd(char *path, int n) /* change at position n to path */
545 for (pe = pathhead; pe; pe = pe->pnext) {
550 "setpath: %d not valid position in %s\n"),
556 change(struct pelem *pe, int loc, char *key)
559 char newbuf[MAXPATHLEN+1];/*FIXBUF*/
561 if (sflag) { /* append suffix */
563 (void) strcpy(new, key);
564 (void) strcat(new, pe->psuf);
568 xfree((ptr_t) (pe->pdir[loc]));
572 /***************************************
573 *** F I N D P A T H N A M E ***
574 ***************************************/
577 locate(struct pelem *pe, char *key)
581 char keybuf[MAXPATHLEN+1];/*FIXBUF*/
585 (void) strcpy(realkey, key);
586 (void) strcat(realkey, pe->psuf);
589 for (i = 0; i < pe->pdirs; i++)
590 if (strcmp(pe->pdir[i], realkey) == 0)
592 return((i < pe->pdirs) ? i : -1);