1 /* $Header: /src/pub/tcsh/tw.init.c,v 3.25 1998/10/25 15:10:50 christos Exp $ */ 2 /* 3 * tw.init.c: Handle lists of things to complete 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 #include "sh.h" 38 39 RCSID("$Id: tw.init.c,v 3.25 1998/10/25 15:10:50 christos Exp $") 40 41 #include "tw.h" 42 #include "ed.h" 43 #include "tc.h" 44 #include "sh.proc.h" 45 46 #if !defined(NSIG) && defined(SIGMAX) 47 # define NSIG (SIGMAX+1) 48 #endif /* !NSIG && SIGMAX */ 49 #if !defined(NSIG) && defined(_NSIG) 50 # define NSIG _NSIG 51 #endif /* !NSIG && _NSIG */ 52 53 #define TW_INCR 128 54 55 typedef struct { 56 Char **list, /* List of command names */ 57 *buff; /* Space holding command names */ 58 int nlist, /* Number of items */ 59 nbuff, /* Current space in name buf */ 60 tlist, /* Total space in list */ 61 tbuff; /* Total space in name buf */ 62 } stringlist_t; 63 64 65 static struct varent *tw_vptr = NULL; /* Current shell variable */ 66 static Char **tw_env = NULL; /* Current environment variable */ 67 static Char *tw_word; /* Current word pointer */ 68 static struct KeyFuncs *tw_bind = NULL; /* List of the bindings */ 69 #ifndef HAVENOLIMIT 70 static struct limits *tw_limit = NULL; /* List of the resource limits */ 71 #endif /* HAVENOLIMIT */ 72 static int tw_index = 0; /* signal and job index */ 73 static DIR *tw_dir_fd = NULL; /* Current directory descriptor */ 74 static Char tw_retname[MAXPATHLEN+1]; /* Return buffer */ 75 static int tw_cmd_got = 0; /* What we need to do */ 76 static stringlist_t tw_cmd = { NULL, NULL, 0, 0, 0, 0 }; 77 static stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 }; 78 #define TW_FL_CMD 0x01 79 #define TW_FL_ALIAS 0x02 80 #define TW_FL_BUILTIN 0x04 81 #define TW_FL_SORT 0x08 82 #define TW_FL_REL 0x10 83 84 static struct { /* Current element pointer */ 85 int cur; /* Current element number */ 86 Char **pathv; /* Current element in path */ 87 DIR *dfd; /* Current directory descriptor */ 88 } tw_cmd_state; 89 90 91 #ifdef BSDSIGS 92 static sigmask_t tw_omask; 93 # define TW_HOLD() tw_omask = sigblock(sigmask(SIGINT)) 94 # define TW_RELS() (void) sigsetmask(tw_omask) 95 #else /* !BSDSIGS */ 96 # define TW_HOLD() (void) sighold(SIGINT) 97 # define TW_RELS() (void) sigrelse(SIGINT) 98 #endif /* BSDSIGS */ 99 100 #define SETDIR(dfd) \ 101 { \ 102 tw_dir_fd = dfd; \ 103 if (tw_dir_fd != NULL) \ 104 rewinddir(tw_dir_fd); \ 105 } 106 107 #define CLRDIR(dfd) \ 108 if (dfd != NULL) { \ 109 TW_HOLD(); \ 110 (void) closedir(dfd); \ 111 dfd = NULL; \ 112 TW_RELS(); \ 113 } 114 115 static Char *tw_str_add __P((stringlist_t *, int)); 116 static void tw_str_free __P((stringlist_t *)); 117 static Char *tw_dir_next __P((DIR *)); 118 static void tw_cmd_add __P((Char *name)); 119 static void tw_cmd_cmd __P((void)); 120 static void tw_cmd_builtin __P((void)); 121 static void tw_cmd_alias __P((void)); 122 static void tw_cmd_sort __P((void)); 123 static void tw_vptr_start __P((struct varent *)); 124 125 126 /* tw_str_add(): 127 * Add an item to the string list 128 */ 129 static Char * 130 tw_str_add(sl, len) 131 stringlist_t *sl; 132 int len; 133 { 134 Char *ptr; 135 136 if (sl->tlist <= sl->nlist) { 137 TW_HOLD(); 138 sl->tlist += TW_INCR; 139 sl->list = sl->list ? 140 (Char **) xrealloc((ptr_t) sl->list, 141 (size_t) (sl->tlist * sizeof(Char *))) : 142 (Char **) xmalloc((size_t) (sl->tlist * sizeof(Char *))); 143 TW_RELS(); 144 } 145 if (sl->tbuff <= sl->nbuff + len) { 146 int i; 147 ptr = sl->buff; 148 149 TW_HOLD(); 150 sl->tbuff += TW_INCR + len; 151 sl->buff = sl->buff ? 152 (Char *) xrealloc((ptr_t) sl->buff, 153 (size_t) (sl->tbuff * sizeof(Char))) : 154 (Char *) xmalloc((size_t) (sl->tbuff * sizeof(Char))); 155 /* Re-thread the new pointer list, if changed */ 156 if (ptr != NULL && ptr != sl->buff) { 157 int offs = (int) (sl->buff - ptr); 158 for (i = 0; i < sl->nlist; i++) 159 sl->list[i] += offs; 160 } 161 TW_RELS(); 162 } 163 ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff]; 164 sl->nbuff += len; 165 return ptr; 166 } /* tw_str_add */ 167 168 169 /* tw_str_free(): 170 * Free a stringlist 171 */ 172 static void 173 tw_str_free(sl) 174 stringlist_t *sl; 175 { 176 TW_HOLD(); 177 if (sl->list) { 178 xfree((ptr_t) sl->list); 179 sl->list = NULL; 180 sl->tlist = sl->nlist = 0; 181 } 182 if (sl->buff) { 183 xfree((ptr_t) sl->buff); 184 sl->buff = NULL; 185 sl->tbuff = sl->nbuff = 0; 186 } 187 TW_RELS(); 188 } /* end tw_str_free */ 189 190 191 static Char * 192 tw_dir_next(dfd) 193 DIR *dfd; 194 { 195 register struct dirent *dirp; 196 197 if (dfd == NULL) 198 return NULL; 199 200 if ((dirp = readdir(dfd)) != NULL) { 201 (void) Strcpy(tw_retname, str2short(dirp->d_name)); 202 return (tw_retname); 203 } 204 return NULL; 205 } /* end tw_dir_next */ 206 207 208 /* tw_cmd_add(): 209 * Add the name to the command list 210 */ 211 static void 212 tw_cmd_add(name) 213 Char *name; 214 { 215 int len; 216 217 len = (int) Strlen(name) + 2; 218 (void) Strcpy(tw_str_add(&tw_cmd, len), name); 219 } /* end tw_cmd_add */ 220 221 222 /* tw_cmd_free(): 223 * Free the command list 224 */ 225 void 226 tw_cmd_free() 227 { 228 CLRDIR(tw_dir_fd) 229 tw_str_free(&tw_cmd); 230 tw_cmd_got = 0; 231 } /* end tw_cmd_free */ 232 233 /* tw_cmd_cmd(): 234 * Add system commands to the command list 235 */ 236 static void 237 tw_cmd_cmd() 238 { 239 register DIR *dirp; 240 register struct dirent *dp; 241 register Char *dir = NULL, *name; 242 register Char **pv; 243 struct varent *v = adrof(STRpath); 244 struct varent *recexec = adrof(STRrecognize_only_executables); 245 int len; 246 247 248 if (v == NULL) /* if no path */ 249 return; 250 251 for (pv = v->vec; *pv; pv++) { 252 if (pv[0][0] != '/') { 253 tw_cmd_got |= TW_FL_REL; 254 continue; 255 } 256 257 if ((dirp = opendir(short2str(*pv))) == NULL) 258 continue; 259 260 if (recexec) 261 dir = Strspl(*pv, STRslash); 262 while ((dp = readdir(dirp)) != NULL) { 263 /* the call to executable() may make this a bit slow */ 264 name = str2short(dp->d_name); 265 if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0))) 266 continue; 267 len = (int) Strlen(name) + 2; 268 if (name[0] == '#' || /* emacs temp files */ 269 name[0] == '.' || /* .files */ 270 name[len - 3] == '~' || /* emacs backups */ 271 name[len - 3] == '%') /* textedit backups */ 272 continue; /* Ignore! */ 273 tw_cmd_add(name); 274 } 275 (void) closedir(dirp); 276 if (recexec) 277 xfree((ptr_t) dir); 278 } 279 } /* end tw_cmd_cmd */ 280 281 282 /* tw_cmd_builtin(): 283 * Add builtins to the command list 284 */ 285 static void 286 tw_cmd_builtin() 287 { 288 register struct biltins *bptr; 289 290 for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) 291 if (bptr->bname) 292 tw_cmd_add(str2short(bptr->bname)); 293 #ifdef WINNT 294 for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) 295 if (bptr->bname) 296 tw_cmd_add(str2short(bptr->bname)); 297 #endif /* WINNT*/ 298 } /* end tw_cmd_builtin */ 299 300 301 /* tw_cmd_alias(): 302 * Add aliases to the command list 303 */ 304 static void 305 tw_cmd_alias() 306 { 307 register struct varent *p; 308 register struct varent *c; 309 310 p = &aliases; 311 for (;;) { 312 while (p->v_left) 313 p = p->v_left; 314 x: 315 if (p->v_parent == 0) /* is it the header? */ 316 return; 317 if (p->v_name) 318 tw_cmd_add(p->v_name); 319 if (p->v_right) { 320 p = p->v_right; 321 continue; 322 } 323 do { 324 c = p; 325 p = p->v_parent; 326 } while (p->v_right == c); 327 goto x; 328 } 329 } /* end tw_cmd_alias */ 330 331 332 /* tw_cmd_sort(): 333 * Sort the command list removing duplicate elements 334 */ 335 static void 336 tw_cmd_sort() 337 { 338 int fwd, i; 339 340 TW_HOLD(); 341 /* sort the list. */ 342 qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *), 343 (int (*) __P((const void *, const void *))) fcompare); 344 345 /* get rid of multiple entries */ 346 for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) { 347 if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */ 348 fwd++; /* increase the forward ref. count */ 349 else if (fwd) 350 tw_cmd.list[i - fwd] = tw_cmd.list[i]; 351 } 352 /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */ 353 if (fwd) 354 tw_cmd.list[i - fwd] = tw_cmd.list[i]; 355 tw_cmd.nlist -= fwd; 356 TW_RELS(); 357 } /* end tw_cmd_sort */ 358 359 360 /* tw_cmd_start(): 361 * Get the command list and sort it, if not done yet. 362 * Reset the current pointer to the beginning of the command list 363 */ 364 /*ARGSUSED*/ 365 void 366 tw_cmd_start(dfd, pat) 367 DIR *dfd; 368 Char *pat; 369 { 370 static Char *defpath[] = { STRNULL, 0 }; 371 USE(pat); 372 SETDIR(dfd) 373 if ((tw_cmd_got & TW_FL_CMD) == 0) { 374 tw_cmd_free(); 375 tw_cmd_cmd(); 376 tw_cmd_got |= TW_FL_CMD; 377 } 378 if ((tw_cmd_got & TW_FL_ALIAS) == 0) { 379 tw_cmd_alias(); 380 tw_cmd_got &= ~TW_FL_SORT; 381 tw_cmd_got |= TW_FL_ALIAS; 382 } 383 if ((tw_cmd_got & TW_FL_BUILTIN) == 0) { 384 tw_cmd_builtin(); 385 tw_cmd_got &= ~TW_FL_SORT; 386 tw_cmd_got |= TW_FL_BUILTIN; 387 } 388 if ((tw_cmd_got & TW_FL_SORT) == 0) { 389 tw_cmd_sort(); 390 tw_cmd_got |= TW_FL_SORT; 391 } 392 393 tw_cmd_state.cur = 0; 394 CLRDIR(tw_cmd_state.dfd) 395 if (tw_cmd_got & TW_FL_REL) { 396 struct varent *vp = adrof(STRpath); 397 if (vp && vp->vec) 398 tw_cmd_state.pathv = vp->vec; 399 else 400 tw_cmd_state.pathv = defpath; 401 } 402 else 403 tw_cmd_state.pathv = defpath; 404 } /* tw_cmd_start */ 405 406 407 /* tw_cmd_next(): 408 * Return the next element in the command list or 409 * Look for commands in the relative path components 410 */ 411 Char * 412 tw_cmd_next(dir, flags) 413 Char *dir; 414 int *flags; 415 { 416 Char *ptr = NULL; 417 418 if (tw_cmd_state.cur < tw_cmd.nlist) { 419 *flags = TW_DIR_OK; 420 return tw_cmd.list[tw_cmd_state.cur++]; 421 } 422 423 /* 424 * We need to process relatives in the path. 425 */ 426 while (((tw_cmd_state.dfd == NULL) || 427 ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) && 428 (*tw_cmd_state.pathv != NULL)) { 429 430 CLRDIR(tw_cmd_state.dfd) 431 432 while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/') 433 tw_cmd_state.pathv++; 434 if ((ptr = *tw_cmd_state.pathv) != 0) { 435 /* 436 * We complete directories only on '.' should that 437 * be changed? 438 */ 439 if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) { 440 *dir = '\0'; 441 tw_cmd_state.dfd = opendir("."); 442 *flags = TW_DIR_OK | TW_EXEC_CHK; 443 } 444 else { 445 copyn(dir, *tw_cmd_state.pathv, FILSIZ); 446 catn(dir, STRslash, FILSIZ); 447 tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv)); 448 *flags = TW_EXEC_CHK; 449 } 450 tw_cmd_state.pathv++; 451 } 452 } 453 return ptr; 454 } /* end tw_cmd_next */ 455 456 457 /* tw_vptr_start(): 458 * Find the first variable in the variable list 459 */ 460 static void 461 tw_vptr_start(c) 462 struct varent *c; 463 { 464 tw_vptr = c; /* start at beginning of variable list */ 465 466 for (;;) { 467 while (tw_vptr->v_left) 468 tw_vptr = tw_vptr->v_left; 469 x: 470 if (tw_vptr->v_parent == 0) { /* is it the header? */ 471 tw_vptr = NULL; 472 return; 473 } 474 if (tw_vptr->v_name) 475 return; /* found first one */ 476 if (tw_vptr->v_right) { 477 tw_vptr = tw_vptr->v_right; 478 continue; 479 } 480 do { 481 c = tw_vptr; 482 tw_vptr = tw_vptr->v_parent; 483 } while (tw_vptr->v_right == c); 484 goto x; 485 } 486 } /* end tw_shvar_start */ 487 488 489 /* tw_shvar_next(): 490 * Return the next shell variable 491 */ 492 /*ARGSUSED*/ 493 Char * 494 tw_shvar_next(dir, flags) 495 Char *dir; 496 int *flags; 497 { 498 register struct varent *p; 499 register struct varent *c; 500 register Char *cp; 501 502 USE(flags); 503 USE(dir); 504 if ((p = tw_vptr) == NULL) 505 return (NULL); /* just in case */ 506 507 cp = p->v_name; /* we know that this name is here now */ 508 509 /* now find the next one */ 510 for (;;) { 511 if (p->v_right) { /* if we can go right */ 512 p = p->v_right; 513 while (p->v_left) 514 p = p->v_left; 515 } 516 else { /* else go up */ 517 do { 518 c = p; 519 p = p->v_parent; 520 } while (p->v_right == c); 521 } 522 if (p->v_parent == 0) { /* is it the header? */ 523 tw_vptr = NULL; 524 return (cp); 525 } 526 if (p->v_name) { 527 tw_vptr = p; /* save state for the next call */ 528 return (cp); 529 } 530 } 531 } /* end tw_shvar_next */ 532 533 534 /* tw_envvar_next(): 535 * Return the next environment variable 536 */ 537 /*ARGSUSED*/ 538 Char * 539 tw_envvar_next(dir, flags) 540 Char *dir; 541 int *flags; 542 { 543 Char *ps, *pd; 544 545 USE(flags); 546 USE(dir); 547 if (tw_env == NULL || *tw_env == NULL) 548 return (NULL); 549 for (ps = *tw_env, pd = tw_retname; 550 *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++) 551 continue; 552 *pd = '\0'; 553 tw_env++; 554 return (tw_retname); 555 } /* end tw_envvar_next */ 556 557 558 /* tw_var_start(): 559 * Begin the list of the shell and environment variables 560 */ 561 /*ARGSUSED*/ 562 void 563 tw_var_start(dfd, pat) 564 DIR *dfd; 565 Char *pat; 566 { 567 USE(pat); 568 SETDIR(dfd) 569 tw_vptr_start(&shvhed); 570 tw_env = STR_environ; 571 } /* end tw_var_start */ 572 573 574 /* tw_alias_start(): 575 * Begin the list of the shell aliases 576 */ 577 /*ARGSUSED*/ 578 void 579 tw_alias_start(dfd, pat) 580 DIR *dfd; 581 Char *pat; 582 { 583 USE(pat); 584 SETDIR(dfd) 585 tw_vptr_start(&aliases); 586 tw_env = NULL; 587 } /* tw_alias_start */ 588 589 590 /* tw_complete_start(): 591 * Begin the list of completions 592 */ 593 /*ARGSUSED*/ 594 void 595 tw_complete_start(dfd, pat) 596 DIR *dfd; 597 Char *pat; 598 { 599 extern struct varent completions; 600 601 USE(pat); 602 SETDIR(dfd) 603 tw_vptr_start(&completions); 604 tw_env = NULL; 605 } /* end tw_complete_start */ 606 607 608 /* tw_var_next(): 609 * Return the next shell or environment variable 610 */ 611 Char * 612 tw_var_next(dir, flags) 613 Char *dir; 614 int *flags; 615 { 616 Char *ptr = NULL; 617 618 if (tw_vptr) 619 ptr = tw_shvar_next(dir, flags); 620 if (!ptr && tw_env) 621 ptr = tw_envvar_next(dir, flags); 622 return ptr; 623 } /* end tw_var_next */ 624 625 626 /* tw_logname_start(): 627 * Initialize lognames to the beginning of the list 628 */ 629 /*ARGSUSED*/ 630 void 631 tw_logname_start(dfd, pat) 632 DIR *dfd; 633 Char *pat; 634 { 635 USE(pat); 636 SETDIR(dfd) 637 #if !defined(_VMS_POSIX) && !defined(WINNT) 638 (void) setpwent(); /* Open passwd file */ 639 #endif /* !_VMS_POSIX && !WINNT */ 640 } /* end tw_logname_start */ 641 642 643 /* tw_logname_next(): 644 * Return the next entry from the passwd file 645 */ 646 /*ARGSUSED*/ 647 Char * 648 tw_logname_next(dir, flags) 649 Char *dir; 650 int *flags; 651 { 652 static Char retname[MAXPATHLEN]; 653 struct passwd *pw; 654 /* 655 * We don't want to get interrupted inside getpwent() 656 * because the yellow pages code is not interruptible, 657 * and if we call endpwent() immediatetely after 658 * (in pintr()) we may be freeing an invalid pointer 659 */ 660 USE(flags); 661 USE(dir); 662 TW_HOLD(); 663 #if !defined(_VMS_POSIX) && !defined(WINNT) 664 /* ISC does not declare getpwent()? */ 665 pw = (struct passwd *) getpwent(); 666 #else /* _VMS_POSIX || WINNT */ 667 pw = NULL; 668 #endif /* !_VMS_POSIX && !WINNT */ 669 TW_RELS(); 670 671 if (pw == NULL) { 672 #ifdef YPBUGS 673 fix_yp_bugs(); 674 #endif 675 return (NULL); 676 } 677 (void) Strcpy(retname, str2short(pw->pw_name)); 678 return (retname); 679 } /* end tw_logname_next */ 680 681 682 /* tw_logname_end(): 683 * Close the passwd file to finish the logname list 684 */ 685 void 686 tw_logname_end() 687 { 688 #ifdef YPBUGS 689 fix_yp_bugs(); 690 #endif 691 #if !defined(_VMS_POSIX) && !defined(WINNT) 692 (void) endpwent(); 693 #endif /* !_VMS_POSIX && !WINNT */ 694 } /* end tw_logname_end */ 695 696 697 /* tw_grpname_start(): 698 * Initialize grpnames to the beginning of the list 699 */ 700 /*ARGSUSED*/ 701 void 702 tw_grpname_start(dfd, pat) 703 DIR *dfd; 704 Char *pat; 705 { 706 USE(pat); 707 SETDIR(dfd) 708 #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 709 (void) setgrent(); /* Open group file */ 710 #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 711 } /* end tw_grpname_start */ 712 713 714 /* tw_grpname_next(): 715 * Return the next entry from the group file 716 */ 717 /*ARGSUSED*/ 718 Char * 719 tw_grpname_next(dir, flags) 720 Char *dir; 721 int *flags; 722 { 723 static Char retname[MAXPATHLEN]; 724 struct group *gr; 725 /* 726 * We don't want to get interrupted inside getgrent() 727 * because the yellow pages code is not interruptible, 728 * and if we call endgrent() immediatetely after 729 * (in pintr()) we may be freeing an invalid pointer 730 */ 731 USE(flags); 732 USE(dir); 733 TW_HOLD(); 734 #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 735 gr = (struct group *) getgrent(); 736 #else /* _VMS_POSIX || _OSD_POSIX || WINNT */ 737 gr = NULL; 738 #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 739 TW_RELS(); 740 741 if (gr == NULL) { 742 #ifdef YPBUGS 743 fix_yp_bugs(); 744 #endif 745 return (NULL); 746 } 747 (void) Strcpy(retname, str2short(gr->gr_name)); 748 return (retname); 749 } /* end tw_grpname_next */ 750 751 752 /* tw_grpname_end(): 753 * Close the group file to finish the groupname list 754 */ 755 void 756 tw_grpname_end() 757 { 758 #ifdef YPBUGS 759 fix_yp_bugs(); 760 #endif 761 #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 762 (void) endgrent(); 763 #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 764 } /* end tw_grpname_end */ 765 766 /* tw_file_start(): 767 * Initialize the directory for the file list 768 */ 769 /*ARGSUSED*/ 770 void 771 tw_file_start(dfd, pat) 772 DIR *dfd; 773 Char *pat; 774 { 775 struct varent *vp; 776 USE(pat); 777 SETDIR(dfd) 778 if ((vp = adrof(STRcdpath)) != NULL) 779 tw_env = vp->vec; 780 } /* end tw_file_start */ 781 782 783 /* tw_file_next(): 784 * Return the next file in the directory 785 */ 786 Char * 787 tw_file_next(dir, flags) 788 Char *dir; 789 int *flags; 790 { 791 Char *ptr = tw_dir_next(tw_dir_fd); 792 if (ptr == NULL && (*flags & TW_DIR_OK) != 0) { 793 CLRDIR(tw_dir_fd) 794 while (tw_env && *tw_env) 795 if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL) 796 break; 797 else 798 tw_env++; 799 800 if (tw_dir_fd) { 801 copyn(dir, *tw_env++, MAXPATHLEN); 802 catn(dir, STRslash, MAXPATHLEN); 803 ptr = tw_dir_next(tw_dir_fd); 804 } 805 } 806 return ptr; 807 } /* end tw_file_next */ 808 809 810 /* tw_dir_end(): 811 * Clear directory related lists 812 */ 813 void 814 tw_dir_end() 815 { 816 CLRDIR(tw_dir_fd) 817 CLRDIR(tw_cmd_state.dfd) 818 } /* end tw_dir_end */ 819 820 821 /* tw_item_free(): 822 * Free the item list 823 */ 824 void 825 tw_item_free() 826 { 827 tw_str_free(&tw_item); 828 } /* end tw_item_free */ 829 830 831 /* tw_item_get(): 832 * Return the list of items 833 */ 834 Char ** 835 tw_item_get() 836 { 837 return tw_item.list; 838 } /* end tw_item_get */ 839 840 841 /* tw_item_add(): 842 * Return a new item 843 */ 844 Char * 845 tw_item_add(len) 846 int len; 847 { 848 return tw_str_add(&tw_item, len); 849 } /* tw_item_add */ 850 851 852 /* tw_item_find(): 853 * Find the string if it exists in the item list 854 * end return it. 855 */ 856 Char * 857 tw_item_find(str) 858 Char *str; 859 { 860 int i; 861 862 if (tw_item.list == NULL || str == NULL) 863 return NULL; 864 865 for (i = 0; i < tw_item.nlist; i++) 866 if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0) 867 return tw_item.list[i]; 868 return NULL; 869 } /* end tw_item_find */ 870 871 872 /* tw_vl_start(): 873 * Initialize a variable list 874 */ 875 void 876 tw_vl_start(dfd, pat) 877 DIR *dfd; 878 Char *pat; 879 { 880 SETDIR(dfd) 881 if ((tw_vptr = adrof(pat)) != NULL) { 882 tw_env = tw_vptr->vec; 883 tw_vptr = NULL; 884 } 885 else 886 tw_env = NULL; 887 } /* end tw_vl_start */ 888 889 890 /* 891 * Initialize a word list 892 */ 893 void 894 tw_wl_start(dfd, pat) 895 DIR *dfd; 896 Char *pat; 897 { 898 SETDIR(dfd); 899 tw_word = pat; 900 } /* end tw_wl_start */ 901 902 903 /* 904 * Return the next word from the word list 905 */ 906 /*ARGSUSED*/ 907 Char * 908 tw_wl_next(dir, flags) 909 Char *dir; 910 int *flags; 911 { 912 USE(flags); 913 if (tw_word == NULL || tw_word[0] == '\0') 914 return NULL; 915 916 while (*tw_word && Isspace(*tw_word)) tw_word++; 917 918 for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++) 919 continue; 920 if (*tw_word) 921 *tw_word++ = '\0'; 922 return *dir ? dir : NULL; 923 } /* end tw_wl_next */ 924 925 926 /* tw_bind_start(): 927 * Begin the list of the shell bindings 928 */ 929 /*ARGSUSED*/ 930 void 931 tw_bind_start(dfd, pat) 932 DIR *dfd; 933 Char *pat; 934 { 935 USE(pat); 936 SETDIR(dfd) 937 tw_bind = FuncNames; 938 } /* end tw_bind_start */ 939 940 941 /* tw_bind_next(): 942 * Begin the list of the shell bindings 943 */ 944 /*ARGSUSED*/ 945 Char * 946 tw_bind_next(dir, flags) 947 Char *dir; 948 int *flags; 949 { 950 char *ptr; 951 USE(flags); 952 if (tw_bind && tw_bind->name) { 953 for (ptr = tw_bind->name, dir = tw_retname; 954 (*dir++ = (Char) *ptr++) != '\0';) 955 continue; 956 tw_bind++; 957 return(tw_retname); 958 } 959 return NULL; 960 } /* end tw_bind_next */ 961 962 963 /* tw_limit_start(): 964 * Begin the list of the shell limitings 965 */ 966 /*ARGSUSED*/ 967 void 968 tw_limit_start(dfd, pat) 969 DIR *dfd; 970 Char *pat; 971 { 972 USE(pat); 973 SETDIR(dfd) 974 #ifndef HAVENOLIMIT 975 tw_limit = limits; 976 #endif /* ! HAVENOLIMIT */ 977 } /* end tw_limit_start */ 978 979 980 /* tw_limit_next(): 981 * Begin the list of the shell limitings 982 */ 983 /*ARGSUSED*/ 984 Char * 985 tw_limit_next(dir, flags) 986 Char *dir; 987 int *flags; 988 { 989 #ifndef HAVENOLIMIT 990 char *ptr; 991 if (tw_limit && tw_limit->limname) { 992 for (ptr = tw_limit->limname, dir = tw_retname; 993 (*dir++ = (Char) *ptr++) != '\0';) 994 continue; 995 tw_limit++; 996 return(tw_retname); 997 } 998 #endif /* ! HAVENOLIMIT */ 999 USE(flags); 1000 return NULL; 1001 } /* end tw_limit_next */ 1002 1003 1004 /* tw_sig_start(): 1005 * Begin the list of the shell sigings 1006 */ 1007 /*ARGSUSED*/ 1008 void 1009 tw_sig_start(dfd, pat) 1010 DIR *dfd; 1011 Char *pat; 1012 { 1013 USE(pat); 1014 SETDIR(dfd) 1015 tw_index = 0; 1016 } /* end tw_sig_start */ 1017 1018 1019 /* tw_sig_next(): 1020 * Begin the list of the shell sigings 1021 */ 1022 /*ARGSUSED*/ 1023 Char * 1024 tw_sig_next(dir, flags) 1025 Char *dir; 1026 int *flags; 1027 { 1028 char *ptr; 1029 extern int nsig; 1030 USE(flags); 1031 for (;tw_index < nsig; tw_index++) { 1032 1033 if (mesg[tw_index].iname == NULL) 1034 continue; 1035 1036 for (ptr = mesg[tw_index].iname, dir = tw_retname; 1037 (*dir++ = (Char) *ptr++) != '\0';) 1038 continue; 1039 tw_index++; 1040 return(tw_retname); 1041 } 1042 return NULL; 1043 } /* end tw_sig_next */ 1044 1045 1046 /* tw_job_start(): 1047 * Begin the list of the shell jobings 1048 */ 1049 /*ARGSUSED*/ 1050 void 1051 tw_job_start(dfd, pat) 1052 DIR *dfd; 1053 Char *pat; 1054 { 1055 USE(pat); 1056 SETDIR(dfd) 1057 tw_index = 1; 1058 } /* end tw_job_start */ 1059 1060 1061 /* tw_job_next(): 1062 * Begin the list of the shell jobings 1063 */ 1064 /*ARGSUSED*/ 1065 Char * 1066 tw_job_next(dir, flags) 1067 Char *dir; 1068 int *flags; 1069 { 1070 Char *ptr; 1071 struct process *j; 1072 1073 USE(flags); 1074 for (;tw_index <= pmaxindex; tw_index++) { 1075 for (j = proclist.p_next; j != NULL; j = j->p_next) 1076 if (j->p_index == tw_index && j->p_procid == j->p_jobid) 1077 break; 1078 if (j == NULL) 1079 continue; 1080 for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';) 1081 continue; 1082 *dir = '\0'; 1083 tw_index++; 1084 return(tw_retname); 1085 } 1086 return NULL; 1087 } /* end tw_job_next */ 1088