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" 85 RCSID("$tcsh: ma.setp.c,v 1.18 2006/03/02 18:46:44 christos 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 94 static int npaths; /* # pathlist arguments */ 95 96 static 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 105 static 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 118 static int sflag; 119 static 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 135 static int initpaths (char **); 136 static void savepaths (char **); 137 static void freepaths (void); 138 static void 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 *); 151 152 153 154 int 155 setpath(char **paths, char **cmds, char *localsyspath, int dosuffix, 156 int printerrors) 157 { 158 char *cmd, *cmd1, *cmd2; 159 int ncmd; 160 161 sflag = dosuffix; 162 eflag = printerrors; 163 if (initpaths(paths) < 0) 164 return(-1); 165 if (npaths == 0) 166 return(0); 167 for (ncmd = 0; cmd = cmds[ncmd]; ncmd++) { 168 if (cmd[0] != '-') 169 INVALID; 170 cmd1 = cmds[ncmd+1]; 171 cmd2 = cmds[ncmd+2]; 172 switch (cmd[1]) { 173 case 'r': 174 if (cmd[2] != '\0') 175 INVALID; 176 rcmd(localsyspath); 177 break; 178 case 'i': 179 if (cmd[2] == '\0') { 180 ncmd++; 181 if (cmd1 == NULL) TOOFEW; 182 icmd(cmd1, localsyspath); 183 } else if (isdigit(cmd[2])) { 184 ncmd++; 185 if (cmd1 == NULL) TOOFEW; 186 incmd(cmd1, atoi(cmd+2)); 187 } else if (cmd[3] != '\0' || (cmd[2] != 'a' && cmd[2] != 'b')) { 188 INVALID; 189 } else { 190 ncmd += 2; 191 if (cmd1 == NULL || cmd2 == NULL) TOOFEW; 192 if (cmd[2] == 'a') 193 iacmd(cmd1, cmd2); 194 else 195 ibcmd(cmd1, cmd2); 196 } 197 break; 198 case 'd': 199 if (cmd[2] == '\0') { 200 ncmd++; 201 if (cmd1 == NULL) TOOFEW; 202 dcmd(cmd1); 203 } else if (isdigit(cmd[2])) 204 dncmd(atoi(cmd+2)); 205 else { 206 INVALID; 207 } 208 break; 209 case 'c': 210 if (cmd[2] == '\0') { 211 ncmd += 2; 212 if (cmd1 == NULL || cmd2 == NULL) TOOFEW; 213 ccmd(cmd1, cmd2); 214 } else if (isdigit(cmd[2])) { 215 ncmd++; 216 if (cmd1 == NULL) TOOFEW; 217 cncmd(cmd1, atoi(cmd+2)); 218 } else { 219 INVALID; 220 } 221 break; 222 default: 223 INVALID; 224 } 225 } 226 savepaths(paths); 227 freepaths(); 228 return(0); 229 } 230 231 static int 232 initpaths(char **paths) 233 { 234 char *path, *val, *p, *q; 235 int i, done; 236 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(CGETS(10, 3, 244 "setpath: value missing in path '%s'\n"), path); 245 freepaths(); 246 return(-1); 247 } 248 *val++ = '\0'; 249 pe = xmalloc(sizeof(struct pelem)); 250 setzero(pe, sizeof(struct pelem)); 251 if (pathhead == NULL) 252 pathhead = pathend = pe; 253 else { 254 pathend->pnext = pe; 255 pathend = pe; 256 } 257 p = strsave(path); 258 pe->pname = p; 259 pe->psuf = ""; 260 pe->pdef = ""; 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; 265 break; 266 } 267 q = val; 268 for (;;) { 269 q = index(p = q, ':'); 270 done = (q == NULL); 271 if (!done) 272 *q++ = '\0'; 273 p = strsave(p); 274 pe->pdir[pe->pdirs] = p; 275 pe->pdirs++; 276 if (done) 277 break; 278 } 279 } 280 return(0); 281 } 282 283 static void 284 savepaths(char **paths) 285 { 286 char *p, *q; 287 int npath, i, len; 288 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 311 static void 312 freepaths(void) 313 { 314 char *p; 315 int i; 316 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((ptr_t) p); 328 } 329 pe->pdirs = 0; 330 p = pe->pname; 331 pe->pname = NULL; 332 xfree((ptr_t) p); 333 } 334 pathhead = pe->pnext; 335 xfree((ptr_t) 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 344 static void 345 rcmd(char *localsyspath) /* reset path with localsyspath */ 346 { 347 int n, done; 348 char *new, *p; 349 struct pelem *pe; 350 char newbuf[MAXPATHLEN+1];/*FIXBUF*/ 351 352 for (pe = pathhead; pe; pe = pe->pnext) { 353 new = newbuf; 354 *new = '\0'; 355 if (localsyspath != NULL) { 356 *new = ':'; 357 (void) strcpy(new + 1, localsyspath); 358 (void) strcat(new, pe->psuf); 359 } 360 (void) strcat(new, pe->pdef); 361 for (n = 0; n < pe->pdirs; n++) { 362 if (pe->pdir[n] == NULL) 363 continue; 364 p = pe->pdir[n]; 365 pe->pdir[n] = NULL; 366 xfree((ptr_t) p); 367 } 368 pe->pdirs = 0; 369 for (;;) { 370 new = index(p = new, ':'); 371 done = (new == NULL); 372 if (!done) 373 *new++ = '\0'; 374 p = strsave(p); 375 pe->pdir[pe->pdirs] = p; 376 pe->pdirs++; 377 if (done) 378 break; 379 } 380 } 381 } 382 383 /*********************************************** 384 *** I N S E R T A P A T H N A M E *** 385 ***********************************************/ 386 387 static void 388 icmd(char *path, char *localsyspath) /* insert path before localsyspath */ 389 { 390 int n; 391 char *new; 392 struct pelem *pe; 393 char newbuf[MAXPATHLEN+1];/*FIXBUF*/ 394 395 for (pe = pathhead; pe; pe = pe->pnext) { 396 if (sflag) 397 new = localsyspath; 398 else { 399 new = newbuf; 400 (void) strcpy(new, localsyspath); 401 (void) strcat(new, pe->psuf); 402 } 403 n = locate(pe, new); 404 if (n >= 0) 405 insert(pe, n, path); 406 else 407 insert(pe, 0, path); 408 } 409 } 410 411 static void 412 iacmd(char *inpath, char *path) /* insert path after inpath */ 413 { 414 int n; 415 struct pelem *pe; 416 417 for (pe = pathhead; pe; pe = pe->pnext) { 418 n = locate(pe, inpath); 419 if (n >= 0) 420 insert(pe, n + 1, path); 421 else 422 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"), 423 inpath, pe->pname); 424 } 425 } 426 427 static void 428 ibcmd(char *inpath, char *path) /* insert path before inpath */ 429 { 430 int n; 431 struct pelem *pe; 432 433 for (pe = pathhead; pe; pe = pe->pnext) { 434 n = locate(pe, inpath); 435 if (n >= 0) 436 insert(pe, n, path); 437 else 438 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"), 439 inpath, pe->pname); 440 } 441 } 442 443 static void 444 incmd(char *path, int n) /* insert path at position n */ 445 { 446 struct pelem *pe; 447 448 for (pe = pathhead; pe; pe = pe->pnext) 449 insert(pe, n, path); 450 } 451 452 static void 453 insert(struct pelem *pe, int loc, char *key) 454 { 455 int i; 456 char *new; 457 char newbuf[2000];/*FIXBUF*/ 458 459 if (sflag) { /* add suffix */ 460 new = newbuf; 461 (void) strcpy(new, key); 462 (void) strcat(new, pe->psuf); 463 } else 464 new = key; 465 new = strsave(new); 466 for (i = pe->pdirs; i > loc; --i) 467 pe->pdir[i] = pe->pdir[i-1]; 468 if (loc > pe->pdirs) 469 loc = pe->pdirs; 470 pe->pdir[loc] = new; 471 pe->pdirs++; 472 } 473 474 /*********************************************** 475 *** D E L E T E A P A T H N A M E *** 476 ***********************************************/ 477 478 static void 479 dcmd(char *path) /* delete path */ 480 { 481 int n; 482 struct pelem *pe; 483 484 for (pe = pathhead; pe; pe = pe->pnext) { 485 n = locate(pe, path); 486 if (n >= 0) 487 delete(pe, n); 488 else 489 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"), 490 path, pe->pname); 491 } 492 } 493 494 static void 495 dncmd(int n) /* delete at position n */ 496 { 497 struct pelem *pe; 498 499 for (pe = pathhead; pe; pe = pe->pnext) { 500 if (n < pe->pdirs) 501 delete(pe, n); 502 else 503 xprintf(CGETS(10, 5, 504 "setpath: %d not valid position in %s\n"), 505 n, pe->pname); 506 } 507 } 508 509 static void 510 delete(struct pelem *pe, int n) 511 { 512 int d; 513 514 xfree((ptr_t) (pe->pdir[n])); 515 for (d = n; d < pe->pdirs - 1; d++) 516 pe->pdir[d] = pe->pdir[d+1]; 517 --pe->pdirs; 518 } 519 520 /*********************************************** 521 *** C H A N G E A P A T H N A M E *** 522 ***********************************************/ 523 524 static void 525 ccmd(char *inpath, char *path) /* change inpath to path */ 526 { 527 int n; 528 struct pelem *pe; 529 530 for (pe = pathhead; pe; pe = pe->pnext) { 531 n = locate(pe, inpath); 532 if (n >= 0) 533 change(pe, n, path); 534 else 535 xprintf(CGETS(10, 4, "setpath: %s not found in %s\n"), 536 inpath, pe->pname); 537 } 538 } 539 540 static void 541 cncmd(char *path, int n) /* change at position n to path */ 542 { 543 struct pelem *pe; 544 545 for (pe = pathhead; pe; pe = pe->pnext) { 546 if (n < pe->pdirs) 547 change(pe, n, path); 548 else 549 xprintf(CGETS(10, 5, 550 "setpath: %d not valid position in %s\n"), 551 n, pe->pname); 552 } 553 } 554 555 static void 556 change(struct pelem *pe, int loc, char *key) 557 { 558 char *new; 559 char newbuf[MAXPATHLEN+1];/*FIXBUF*/ 560 561 if (sflag) { /* append suffix */ 562 new = newbuf; 563 (void) strcpy(new, key); 564 (void) strcat(new, pe->psuf); 565 } else 566 new = key; 567 new = strsave(new); 568 xfree((ptr_t) (pe->pdir[loc])); 569 pe->pdir[loc] = new; 570 } 571 572 /*************************************** 573 *** F I N D P A T H N A M E *** 574 ***************************************/ 575 576 static int 577 locate(struct pelem *pe, char *key) 578 { 579 int i; 580 char *realkey; 581 char keybuf[MAXPATHLEN+1];/*FIXBUF*/ 582 583 if (sflag) { 584 realkey = keybuf; 585 (void) strcpy(realkey, key); 586 (void) strcat(realkey, pe->psuf); 587 } else 588 realkey = key; 589 for (i = 0; i < pe->pdirs; i++) 590 if (strcmp(pe->pdir[i], realkey) == 0) 591 break; 592 return((i < pe->pdirs) ? i : -1); 593 } 594 #endif 595