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("$Id: ma.setp.c,v 1.12 1996/04/26 19:18:36 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
__P((char **));
136 static void savepaths
__P((char **));
137 static void freepaths
__P((void));
138 static void rcmd
__P((char *));
139 static void icmd
__P((char *, char *));
140 static void iacmd
__P((char *, char *));
141 static void ibcmd
__P((char *, char *));
142 static void incmd
__P((char *, int));
143 static void insert
__P((struct pelem
*, int, char *));
144 static void dcmd
__P((char *));
145 static void dncmd
__P((int));
146 static void delete __P((struct pelem
*, int));
147 static void ccmd
__P((char *, char *));
148 static void cncmd
__P((char *, int));
149 static void change
__P((struct pelem
*, int, char *));
150 static int locate
__P((struct pelem
*, char *));
155 setpath(paths
, cmds
, localsyspath
, dosuffix
, printerrors
)
156 register char **paths
, **cmds
, *localsyspath
;
157 int dosuffix
, printerrors
;
159 register char *cmd
, *cmd1
, *cmd2
;
164 if (initpaths(paths
) < 0)
168 for (ncmd
= 0; cmd
= cmds
[ncmd
]; ncmd
++) {
180 if (cmd
[2] == '\0') {
182 if (cmd1
== NULL
) TOOFEW
;
183 icmd(cmd1
, localsyspath
);
184 } else if (isdigit(cmd
[2])) {
186 if (cmd1
== NULL
) TOOFEW
;
187 incmd(cmd1
, atoi(cmd
+2));
188 } else if (cmd
[3] != '\0' || (cmd
[2] != 'a' && cmd
[2] != 'b')) {
192 if (cmd1
== NULL
|| cmd2
== NULL
) TOOFEW
;
200 if (cmd
[2] == '\0') {
202 if (cmd1
== NULL
) TOOFEW
;
204 } else if (isdigit(cmd
[2]))
211 if (cmd
[2] == '\0') {
213 if (cmd1
== NULL
|| cmd2
== NULL
) TOOFEW
;
215 } else if (isdigit(cmd
[2])) {
217 if (cmd1
== NULL
) TOOFEW
;
218 cncmd(cmd1
, atoi(cmd
+2));
234 register char **paths
;
236 register char *path
, *val
, *p
, *q
;
237 register int i
, done
;
238 register struct pelem
*pe
, *pathend
;
241 for (npaths
= 0; path
= paths
[npaths
]; npaths
++) {
242 val
= index(path
, '=');
246 "setpath: value missing in path '%s'\n"), path
);
251 pe
= (struct pelem
*)xmalloc((unsigned)(sizeof(struct pelem
)));
252 setzero((char *) pe
, sizeof(struct pelem
));
253 if (pathhead
== NULL
)
254 pathhead
= pathend
= pe
;
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
;
271 q
= index(p
= q
, ':');
276 pe
->pdir
[pe
->pdirs
] = p
;
287 register char **paths
;
289 register char *p
, *q
;
290 register int npath
, i
, len
;
291 register struct pelem
*pe
;
293 for (npath
= 0, pe
= pathhead
; pe
; npath
++, pe
= pe
->pnext
) {
294 len
= strlen(pe
->pname
) + 1;
297 else for (i
= 0; i
< pe
->pdirs
; i
++)
298 len
+= strlen(pe
->pdir
[i
]) + 1;
299 p
= xmalloc((unsigned)len
);
301 for (q
= pe
->pname
; *p
= *q
; p
++, q
++);
303 if (pe
->pdirs
!= 0) {
304 for (i
= 0; i
< pe
->pdirs
; i
++) {
305 for (q
= pe
->pdir
[i
]; *p
= *q
; p
++, q
++);
319 register struct pelem
*pe
;
321 if (npaths
== 0 || pathhead
== NULL
)
323 while (pe
= pathhead
) {
325 for (i
= 0; i
< pe
->pdirs
; i
++) {
326 if (pe
->pdir
[i
] == NULL
)
337 pathhead
= pe
->pnext
;
343 /***********************************************
344 *** R E S E T A P A T H N A M E ***
345 ***********************************************/
348 rcmd(localsyspath
) /* reset path with localsyspath */
351 register int n
, done
;
352 register char *new, *p
;
353 register struct pelem
*pe
;
354 char newbuf
[MAXPATHLEN
+1];
356 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
359 if (localsyspath
!= NULL
) {
361 (void) strcpy(new + 1, localsyspath
);
362 (void) strcat(new, pe
->psuf
);
364 (void) strcat(new, pe
->pdef
);
365 for (n
= 0; n
< pe
->pdirs
; n
++) {
366 if (pe
->pdir
[n
] == NULL
)
374 new = index(p
= new, ':');
375 done
= (new == NULL
);
379 pe
->pdir
[pe
->pdirs
] = p
;
387 /***********************************************
388 *** I N S E R T A P A T H N A M E ***
389 ***********************************************/
392 icmd(path
, localsyspath
) /* insert path before localsyspath */
393 char *path
, *localsyspath
;
397 register struct pelem
*pe
;
398 char newbuf
[MAXPATHLEN
+1];
400 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
405 (void) strcpy(new, localsyspath
);
406 (void) strcat(new, pe
->psuf
);
417 iacmd(inpath
, path
) /* insert path after inpath */
421 register struct pelem
*pe
;
423 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
424 n
= locate(pe
, inpath
);
426 insert(pe
, n
+ 1, path
);
428 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
434 ibcmd(inpath
, path
) /* insert path before inpath */
438 register struct pelem
*pe
;
440 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
441 n
= locate(pe
, inpath
);
445 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n",
451 incmd(path
, n
) /* insert path at position n */
455 register struct pelem
*pe
;
457 for (pe
= pathhead
; pe
; pe
= pe
->pnext
)
463 register struct pelem
*pe
;
471 if (sflag
) { /* add suffix */
473 (void) strcpy(new, key
);
474 (void) strcat(new, pe
->psuf
);
478 for (i
= pe
->pdirs
; i
> loc
; --i
)
479 pe
->pdir
[i
] = pe
->pdir
[i
-1];
486 /***********************************************
487 *** D E L E T E A P A T H N A M E ***
488 ***********************************************/
491 dcmd(path
) /* delete path */
495 register struct pelem
*pe
;
497 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
498 n
= locate(pe
, path
);
502 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
508 dncmd(n
) /* delete at position n */
511 register struct pelem
*pe
;
513 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
518 "setpath: %d not valid position in %s\n"),
525 register struct pelem
*pe
;
530 xfree((ptr_t
) (pe
->pdir
[n
]));
531 for (d
= n
; d
< pe
->pdirs
- 1; d
++)
532 pe
->pdir
[d
] = pe
->pdir
[d
+1];
536 /***********************************************
537 *** C H A N G E A P A T H N A M E ***
538 ***********************************************/
541 ccmd(inpath
, path
) /* change inpath to path */
545 register struct pelem
*pe
;
547 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
548 n
= locate(pe
, inpath
);
552 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
558 cncmd(path
, n
) /* change at position n to path */
562 register struct pelem
*pe
;
564 for (pe
= pathhead
; pe
; pe
= pe
->pnext
) {
569 "setpath: %d not valid position in %s\n"),
576 register struct pelem
*pe
;
581 char newbuf
[MAXPATHLEN
+1];
583 if (sflag
) { /* append suffix */
585 (void) strcpy(new, key
);
586 (void) strcat(new, pe
->psuf
);
590 xfree((ptr_t
) (pe
->pdir
[loc
]));
594 /***************************************
595 *** F I N D P A T H N A M E ***
596 ***************************************/
600 register struct pelem
*pe
;
604 register char *realkey
;
605 char keybuf
[MAXPATHLEN
+1];
609 (void) strcpy(realkey
, key
);
610 (void) strcat(realkey
, pe
->psuf
);
613 for (i
= 0; i
< pe
->pdirs
; i
++)
614 if (strcmp(pe
->pdir
[i
], realkey
) == 0)
616 return((i
< pe
->pdirs
) ? i
: -1);