tw.init.c revision 59243
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 39RCSID("$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 55typedef 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 65static struct varent *tw_vptr = NULL; /* Current shell variable */ 66static Char **tw_env = NULL; /* Current environment variable */ 67static Char *tw_word; /* Current word pointer */ 68static struct KeyFuncs *tw_bind = NULL; /* List of the bindings */ 69#ifndef HAVENOLIMIT 70static struct limits *tw_limit = NULL; /* List of the resource limits */ 71#endif /* HAVENOLIMIT */ 72static int tw_index = 0; /* signal and job index */ 73static DIR *tw_dir_fd = NULL; /* Current directory descriptor */ 74static Char tw_retname[MAXPATHLEN+1]; /* Return buffer */ 75static int tw_cmd_got = 0; /* What we need to do */ 76static stringlist_t tw_cmd = { NULL, NULL, 0, 0, 0, 0 }; 77static 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 84static 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 92static 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 115static Char *tw_str_add __P((stringlist_t *, int)); 116static void tw_str_free __P((stringlist_t *)); 117static Char *tw_dir_next __P((DIR *)); 118static void tw_cmd_add __P((Char *name)); 119static void tw_cmd_cmd __P((void)); 120static void tw_cmd_builtin __P((void)); 121static void tw_cmd_alias __P((void)); 122static void tw_cmd_sort __P((void)); 123static void tw_vptr_start __P((struct varent *)); 124 125 126/* tw_str_add(): 127 * Add an item to the string list 128 */ 129static Char * 130tw_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 */ 172static void 173tw_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 191static Char * 192tw_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 */ 211static void 212tw_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 */ 225void 226tw_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 */ 236static void 237tw_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 */ 285static void 286tw_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 */ 304static void 305tw_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; 314x: 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 */ 335static void 336tw_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*/ 365void 366tw_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 */ 411Char * 412tw_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 */ 460static void 461tw_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; 469x: 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*/ 493Char * 494tw_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*/ 538Char * 539tw_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*/ 562void 563tw_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*/ 578void 579tw_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*/ 594void 595tw_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 */ 611Char * 612tw_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*/ 630void 631tw_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*/ 647Char * 648tw_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 */ 685void 686tw_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*/ 701void 702tw_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*/ 718Char * 719tw_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 */ 755void 756tw_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*/ 770void 771tw_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 */ 786Char * 787tw_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 */ 813void 814tw_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 */ 824void 825tw_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 */ 834Char ** 835tw_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 */ 844Char * 845tw_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 */ 856Char * 857tw_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 */ 875void 876tw_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 */ 893void 894tw_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*/ 907Char * 908tw_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*/ 930void 931tw_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*/ 945Char * 946tw_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*/ 967void 968tw_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*/ 984Char * 985tw_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*/ 1008void 1009tw_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*/ 1023Char * 1024tw_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*/ 1050void 1051tw_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*/ 1065Char * 1066tw_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