159243Sobrien/*
259243Sobrien * Copyright (c) 1990 Carnegie Mellon University
359243Sobrien * All Rights Reserved.
459243Sobrien *
559243Sobrien * Permission to use, copy, modify and distribute this software and its
659243Sobrien * documentation is hereby granted, provided that both the copyright
759243Sobrien * notice and this permission notice appear in all copies of the
859243Sobrien * software, derivative works or modified versions, and any portions
959243Sobrien * thereof, and that both notices appear in supporting documentation.
1059243Sobrien *
1159243Sobrien * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
1259243Sobrien * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
1359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT
1459243Sobrien * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
1559243Sobrien * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
1659243Sobrien * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
1759243Sobrien * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1859243Sobrien * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1959243Sobrien *
2059243Sobrien * Users of this software agree to return to Carnegie Mellon any
2159243Sobrien * improvements or extensions that they make and grant Carnegie the
2259243Sobrien * rights to redistribute these changes.
2359243Sobrien *
2459243Sobrien * Export of this software is permitted only after complying with the
2559243Sobrien * regulations of the U.S. Deptartment of Commerce relating to the
2659243Sobrien * Export of Technical Data.
2759243Sobrien */
2859243Sobrien/*
2959243Sobrien *  setpath --- smart interface for setting path variables
3059243Sobrien *
3159243Sobrien *  usage:	setpath(paths, cmds, localsyspath, dosuffix, printerrors)
3259243Sobrien *		char **paths, **cmds, *localsyspath;
3359243Sobrien *		int dosuffix, printerrors;
3459243Sobrien *
3559243Sobrien *  The 'paths' argument is a list of pointers to path lists of the
3659243Sobrien *  form "name=value" where name is the name of the path and value
3759243Sobrien *  is a colon separated list of directories.  There can never be
3859243Sobrien *  more than MAXDIRS (64) directories in a path.
3959243Sobrien *
4059243Sobrien *  The 'cmds' argument may be a sequence of any of the following:
4159243Sobrien *	-r			reset path to default
4259243Sobrien *	-i newpath		insert newpath before localsyspath
4359243Sobrien *	-ia oldpath newpath	insert newpath after oldpath
4459243Sobrien *	-ib oldpath newpath	insert newpath before oldpath
4559243Sobrien *	-i# newpath		insert newpath at position #
4659243Sobrien *	-d oldpath		delete oldpath
4759243Sobrien *	-d#			delete path at position #
4859243Sobrien *	-c oldpath newpath	change oldpath to newpath
4959243Sobrien *	-c# newpath		change position # to newpath
5059243Sobrien *
5159243Sobrien *  The "-i newpath" command is equivilent to "-ib 'localsyspath' newpath".
5259243Sobrien *
5359243Sobrien *  If 'dosuffix' is true, the appropriate suffix will be added to
5459243Sobrien *  all command operands for any system path in 'paths'.
5559243Sobrien *
5659243Sobrien *  Both of the 'paths' and 'cmds' lists are terminated by a NULL
5759243Sobrien *  entry.
5859243Sobrien *
5959243Sobrien *  if 'printerrors' is true, setpath will printf error diagnostics.
6059243Sobrien *
6159243Sobrien *  WARNING !!!: Under no circumstances should anyone change this
6259243Sobrien *  module without fully understanding the impact on the C shell.
6359243Sobrien *  The C shell has it's own malloc and printf routines and this
6459243Sobrien *  module was carefully written taking that into account.  Do not
6559243Sobrien *  use any stdio routines from this module except printf.
6659243Sobrien *
6759243Sobrien **********************************************************************
6859243Sobrien * HISTORY
6959243Sobrien *
7059243Sobrien * Revision 1.4  90/12/11  17:58:44  mja
7159243Sobrien * 	Add copyright/disclaimer for distribution.
7259243Sobrien *
7359243Sobrien * 05-Jun-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
7459243Sobrien *	Make all non-entry points static.
7559243Sobrien *
7659243Sobrien * 30-Apr-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
7759243Sobrien *	Added -r switch to reset paths to their default values.
7859243Sobrien *
7959243Sobrien * 06-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
8059243Sobrien *	Created from old setpath program for the shell.
8159243Sobrien *
8259243Sobrien **********************************************************************
8359243Sobrien */
8459243Sobrien#include "sh.h"
8559243Sobrien
8659243Sobrien#ifdef MACH
8759243Sobrien
8859243Sobrien#define MAXDIRS 64		/* max directories on a path */
8959243Sobrien#ifndef NULL
9059243Sobrien# define NULL 0
9159243Sobrien#endif
9259243Sobrien
9359243Sobrienstatic int npaths;		/* # pathlist arguments */
9459243Sobrien
9559243Sobrienstatic struct pelem {
9659243Sobrien    struct pelem *pnext;	/* pointer to next path */
9759243Sobrien    char *pname;		/* name of pathlist */
9859243Sobrien    char *psuf;			/* suffix for pathlist */
9959243Sobrien    char *pdef;			/* default for pathlist */
10059243Sobrien    int pdirs;			/* # directories on each pathlist */
10159243Sobrien    char *pdir[MAXDIRS];	/* directory names for each pathlist */
10259243Sobrien} *pathhead = NULL;
10359243Sobrien
10459243Sobrienstatic struct {
10559243Sobrien    char *name;
10659243Sobrien    char *suffix;
10759243Sobrien    char *defalt;
10859243Sobrien} syspath[] = {
10959243Sobrien    "PATH",	"/bin",		":/usr/ucb:/bin:/usr/bin",
11059243Sobrien    "CPATH",	"/include",	":/usr/include",
11159243Sobrien    "LPATH",	"/lib",		":/lib:/usr/lib",
11259243Sobrien    "MPATH",	"/man",		":/usr/man",
11359243Sobrien    "EPATH",	"/maclib",	"",
11459243Sobrien    0, 0, 0
11559243Sobrien};
11659243Sobrien
11759243Sobrienstatic int sflag;
11859243Sobrienstatic int eflag;
11959243Sobrien
12059243Sobrien#define INVALID { \
12159243Sobrien	if (eflag) xprintf(CGETS(10, 1, \
12259243Sobrien				 "setpath: invalid command '%s'.\n"), cmd); \
12359243Sobrien	freepaths(); \
12459243Sobrien	return(-1); \
12559243Sobrien}
12659243Sobrien
12759243Sobrien#define TOOFEW { \
12859243Sobrien	if (eflag) xprintf(CGETS(10, 2, \
12959243Sobrien		 "setpath: insufficient arguments to command '%s'.\n"), cmd); \
13059243Sobrien	freepaths(); \
13159243Sobrien	return(-1); \
13259243Sobrien}
13359243Sobrien
134167465Smpstatic int initpaths	(char **);
135167465Smpstatic void savepaths	(char **);
136167465Smpstatic void freepaths	(void);
137195609Smpstatic void tcsh_rcmd	(char *);
138167465Smpstatic void icmd	(char *, char *);
139167465Smpstatic void iacmd	(char *, char *);
140167465Smpstatic void ibcmd	(char *, char *);
141167465Smpstatic void incmd	(char *, int);
142167465Smpstatic void insert	(struct pelem *, int, char *);
143167465Smpstatic void dcmd	(char *);
144167465Smpstatic void dncmd	(int);
145167465Smpstatic void delete	(struct pelem *, int);
146167465Smpstatic void ccmd	(char *, char *);
147167465Smpstatic void cncmd	(char *, int);
148167465Smpstatic void change	(struct pelem *, int, char *);
149167465Smpstatic int locate	(struct pelem *, char *);
15059243Sobrien
15159243Sobrien
15259243Sobrien
15359243Sobrienint
154167465Smpsetpath(char **paths, char **cmds, char *localsyspath, int dosuffix,
155167465Smp	int printerrors)
15659243Sobrien{
157145479Smp    char *cmd, *cmd1, *cmd2;
158145479Smp    int ncmd;
15959243Sobrien
16059243Sobrien    sflag = dosuffix;
16159243Sobrien    eflag = printerrors;
16259243Sobrien    if (initpaths(paths) < 0)
16359243Sobrien	return(-1);
16459243Sobrien    if (npaths == 0)
16559243Sobrien	return(0);
16659243Sobrien    for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) {
16759243Sobrien	if (cmd[0] != '-')
16859243Sobrien	    INVALID;
16959243Sobrien	cmd1 = cmds[ncmd+1];
17059243Sobrien	cmd2 = cmds[ncmd+2];
17159243Sobrien	switch (cmd[1]) {
17259243Sobrien	case 'r':
17359243Sobrien	    if (cmd[2] != '\0')
17459243Sobrien		INVALID;
175195609Smp	    tcsh_rcmd(localsyspath);
17659243Sobrien	    break;
17759243Sobrien	case 'i':
17859243Sobrien	    if (cmd[2] == '\0') {
17959243Sobrien		ncmd++;
18059243Sobrien		if (cmd1 == NULL) TOOFEW;
18159243Sobrien		icmd(cmd1, localsyspath);
18259243Sobrien	    } else if (isdigit(cmd[2])) {
18359243Sobrien		ncmd++;
18459243Sobrien		if (cmd1 == NULL) TOOFEW;
18559243Sobrien		incmd(cmd1, atoi(cmd+2));
18659243Sobrien	    } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) {
18759243Sobrien		INVALID;
18859243Sobrien	    } else {
18959243Sobrien		ncmd += 2;
19059243Sobrien		if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
19159243Sobrien		if (cmd[2] == 'a')
19259243Sobrien		    iacmd(cmd1, cmd2);
19359243Sobrien		else
19459243Sobrien		    ibcmd(cmd1, cmd2);
19559243Sobrien	    }
19659243Sobrien	    break;
19759243Sobrien	case 'd':
19859243Sobrien	    if (cmd[2] == '\0') {
19959243Sobrien		ncmd++;
20059243Sobrien		if (cmd1 == NULL) TOOFEW;
20159243Sobrien		dcmd(cmd1);
20259243Sobrien	    } else if (isdigit(cmd[2]))
20359243Sobrien		dncmd(atoi(cmd+2));
20459243Sobrien	    else {
20559243Sobrien		INVALID;
20659243Sobrien	    }
20759243Sobrien	    break;
20859243Sobrien	case 'c':
20959243Sobrien	    if (cmd[2] == '\0') {
21059243Sobrien		ncmd += 2;
21159243Sobrien		if (cmd1 == NULL || cmd2 == NULL) TOOFEW;
21259243Sobrien		ccmd(cmd1, cmd2);
21359243Sobrien	    } else if (isdigit(cmd[2])) {
21459243Sobrien		ncmd++;
21559243Sobrien		if (cmd1 == NULL) TOOFEW;
21659243Sobrien		cncmd(cmd1, atoi(cmd+2));
21759243Sobrien	    } else {
21859243Sobrien		INVALID;
21959243Sobrien	    }
22059243Sobrien	    break;
22159243Sobrien	default:
22259243Sobrien	    INVALID;
22359243Sobrien	}
22459243Sobrien    }
22559243Sobrien    savepaths(paths);
22659243Sobrien    freepaths();
22759243Sobrien    return(0);
22859243Sobrien}
22959243Sobrien
23059243Sobrienstatic int
231167465Smpinitpaths(char **paths)
23259243Sobrien{
233145479Smp    char *path, *val, *p, *q;
234145479Smp    int i, done;
235145479Smp    struct pelem *pe, *pathend;
23659243Sobrien
23759243Sobrien    freepaths();
23859243Sobrien    for (npaths = 0; path = paths[npaths]; npaths++) {
23959243Sobrien	val = index(path, '=');
24059243Sobrien	if (val == NULL) {
24159243Sobrien	    if (eflag)
24259243Sobrien		xprintf(CGETS(10, 3,
24359243Sobrien			      "setpath: value missing in path '%s'\n"), path);
24459243Sobrien	    freepaths();
24559243Sobrien	    return(-1);
24659243Sobrien	}
24759243Sobrien	*val++ = '\0';
248167465Smp	pe = xmalloc(sizeof(struct pelem));
249167465Smp	setzero(pe, sizeof(struct pelem));
25059243Sobrien	if (pathhead == NULL)
25159243Sobrien	    pathhead = pathend = pe;
25259243Sobrien	else {
25359243Sobrien	    pathend->pnext = pe;
25459243Sobrien	    pathend = pe;
25559243Sobrien	}
25659243Sobrien	p = strsave(path);
25759243Sobrien	pe->pname = p;
25859243Sobrien	pe->psuf = "";
25959243Sobrien	pe->pdef = "";
26059243Sobrien	for (i = 0; syspath[i].name; i++)
26159243Sobrien	    if (strcmp(pe->pname, syspath[i].name) == 0) {
26259243Sobrien		pe->psuf = syspath[i].suffix;
26359243Sobrien		pe->pdef = syspath[i].defalt;
26459243Sobrien		break;
26559243Sobrien	    }
26659243Sobrien	q = val;
26759243Sobrien	for (;;) {
26859243Sobrien	    q = index(p = q, ':');
26959243Sobrien	    done = (q == NULL);
27059243Sobrien	    if (!done)
27159243Sobrien		*q++ = '\0';
27259243Sobrien	    p = strsave(p);
27359243Sobrien	    pe->pdir[pe->pdirs] = p;
27459243Sobrien	    pe->pdirs++;
27559243Sobrien	    if (done)
27659243Sobrien		break;
27759243Sobrien	}
27859243Sobrien    }
27959243Sobrien    return(0);
28059243Sobrien}
28159243Sobrien
28259243Sobrienstatic void
283167465Smpsavepaths(char **paths)
28459243Sobrien{
285145479Smp    char *p, *q;
286145479Smp    int npath, i, len;
287145479Smp    struct pelem *pe;
28859243Sobrien
28959243Sobrien    for (npath = 0, pe = pathhead; pe; npath++, pe = pe->pnext) {
29059243Sobrien	len = strlen(pe->pname) + 1;
29159243Sobrien	if (pe->pdirs == 0)
29259243Sobrien	    len++;
29359243Sobrien	else for (i = 0; i < pe->pdirs; i++)
29459243Sobrien	    len += strlen(pe->pdir[i]) + 1;
29559243Sobrien	p = xmalloc((unsigned)len);
29659243Sobrien	paths[npath] = p;
29759243Sobrien	for (q = pe->pname; *p = *q; p++, q++);
29859243Sobrien	*p++ = '=';
29959243Sobrien	if (pe->pdirs != 0) {
30059243Sobrien	    for (i = 0; i < pe->pdirs; i++) {
30159243Sobrien		for (q = pe->pdir[i]; *p = *q; p++, q++);
30259243Sobrien		*p++ = ':';
30359243Sobrien	    }
30459243Sobrien	    p--;
30559243Sobrien	}
30659243Sobrien	*p = '\0';
30759243Sobrien    }
30859243Sobrien}
30959243Sobrien
31059243Sobrienstatic void
311167465Smpfreepaths(void)
31259243Sobrien{
313145479Smp    char *p;
314145479Smp    int i;
315145479Smp    struct pelem *pe;
31659243Sobrien
31759243Sobrien    if (npaths == 0 || pathhead == NULL)
31859243Sobrien	return;
31959243Sobrien    while (pe = pathhead) {
32059243Sobrien	if (pe->pname) {
32159243Sobrien	    for (i = 0; i < pe->pdirs; i++) {
32259243Sobrien		if (pe->pdir[i] == NULL)
32359243Sobrien		    continue;
32459243Sobrien		p = pe->pdir[i];
32559243Sobrien		pe->pdir[i] = NULL;
32659243Sobrien		xfree((ptr_t) p);
32759243Sobrien	    }
32859243Sobrien	    pe->pdirs = 0;
32959243Sobrien	    p = pe->pname;
33059243Sobrien	    pe->pname = NULL;
33159243Sobrien	    xfree((ptr_t) p);
33259243Sobrien	}
33359243Sobrien	pathhead = pe->pnext;
33459243Sobrien	xfree((ptr_t) pe);
33559243Sobrien    }
33659243Sobrien    npaths = 0;
33759243Sobrien}
33859243Sobrien
33959243Sobrien/***********************************************
34059243Sobrien ***    R E S E T   A   P A T H N A M E    ***
34159243Sobrien ***********************************************/
34259243Sobrien
34359243Sobrienstatic void
344195609Smptcsh_rcmd(char *localsyspath)	/* reset path with localsyspath */
34559243Sobrien{
346145479Smp    int n, done;
347145479Smp    char *new, *p;
348145479Smp    struct pelem *pe;
349167465Smp    char newbuf[MAXPATHLEN+1];/*FIXBUF*/
35059243Sobrien
35159243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
35259243Sobrien	new = newbuf;
35359243Sobrien	*new = '\0';
35459243Sobrien	if (localsyspath != NULL) {
35559243Sobrien	    *new = ':';
35659243Sobrien	    (void) strcpy(new + 1, localsyspath);
35759243Sobrien	    (void) strcat(new, pe->psuf);
35859243Sobrien	}
35959243Sobrien	(void) strcat(new, pe->pdef);
36059243Sobrien	for (n = 0; n < pe->pdirs; n++) {
36159243Sobrien	    if (pe->pdir[n] == NULL)
36259243Sobrien		continue;
36359243Sobrien	    p = pe->pdir[n];
36459243Sobrien	    pe->pdir[n] = NULL;
36559243Sobrien	    xfree((ptr_t) p);
36659243Sobrien	}
36759243Sobrien	pe->pdirs = 0;
36859243Sobrien	for (;;) {
36959243Sobrien	    new = index(p = new, ':');
37059243Sobrien	    done = (new == NULL);
37159243Sobrien	    if (!done)
37259243Sobrien		*new++ = '\0';
37359243Sobrien	    p = strsave(p);
37459243Sobrien	    pe->pdir[pe->pdirs] = p;
37559243Sobrien	    pe->pdirs++;
37659243Sobrien	    if (done)
37759243Sobrien		break;
37859243Sobrien	}
37959243Sobrien    }
38059243Sobrien}
38159243Sobrien
38259243Sobrien/***********************************************
38359243Sobrien ***    I N S E R T   A   P A T H N A M E    ***
38459243Sobrien ***********************************************/
38559243Sobrien
38659243Sobrienstatic void
387167465Smpicmd(char *path, char *localsyspath)	/* insert path before localsyspath */
38859243Sobrien{
389145479Smp    int n;
390145479Smp    char *new;
391145479Smp    struct pelem *pe;
392167465Smp    char newbuf[MAXPATHLEN+1];/*FIXBUF*/
39359243Sobrien
39459243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
39559243Sobrien	if (sflag)
39659243Sobrien	    new = localsyspath;
39759243Sobrien	else {
39859243Sobrien	    new = newbuf;
39959243Sobrien	    (void) strcpy(new, localsyspath);
40059243Sobrien	    (void) strcat(new, pe->psuf);
40159243Sobrien	}
40259243Sobrien	n = locate(pe, new);
40359243Sobrien	if (n >= 0)
40459243Sobrien	    insert(pe, n, path);
40559243Sobrien	else
40659243Sobrien	    insert(pe, 0, path);
40759243Sobrien    }
40859243Sobrien}
40959243Sobrien
41059243Sobrienstatic void
411167465Smpiacmd(char *inpath, char *path)	/* insert path after inpath */
41259243Sobrien{
413145479Smp    int n;
414145479Smp    struct pelem *pe;
41559243Sobrien
41659243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
41759243Sobrien	n = locate(pe, inpath);
41859243Sobrien	if (n >= 0)
41959243Sobrien	    insert(pe, n + 1, path);
42059243Sobrien	else
42159243Sobrien	    xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
42259243Sobrien		    inpath, pe->pname);
42359243Sobrien    }
42459243Sobrien}
42559243Sobrien
42659243Sobrienstatic void
427167465Smpibcmd(char *inpath, char *path)	/* insert path before inpath */
42859243Sobrien{
429145479Smp    int n;
430145479Smp    struct pelem *pe;
43159243Sobrien
43259243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
43359243Sobrien	n = locate(pe, inpath);
43459243Sobrien	if (n >= 0)
43559243Sobrien	    insert(pe, n, path);
43659243Sobrien	else
437131962Smp	    xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
438131962Smp		    inpath, pe->pname);
43959243Sobrien    }
44059243Sobrien}
44159243Sobrien
44259243Sobrienstatic void
443167465Smpincmd(char *path, int n)	/* insert path at position n */
44459243Sobrien{
445145479Smp    struct pelem *pe;
44659243Sobrien
44759243Sobrien    for (pe = pathhead; pe; pe = pe->pnext)
44859243Sobrien	insert(pe, n, path);
44959243Sobrien}
45059243Sobrien
45159243Sobrienstatic void
452167465Smpinsert(struct pelem *pe, int loc, char *key)
45359243Sobrien{
454145479Smp    int i;
455145479Smp    char *new;
456167465Smp    char newbuf[2000];/*FIXBUF*/
45759243Sobrien
45859243Sobrien    if (sflag) {		/* add suffix */
45959243Sobrien	new = newbuf;
46059243Sobrien	(void) strcpy(new, key);
46159243Sobrien	(void) strcat(new, pe->psuf);
46259243Sobrien    } else
46359243Sobrien	new = key;
46459243Sobrien    new = strsave(new);
46559243Sobrien    for (i = pe->pdirs; i > loc; --i)
46659243Sobrien	pe->pdir[i] = pe->pdir[i-1];
46759243Sobrien    if (loc > pe->pdirs)
46859243Sobrien	loc = pe->pdirs;
46959243Sobrien    pe->pdir[loc] = new;
47059243Sobrien    pe->pdirs++;
47159243Sobrien}
47259243Sobrien
47359243Sobrien/***********************************************
47459243Sobrien ***    D E L E T E   A   P A T H N A M E    ***
47559243Sobrien ***********************************************/
47659243Sobrien
47759243Sobrienstatic void
478167465Smpdcmd(char *path)		/* delete path */
47959243Sobrien{
480145479Smp    int n;
481145479Smp    struct pelem *pe;
48259243Sobrien
48359243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
48459243Sobrien	n = locate(pe, path);
48559243Sobrien	if (n >= 0)
48659243Sobrien	    delete(pe, n);
48759243Sobrien	else
48859243Sobrien	    xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
48959243Sobrien		    path, pe->pname);
49059243Sobrien    }
49159243Sobrien}
49259243Sobrien
49359243Sobrienstatic void
494167465Smpdncmd(int n)			/* delete at position n */
49559243Sobrien{
496145479Smp    struct pelem *pe;
49759243Sobrien
49859243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
49959243Sobrien	if (n < pe->pdirs)
50059243Sobrien	    delete(pe, n);
50159243Sobrien	else
50259243Sobrien	    xprintf(CGETS(10, 5,
50359243Sobrien			    "setpath: %d not valid position in %s\n"),
50459243Sobrien		    n, pe->pname);
50559243Sobrien    }
50659243Sobrien}
50759243Sobrien
50859243Sobrienstatic void
509167465Smpdelete(struct pelem *pe, int n)
51059243Sobrien{
511145479Smp    int d;
51259243Sobrien
51359243Sobrien    xfree((ptr_t) (pe->pdir[n]));
51459243Sobrien    for (d = n; d < pe->pdirs - 1; d++)
51559243Sobrien	pe->pdir[d] = pe->pdir[d+1];
51659243Sobrien    --pe->pdirs;
51759243Sobrien}
51859243Sobrien
51959243Sobrien/***********************************************
52059243Sobrien ***    C H A N G E   A   P A T H N A M E    ***
52159243Sobrien ***********************************************/
52259243Sobrien
52359243Sobrienstatic void
524167465Smpccmd(char *inpath, char *path)	/* change inpath to path */
52559243Sobrien{
526145479Smp    int n;
527145479Smp    struct pelem *pe;
52859243Sobrien
52959243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
53059243Sobrien	n = locate(pe, inpath);
53159243Sobrien	if (n >= 0)
53259243Sobrien	    change(pe, n, path);
53359243Sobrien	else
53459243Sobrien	    xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"),
53559243Sobrien		    inpath, pe->pname);
53659243Sobrien    }
53759243Sobrien}
53859243Sobrien
53959243Sobrienstatic void
540167465Smpcncmd(char *path, int n)	/* change at position n to path */
54159243Sobrien{
542145479Smp    struct pelem *pe;
54359243Sobrien
54459243Sobrien    for (pe = pathhead; pe; pe = pe->pnext) {
54559243Sobrien	if (n < pe->pdirs)
54659243Sobrien	    change(pe, n, path);
54759243Sobrien	else
54859243Sobrien	    xprintf(CGETS(10, 5,
54959243Sobrien			    "setpath: %d not valid position in %s\n"),
55059243Sobrien		    n, pe->pname);
55159243Sobrien    }
55259243Sobrien}
55359243Sobrien
55459243Sobrienstatic void
555167465Smpchange(struct pelem *pe, int loc, char *key)
55659243Sobrien{
557145479Smp    char *new;
558167465Smp    char newbuf[MAXPATHLEN+1];/*FIXBUF*/
55959243Sobrien
56059243Sobrien    if (sflag) {		/* append suffix */
56159243Sobrien	new = newbuf;
56259243Sobrien	(void) strcpy(new, key);
56359243Sobrien	(void) strcat(new, pe->psuf);
56459243Sobrien    } else
56559243Sobrien	new = key;
56659243Sobrien    new = strsave(new);
56759243Sobrien    xfree((ptr_t) (pe->pdir[loc]));
56859243Sobrien    pe->pdir[loc] = new;
56959243Sobrien}
57059243Sobrien
57159243Sobrien/***************************************
57259243Sobrien ***    F I N D   P A T H N A M E    ***
57359243Sobrien ***************************************/
57459243Sobrien
57559243Sobrienstatic int
576167465Smplocate(struct pelem *pe, char *key)
57759243Sobrien{
578145479Smp    int i;
579145479Smp    char *realkey;
580167465Smp    char keybuf[MAXPATHLEN+1];/*FIXBUF*/
58159243Sobrien
58259243Sobrien    if (sflag) {
58359243Sobrien	realkey = keybuf;
58459243Sobrien	(void) strcpy(realkey, key);
58559243Sobrien	(void) strcat(realkey, pe->psuf);
58659243Sobrien    } else
58759243Sobrien	realkey = key;
58859243Sobrien    for (i = 0; i < pe->pdirs; i++)
58959243Sobrien	if (strcmp(pe->pdir[i], realkey) == 0)
59059243Sobrien	    break;
59159243Sobrien    return((i < pe->pdirs) ? i : -1);
59259243Sobrien}
59359243Sobrien#endif
594