tw.init.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/tw.init.c,v 3.29 2002/06/25 19:02:12 christos Exp $ */ 259243Sobrien/* 359243Sobrien * tw.init.c: Handle lists of things to complete 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35100616SmpRCSID("$Id: tw.init.c,v 3.29 2002/06/25 19:02:12 christos Exp $") 3659243Sobrien 3759243Sobrien#include "tw.h" 3859243Sobrien#include "ed.h" 3959243Sobrien#include "tc.h" 4059243Sobrien#include "sh.proc.h" 4159243Sobrien 4259243Sobrien#if !defined(NSIG) && defined(SIGMAX) 4359243Sobrien# define NSIG (SIGMAX+1) 4459243Sobrien#endif /* !NSIG && SIGMAX */ 4559243Sobrien#if !defined(NSIG) && defined(_NSIG) 4659243Sobrien# define NSIG _NSIG 4759243Sobrien#endif /* !NSIG && _NSIG */ 4859243Sobrien 4959243Sobrien#define TW_INCR 128 5059243Sobrien 5159243Sobrientypedef struct { 5259243Sobrien Char **list, /* List of command names */ 5359243Sobrien *buff; /* Space holding command names */ 5459243Sobrien int nlist, /* Number of items */ 5559243Sobrien nbuff, /* Current space in name buf */ 5659243Sobrien tlist, /* Total space in list */ 5759243Sobrien tbuff; /* Total space in name buf */ 5859243Sobrien} stringlist_t; 5959243Sobrien 6059243Sobrien 6159243Sobrienstatic struct varent *tw_vptr = NULL; /* Current shell variable */ 6259243Sobrienstatic Char **tw_env = NULL; /* Current environment variable */ 6359243Sobrienstatic Char *tw_word; /* Current word pointer */ 6459243Sobrienstatic struct KeyFuncs *tw_bind = NULL; /* List of the bindings */ 6559243Sobrien#ifndef HAVENOLIMIT 6659243Sobrienstatic struct limits *tw_limit = NULL; /* List of the resource limits */ 6759243Sobrien#endif /* HAVENOLIMIT */ 6859243Sobrienstatic int tw_index = 0; /* signal and job index */ 6959243Sobrienstatic DIR *tw_dir_fd = NULL; /* Current directory descriptor */ 7059243Sobrienstatic Char tw_retname[MAXPATHLEN+1]; /* Return buffer */ 7159243Sobrienstatic int tw_cmd_got = 0; /* What we need to do */ 7259243Sobrienstatic stringlist_t tw_cmd = { NULL, NULL, 0, 0, 0, 0 }; 7359243Sobrienstatic stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 }; 7459243Sobrien#define TW_FL_CMD 0x01 7559243Sobrien#define TW_FL_ALIAS 0x02 7659243Sobrien#define TW_FL_BUILTIN 0x04 7759243Sobrien#define TW_FL_SORT 0x08 7859243Sobrien#define TW_FL_REL 0x10 7959243Sobrien 8059243Sobrienstatic struct { /* Current element pointer */ 8159243Sobrien int cur; /* Current element number */ 8259243Sobrien Char **pathv; /* Current element in path */ 8359243Sobrien DIR *dfd; /* Current directory descriptor */ 8459243Sobrien} tw_cmd_state; 8559243Sobrien 8659243Sobrien 8759243Sobrien#ifdef BSDSIGS 8859243Sobrienstatic sigmask_t tw_omask; 8959243Sobrien# define TW_HOLD() tw_omask = sigblock(sigmask(SIGINT)) 9059243Sobrien# define TW_RELS() (void) sigsetmask(tw_omask) 9159243Sobrien#else /* !BSDSIGS */ 9259243Sobrien# define TW_HOLD() (void) sighold(SIGINT) 9359243Sobrien# define TW_RELS() (void) sigrelse(SIGINT) 9459243Sobrien#endif /* BSDSIGS */ 9559243Sobrien 9659243Sobrien#define SETDIR(dfd) \ 9759243Sobrien { \ 9859243Sobrien tw_dir_fd = dfd; \ 9959243Sobrien if (tw_dir_fd != NULL) \ 10059243Sobrien rewinddir(tw_dir_fd); \ 10159243Sobrien } 10259243Sobrien 10359243Sobrien#define CLRDIR(dfd) \ 10459243Sobrien if (dfd != NULL) { \ 10559243Sobrien TW_HOLD(); \ 10659243Sobrien (void) closedir(dfd); \ 10759243Sobrien dfd = NULL; \ 10859243Sobrien TW_RELS(); \ 10959243Sobrien } 11059243Sobrien 11159243Sobrienstatic Char *tw_str_add __P((stringlist_t *, int)); 11259243Sobrienstatic void tw_str_free __P((stringlist_t *)); 11359243Sobrienstatic Char *tw_dir_next __P((DIR *)); 11459243Sobrienstatic void tw_cmd_add __P((Char *name)); 11559243Sobrienstatic void tw_cmd_cmd __P((void)); 11659243Sobrienstatic void tw_cmd_builtin __P((void)); 11759243Sobrienstatic void tw_cmd_alias __P((void)); 11859243Sobrienstatic void tw_cmd_sort __P((void)); 11959243Sobrienstatic void tw_vptr_start __P((struct varent *)); 12059243Sobrien 12159243Sobrien 12259243Sobrien/* tw_str_add(): 12359243Sobrien * Add an item to the string list 12459243Sobrien */ 12559243Sobrienstatic Char * 12659243Sobrientw_str_add(sl, len) 12759243Sobrien stringlist_t *sl; 12859243Sobrien int len; 12959243Sobrien{ 13059243Sobrien Char *ptr; 13159243Sobrien 13259243Sobrien if (sl->tlist <= sl->nlist) { 13359243Sobrien TW_HOLD(); 13459243Sobrien sl->tlist += TW_INCR; 13559243Sobrien sl->list = sl->list ? 13659243Sobrien (Char **) xrealloc((ptr_t) sl->list, 13759243Sobrien (size_t) (sl->tlist * sizeof(Char *))) : 13859243Sobrien (Char **) xmalloc((size_t) (sl->tlist * sizeof(Char *))); 13959243Sobrien TW_RELS(); 14059243Sobrien } 14159243Sobrien if (sl->tbuff <= sl->nbuff + len) { 14259243Sobrien int i; 14359243Sobrien ptr = sl->buff; 14459243Sobrien 14559243Sobrien TW_HOLD(); 14659243Sobrien sl->tbuff += TW_INCR + len; 14759243Sobrien sl->buff = sl->buff ? 14859243Sobrien (Char *) xrealloc((ptr_t) sl->buff, 14959243Sobrien (size_t) (sl->tbuff * sizeof(Char))) : 15059243Sobrien (Char *) xmalloc((size_t) (sl->tbuff * sizeof(Char))); 15159243Sobrien /* Re-thread the new pointer list, if changed */ 15259243Sobrien if (ptr != NULL && ptr != sl->buff) { 15359243Sobrien int offs = (int) (sl->buff - ptr); 15459243Sobrien for (i = 0; i < sl->nlist; i++) 15559243Sobrien sl->list[i] += offs; 15659243Sobrien } 15759243Sobrien TW_RELS(); 15859243Sobrien } 15959243Sobrien ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff]; 16059243Sobrien sl->nbuff += len; 16159243Sobrien return ptr; 16259243Sobrien} /* tw_str_add */ 16359243Sobrien 16459243Sobrien 16559243Sobrien/* tw_str_free(): 16659243Sobrien * Free a stringlist 16759243Sobrien */ 16859243Sobrienstatic void 16959243Sobrientw_str_free(sl) 17059243Sobrien stringlist_t *sl; 17159243Sobrien{ 17259243Sobrien TW_HOLD(); 17359243Sobrien if (sl->list) { 17459243Sobrien xfree((ptr_t) sl->list); 17559243Sobrien sl->list = NULL; 17659243Sobrien sl->tlist = sl->nlist = 0; 17759243Sobrien } 17859243Sobrien if (sl->buff) { 17959243Sobrien xfree((ptr_t) sl->buff); 18059243Sobrien sl->buff = NULL; 18159243Sobrien sl->tbuff = sl->nbuff = 0; 18259243Sobrien } 18359243Sobrien TW_RELS(); 18459243Sobrien} /* end tw_str_free */ 18559243Sobrien 18659243Sobrien 18759243Sobrienstatic Char * 18859243Sobrientw_dir_next(dfd) 18959243Sobrien DIR *dfd; 19059243Sobrien{ 19159243Sobrien register struct dirent *dirp; 19259243Sobrien 19359243Sobrien if (dfd == NULL) 19459243Sobrien return NULL; 19559243Sobrien 19659243Sobrien if ((dirp = readdir(dfd)) != NULL) { 19759243Sobrien (void) Strcpy(tw_retname, str2short(dirp->d_name)); 19859243Sobrien return (tw_retname); 19959243Sobrien } 20059243Sobrien return NULL; 20159243Sobrien} /* end tw_dir_next */ 20259243Sobrien 20359243Sobrien 20459243Sobrien/* tw_cmd_add(): 20559243Sobrien * Add the name to the command list 20659243Sobrien */ 20759243Sobrienstatic void 20859243Sobrientw_cmd_add(name) 20959243Sobrien Char *name; 21059243Sobrien{ 21159243Sobrien int len; 21259243Sobrien 21359243Sobrien len = (int) Strlen(name) + 2; 21459243Sobrien (void) Strcpy(tw_str_add(&tw_cmd, len), name); 21559243Sobrien} /* end tw_cmd_add */ 21659243Sobrien 21759243Sobrien 21859243Sobrien/* tw_cmd_free(): 21959243Sobrien * Free the command list 22059243Sobrien */ 22159243Sobrienvoid 22259243Sobrientw_cmd_free() 22359243Sobrien{ 22459243Sobrien CLRDIR(tw_dir_fd) 22559243Sobrien tw_str_free(&tw_cmd); 22659243Sobrien tw_cmd_got = 0; 22759243Sobrien} /* end tw_cmd_free */ 22859243Sobrien 22959243Sobrien/* tw_cmd_cmd(): 23059243Sobrien * Add system commands to the command list 23159243Sobrien */ 23259243Sobrienstatic void 23359243Sobrientw_cmd_cmd() 23459243Sobrien{ 23559243Sobrien register DIR *dirp; 23659243Sobrien register struct dirent *dp; 23759243Sobrien register Char *dir = NULL, *name; 23859243Sobrien register Char **pv; 23959243Sobrien struct varent *v = adrof(STRpath); 24059243Sobrien struct varent *recexec = adrof(STRrecognize_only_executables); 24159243Sobrien int len; 24259243Sobrien 24359243Sobrien 244100616Smp if (v == NULL || v->vec == NULL) /* if no path */ 24559243Sobrien return; 24659243Sobrien 24759243Sobrien for (pv = v->vec; *pv; pv++) { 24859243Sobrien if (pv[0][0] != '/') { 24959243Sobrien tw_cmd_got |= TW_FL_REL; 25059243Sobrien continue; 25159243Sobrien } 25259243Sobrien 25359243Sobrien if ((dirp = opendir(short2str(*pv))) == NULL) 25459243Sobrien continue; 25559243Sobrien 25659243Sobrien if (recexec) 25759243Sobrien dir = Strspl(*pv, STRslash); 25859243Sobrien while ((dp = readdir(dirp)) != NULL) { 25969408Sache#if defined(_UWIN) || defined(__CYGWIN__) 26069408Sache /* Turn foo.{exe,com,bat} into foo since UWIN's readdir returns 26169408Sache * the file with the .exe, .com, .bat extension 26269408Sache */ 26369408Sache size_t ext = strlen(dp->d_name) - 4; 26469408Sache if ((ext > 0) && (strcmp(&dp->d_name[ext], ".exe") == 0 || 26569408Sache strcmp(&dp->d_name[ext], ".bat") == 0 || 26669408Sache strcmp(&dp->d_name[ext], ".com") == 0)) 26769408Sache dp->d_name[ext] = '\0'; 26869408Sache#endif /* _UWIN || __CYGWIN__ */ 26959243Sobrien /* the call to executable() may make this a bit slow */ 27059243Sobrien name = str2short(dp->d_name); 27159243Sobrien if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0))) 27259243Sobrien continue; 27359243Sobrien len = (int) Strlen(name) + 2; 27459243Sobrien if (name[0] == '#' || /* emacs temp files */ 27559243Sobrien name[0] == '.' || /* .files */ 27659243Sobrien name[len - 3] == '~' || /* emacs backups */ 27759243Sobrien name[len - 3] == '%') /* textedit backups */ 27859243Sobrien continue; /* Ignore! */ 27959243Sobrien tw_cmd_add(name); 28059243Sobrien } 28159243Sobrien (void) closedir(dirp); 28259243Sobrien if (recexec) 28359243Sobrien xfree((ptr_t) dir); 28459243Sobrien } 28559243Sobrien} /* end tw_cmd_cmd */ 28659243Sobrien 28759243Sobrien 28859243Sobrien/* tw_cmd_builtin(): 28959243Sobrien * Add builtins to the command list 29059243Sobrien */ 29159243Sobrienstatic void 29259243Sobrientw_cmd_builtin() 29359243Sobrien{ 29459243Sobrien register struct biltins *bptr; 29559243Sobrien 29659243Sobrien for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) 29759243Sobrien if (bptr->bname) 29859243Sobrien tw_cmd_add(str2short(bptr->bname)); 29969408Sache#ifdef WINNT_NATIVE 30059243Sobrien for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) 30159243Sobrien if (bptr->bname) 30259243Sobrien tw_cmd_add(str2short(bptr->bname)); 30369408Sache#endif /* WINNT_NATIVE*/ 30459243Sobrien} /* end tw_cmd_builtin */ 30559243Sobrien 30659243Sobrien 30759243Sobrien/* tw_cmd_alias(): 30859243Sobrien * Add aliases to the command list 30959243Sobrien */ 31059243Sobrienstatic void 31159243Sobrientw_cmd_alias() 31259243Sobrien{ 31359243Sobrien register struct varent *p; 31459243Sobrien register struct varent *c; 31559243Sobrien 31659243Sobrien p = &aliases; 31759243Sobrien for (;;) { 31859243Sobrien while (p->v_left) 31959243Sobrien p = p->v_left; 32059243Sobrienx: 32159243Sobrien if (p->v_parent == 0) /* is it the header? */ 32259243Sobrien return; 32359243Sobrien if (p->v_name) 32459243Sobrien tw_cmd_add(p->v_name); 32559243Sobrien if (p->v_right) { 32659243Sobrien p = p->v_right; 32759243Sobrien continue; 32859243Sobrien } 32959243Sobrien do { 33059243Sobrien c = p; 33159243Sobrien p = p->v_parent; 33259243Sobrien } while (p->v_right == c); 33359243Sobrien goto x; 33459243Sobrien } 33559243Sobrien} /* end tw_cmd_alias */ 33659243Sobrien 33759243Sobrien 33859243Sobrien/* tw_cmd_sort(): 33959243Sobrien * Sort the command list removing duplicate elements 34059243Sobrien */ 34159243Sobrienstatic void 34259243Sobrientw_cmd_sort() 34359243Sobrien{ 34459243Sobrien int fwd, i; 34559243Sobrien 34659243Sobrien TW_HOLD(); 34759243Sobrien /* sort the list. */ 34859243Sobrien qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *), 34959243Sobrien (int (*) __P((const void *, const void *))) fcompare); 35059243Sobrien 35159243Sobrien /* get rid of multiple entries */ 35259243Sobrien for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) { 35359243Sobrien if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */ 35459243Sobrien fwd++; /* increase the forward ref. count */ 35559243Sobrien else if (fwd) 35659243Sobrien tw_cmd.list[i - fwd] = tw_cmd.list[i]; 35759243Sobrien } 35859243Sobrien /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */ 35959243Sobrien if (fwd) 36059243Sobrien tw_cmd.list[i - fwd] = tw_cmd.list[i]; 36159243Sobrien tw_cmd.nlist -= fwd; 36259243Sobrien TW_RELS(); 36359243Sobrien} /* end tw_cmd_sort */ 36459243Sobrien 36559243Sobrien 36659243Sobrien/* tw_cmd_start(): 36759243Sobrien * Get the command list and sort it, if not done yet. 36859243Sobrien * Reset the current pointer to the beginning of the command list 36959243Sobrien */ 37059243Sobrien/*ARGSUSED*/ 37159243Sobrienvoid 37259243Sobrientw_cmd_start(dfd, pat) 37359243Sobrien DIR *dfd; 37459243Sobrien Char *pat; 37559243Sobrien{ 37659243Sobrien static Char *defpath[] = { STRNULL, 0 }; 37759243Sobrien USE(pat); 37859243Sobrien SETDIR(dfd) 37959243Sobrien if ((tw_cmd_got & TW_FL_CMD) == 0) { 38059243Sobrien tw_cmd_free(); 38159243Sobrien tw_cmd_cmd(); 38259243Sobrien tw_cmd_got |= TW_FL_CMD; 38359243Sobrien } 38459243Sobrien if ((tw_cmd_got & TW_FL_ALIAS) == 0) { 38559243Sobrien tw_cmd_alias(); 38659243Sobrien tw_cmd_got &= ~TW_FL_SORT; 38759243Sobrien tw_cmd_got |= TW_FL_ALIAS; 38859243Sobrien } 38959243Sobrien if ((tw_cmd_got & TW_FL_BUILTIN) == 0) { 39059243Sobrien tw_cmd_builtin(); 39159243Sobrien tw_cmd_got &= ~TW_FL_SORT; 39259243Sobrien tw_cmd_got |= TW_FL_BUILTIN; 39359243Sobrien } 39459243Sobrien if ((tw_cmd_got & TW_FL_SORT) == 0) { 39559243Sobrien tw_cmd_sort(); 39659243Sobrien tw_cmd_got |= TW_FL_SORT; 39759243Sobrien } 39859243Sobrien 39959243Sobrien tw_cmd_state.cur = 0; 40059243Sobrien CLRDIR(tw_cmd_state.dfd) 40159243Sobrien if (tw_cmd_got & TW_FL_REL) { 40259243Sobrien struct varent *vp = adrof(STRpath); 40359243Sobrien if (vp && vp->vec) 40459243Sobrien tw_cmd_state.pathv = vp->vec; 40559243Sobrien else 40659243Sobrien tw_cmd_state.pathv = defpath; 40759243Sobrien } 40859243Sobrien else 40959243Sobrien tw_cmd_state.pathv = defpath; 41059243Sobrien} /* tw_cmd_start */ 41159243Sobrien 41259243Sobrien 41359243Sobrien/* tw_cmd_next(): 41459243Sobrien * Return the next element in the command list or 41559243Sobrien * Look for commands in the relative path components 41659243Sobrien */ 41759243SobrienChar * 41859243Sobrientw_cmd_next(dir, flags) 41959243Sobrien Char *dir; 42059243Sobrien int *flags; 42159243Sobrien{ 42259243Sobrien Char *ptr = NULL; 42359243Sobrien 42459243Sobrien if (tw_cmd_state.cur < tw_cmd.nlist) { 42559243Sobrien *flags = TW_DIR_OK; 42659243Sobrien return tw_cmd.list[tw_cmd_state.cur++]; 42759243Sobrien } 42859243Sobrien 42959243Sobrien /* 43059243Sobrien * We need to process relatives in the path. 43159243Sobrien */ 43259243Sobrien while (((tw_cmd_state.dfd == NULL) || 43359243Sobrien ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) && 43459243Sobrien (*tw_cmd_state.pathv != NULL)) { 43559243Sobrien 43659243Sobrien CLRDIR(tw_cmd_state.dfd) 43759243Sobrien 43859243Sobrien while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/') 43959243Sobrien tw_cmd_state.pathv++; 44059243Sobrien if ((ptr = *tw_cmd_state.pathv) != 0) { 44159243Sobrien /* 44259243Sobrien * We complete directories only on '.' should that 44359243Sobrien * be changed? 44459243Sobrien */ 44559243Sobrien if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) { 44659243Sobrien *dir = '\0'; 44759243Sobrien tw_cmd_state.dfd = opendir("."); 44859243Sobrien *flags = TW_DIR_OK | TW_EXEC_CHK; 44959243Sobrien } 45059243Sobrien else { 45159243Sobrien copyn(dir, *tw_cmd_state.pathv, FILSIZ); 45259243Sobrien catn(dir, STRslash, FILSIZ); 45359243Sobrien tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv)); 45459243Sobrien *flags = TW_EXEC_CHK; 45559243Sobrien } 45659243Sobrien tw_cmd_state.pathv++; 45759243Sobrien } 45859243Sobrien } 45959243Sobrien return ptr; 46059243Sobrien} /* end tw_cmd_next */ 46159243Sobrien 46259243Sobrien 46359243Sobrien/* tw_vptr_start(): 46459243Sobrien * Find the first variable in the variable list 46559243Sobrien */ 46659243Sobrienstatic void 46759243Sobrientw_vptr_start(c) 46859243Sobrien struct varent *c; 46959243Sobrien{ 47059243Sobrien tw_vptr = c; /* start at beginning of variable list */ 47159243Sobrien 47259243Sobrien for (;;) { 47359243Sobrien while (tw_vptr->v_left) 47459243Sobrien tw_vptr = tw_vptr->v_left; 47559243Sobrienx: 47659243Sobrien if (tw_vptr->v_parent == 0) { /* is it the header? */ 47759243Sobrien tw_vptr = NULL; 47859243Sobrien return; 47959243Sobrien } 48059243Sobrien if (tw_vptr->v_name) 48159243Sobrien return; /* found first one */ 48259243Sobrien if (tw_vptr->v_right) { 48359243Sobrien tw_vptr = tw_vptr->v_right; 48459243Sobrien continue; 48559243Sobrien } 48659243Sobrien do { 48759243Sobrien c = tw_vptr; 48859243Sobrien tw_vptr = tw_vptr->v_parent; 48959243Sobrien } while (tw_vptr->v_right == c); 49059243Sobrien goto x; 49159243Sobrien } 49259243Sobrien} /* end tw_shvar_start */ 49359243Sobrien 49459243Sobrien 49559243Sobrien/* tw_shvar_next(): 49659243Sobrien * Return the next shell variable 49759243Sobrien */ 49859243Sobrien/*ARGSUSED*/ 49959243SobrienChar * 50059243Sobrientw_shvar_next(dir, flags) 50159243Sobrien Char *dir; 50259243Sobrien int *flags; 50359243Sobrien{ 50459243Sobrien register struct varent *p; 50559243Sobrien register struct varent *c; 50659243Sobrien register Char *cp; 50759243Sobrien 50859243Sobrien USE(flags); 50959243Sobrien USE(dir); 51059243Sobrien if ((p = tw_vptr) == NULL) 51159243Sobrien return (NULL); /* just in case */ 51259243Sobrien 51359243Sobrien cp = p->v_name; /* we know that this name is here now */ 51459243Sobrien 51559243Sobrien /* now find the next one */ 51659243Sobrien for (;;) { 51759243Sobrien if (p->v_right) { /* if we can go right */ 51859243Sobrien p = p->v_right; 51959243Sobrien while (p->v_left) 52059243Sobrien p = p->v_left; 52159243Sobrien } 52259243Sobrien else { /* else go up */ 52359243Sobrien do { 52459243Sobrien c = p; 52559243Sobrien p = p->v_parent; 52659243Sobrien } while (p->v_right == c); 52759243Sobrien } 52859243Sobrien if (p->v_parent == 0) { /* is it the header? */ 52959243Sobrien tw_vptr = NULL; 53059243Sobrien return (cp); 53159243Sobrien } 53259243Sobrien if (p->v_name) { 53359243Sobrien tw_vptr = p; /* save state for the next call */ 53459243Sobrien return (cp); 53559243Sobrien } 53659243Sobrien } 53759243Sobrien} /* end tw_shvar_next */ 53859243Sobrien 53959243Sobrien 54059243Sobrien/* tw_envvar_next(): 54159243Sobrien * Return the next environment variable 54259243Sobrien */ 54359243Sobrien/*ARGSUSED*/ 54459243SobrienChar * 54559243Sobrientw_envvar_next(dir, flags) 54659243Sobrien Char *dir; 54759243Sobrien int *flags; 54859243Sobrien{ 54959243Sobrien Char *ps, *pd; 55059243Sobrien 55159243Sobrien USE(flags); 55259243Sobrien USE(dir); 55359243Sobrien if (tw_env == NULL || *tw_env == NULL) 55459243Sobrien return (NULL); 55559243Sobrien for (ps = *tw_env, pd = tw_retname; 55659243Sobrien *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++) 55759243Sobrien continue; 55859243Sobrien *pd = '\0'; 55959243Sobrien tw_env++; 56059243Sobrien return (tw_retname); 56159243Sobrien} /* end tw_envvar_next */ 56259243Sobrien 56359243Sobrien 56459243Sobrien/* tw_var_start(): 56559243Sobrien * Begin the list of the shell and environment variables 56659243Sobrien */ 56759243Sobrien/*ARGSUSED*/ 56859243Sobrienvoid 56959243Sobrientw_var_start(dfd, pat) 57059243Sobrien DIR *dfd; 57159243Sobrien Char *pat; 57259243Sobrien{ 57359243Sobrien USE(pat); 57459243Sobrien SETDIR(dfd) 57559243Sobrien tw_vptr_start(&shvhed); 57659243Sobrien tw_env = STR_environ; 57759243Sobrien} /* end tw_var_start */ 57859243Sobrien 57959243Sobrien 58059243Sobrien/* tw_alias_start(): 58159243Sobrien * Begin the list of the shell aliases 58259243Sobrien */ 58359243Sobrien/*ARGSUSED*/ 58459243Sobrienvoid 58559243Sobrientw_alias_start(dfd, pat) 58659243Sobrien DIR *dfd; 58759243Sobrien Char *pat; 58859243Sobrien{ 58959243Sobrien USE(pat); 59059243Sobrien SETDIR(dfd) 59159243Sobrien tw_vptr_start(&aliases); 59259243Sobrien tw_env = NULL; 59359243Sobrien} /* tw_alias_start */ 59459243Sobrien 59559243Sobrien 59659243Sobrien/* tw_complete_start(): 59759243Sobrien * Begin the list of completions 59859243Sobrien */ 59959243Sobrien/*ARGSUSED*/ 60059243Sobrienvoid 60159243Sobrientw_complete_start(dfd, pat) 60259243Sobrien DIR *dfd; 60359243Sobrien Char *pat; 60459243Sobrien{ 60559243Sobrien extern struct varent completions; 60659243Sobrien 60759243Sobrien USE(pat); 60859243Sobrien SETDIR(dfd) 60959243Sobrien tw_vptr_start(&completions); 61059243Sobrien tw_env = NULL; 61159243Sobrien} /* end tw_complete_start */ 61259243Sobrien 61359243Sobrien 61459243Sobrien/* tw_var_next(): 61559243Sobrien * Return the next shell or environment variable 61659243Sobrien */ 61759243SobrienChar * 61859243Sobrientw_var_next(dir, flags) 61959243Sobrien Char *dir; 62059243Sobrien int *flags; 62159243Sobrien{ 62259243Sobrien Char *ptr = NULL; 62359243Sobrien 62459243Sobrien if (tw_vptr) 62559243Sobrien ptr = tw_shvar_next(dir, flags); 62659243Sobrien if (!ptr && tw_env) 62759243Sobrien ptr = tw_envvar_next(dir, flags); 62859243Sobrien return ptr; 62959243Sobrien} /* end tw_var_next */ 63059243Sobrien 63159243Sobrien 63259243Sobrien/* tw_logname_start(): 63359243Sobrien * Initialize lognames to the beginning of the list 63459243Sobrien */ 63559243Sobrien/*ARGSUSED*/ 63659243Sobrienvoid 63759243Sobrientw_logname_start(dfd, pat) 63859243Sobrien DIR *dfd; 63959243Sobrien Char *pat; 64059243Sobrien{ 64159243Sobrien USE(pat); 64259243Sobrien SETDIR(dfd) 64369408Sache#if !defined(_VMS_POSIX) && !defined(WINNT_NATIVE) 64459243Sobrien (void) setpwent(); /* Open passwd file */ 64569408Sache#endif /* !_VMS_POSIX && !WINNT_NATIVE */ 64659243Sobrien} /* end tw_logname_start */ 64759243Sobrien 64859243Sobrien 64959243Sobrien/* tw_logname_next(): 65059243Sobrien * Return the next entry from the passwd file 65159243Sobrien */ 65259243Sobrien/*ARGSUSED*/ 65359243SobrienChar * 65459243Sobrientw_logname_next(dir, flags) 65559243Sobrien Char *dir; 65659243Sobrien int *flags; 65759243Sobrien{ 65859243Sobrien static Char retname[MAXPATHLEN]; 65959243Sobrien struct passwd *pw; 66059243Sobrien /* 66159243Sobrien * We don't want to get interrupted inside getpwent() 66259243Sobrien * because the yellow pages code is not interruptible, 66359243Sobrien * and if we call endpwent() immediatetely after 66459243Sobrien * (in pintr()) we may be freeing an invalid pointer 66559243Sobrien */ 66659243Sobrien USE(flags); 66759243Sobrien USE(dir); 66859243Sobrien TW_HOLD(); 66969408Sache#if !defined(_VMS_POSIX) && !defined(WINNT_NATIVE) 67059243Sobrien /* ISC does not declare getpwent()? */ 67159243Sobrien pw = (struct passwd *) getpwent(); 67269408Sache#else /* _VMS_POSIX || WINNT_NATIVE */ 67359243Sobrien pw = NULL; 67469408Sache#endif /* !_VMS_POSIX && !WINNT_NATIVE */ 67559243Sobrien TW_RELS(); 67659243Sobrien 67759243Sobrien if (pw == NULL) { 67859243Sobrien#ifdef YPBUGS 67959243Sobrien fix_yp_bugs(); 68059243Sobrien#endif 68159243Sobrien return (NULL); 68259243Sobrien } 68359243Sobrien (void) Strcpy(retname, str2short(pw->pw_name)); 68459243Sobrien return (retname); 68559243Sobrien} /* end tw_logname_next */ 68659243Sobrien 68759243Sobrien 68859243Sobrien/* tw_logname_end(): 68959243Sobrien * Close the passwd file to finish the logname list 69059243Sobrien */ 69159243Sobrienvoid 69259243Sobrientw_logname_end() 69359243Sobrien{ 69459243Sobrien#ifdef YPBUGS 69559243Sobrien fix_yp_bugs(); 69659243Sobrien#endif 69769408Sache#if !defined(_VMS_POSIX) && !defined(WINNT_NATIVE) 69859243Sobrien (void) endpwent(); 69969408Sache#endif /* !_VMS_POSIX && !WINNT_NATIVE */ 70059243Sobrien} /* end tw_logname_end */ 70159243Sobrien 70259243Sobrien 70359243Sobrien/* tw_grpname_start(): 70459243Sobrien * Initialize grpnames to the beginning of the list 70559243Sobrien */ 70659243Sobrien/*ARGSUSED*/ 70759243Sobrienvoid 70859243Sobrientw_grpname_start(dfd, pat) 70959243Sobrien DIR *dfd; 71059243Sobrien Char *pat; 71159243Sobrien{ 71259243Sobrien USE(pat); 71359243Sobrien SETDIR(dfd) 71469408Sache#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) 71559243Sobrien (void) setgrent(); /* Open group file */ 71669408Sache#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */ 71759243Sobrien} /* end tw_grpname_start */ 71859243Sobrien 71959243Sobrien 72059243Sobrien/* tw_grpname_next(): 72159243Sobrien * Return the next entry from the group file 72259243Sobrien */ 72359243Sobrien/*ARGSUSED*/ 72459243SobrienChar * 72559243Sobrientw_grpname_next(dir, flags) 72659243Sobrien Char *dir; 72759243Sobrien int *flags; 72859243Sobrien{ 72959243Sobrien static Char retname[MAXPATHLEN]; 73059243Sobrien struct group *gr; 73159243Sobrien /* 73259243Sobrien * We don't want to get interrupted inside getgrent() 73359243Sobrien * because the yellow pages code is not interruptible, 73459243Sobrien * and if we call endgrent() immediatetely after 73559243Sobrien * (in pintr()) we may be freeing an invalid pointer 73659243Sobrien */ 73759243Sobrien USE(flags); 73859243Sobrien USE(dir); 73959243Sobrien TW_HOLD(); 74069408Sache#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) 74159243Sobrien gr = (struct group *) getgrent(); 74269408Sache#else /* _VMS_POSIX || _OSD_POSIX || WINNT_NATIVE */ 74359243Sobrien gr = NULL; 74469408Sache#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */ 74559243Sobrien TW_RELS(); 74659243Sobrien 74759243Sobrien if (gr == NULL) { 74859243Sobrien#ifdef YPBUGS 74959243Sobrien fix_yp_bugs(); 75059243Sobrien#endif 75159243Sobrien return (NULL); 75259243Sobrien } 75359243Sobrien (void) Strcpy(retname, str2short(gr->gr_name)); 75459243Sobrien return (retname); 75559243Sobrien} /* end tw_grpname_next */ 75659243Sobrien 75759243Sobrien 75859243Sobrien/* tw_grpname_end(): 75959243Sobrien * Close the group file to finish the groupname list 76059243Sobrien */ 76159243Sobrienvoid 76259243Sobrientw_grpname_end() 76359243Sobrien{ 76459243Sobrien#ifdef YPBUGS 76559243Sobrien fix_yp_bugs(); 76659243Sobrien#endif 76769408Sache#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) 76859243Sobrien (void) endgrent(); 76969408Sache#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */ 77059243Sobrien} /* end tw_grpname_end */ 77159243Sobrien 77259243Sobrien/* tw_file_start(): 77359243Sobrien * Initialize the directory for the file list 77459243Sobrien */ 77559243Sobrien/*ARGSUSED*/ 77659243Sobrienvoid 77759243Sobrientw_file_start(dfd, pat) 77859243Sobrien DIR *dfd; 77959243Sobrien Char *pat; 78059243Sobrien{ 78159243Sobrien struct varent *vp; 78259243Sobrien USE(pat); 78359243Sobrien SETDIR(dfd) 78459243Sobrien if ((vp = adrof(STRcdpath)) != NULL) 78559243Sobrien tw_env = vp->vec; 78659243Sobrien} /* end tw_file_start */ 78759243Sobrien 78859243Sobrien 78959243Sobrien/* tw_file_next(): 79059243Sobrien * Return the next file in the directory 79159243Sobrien */ 79259243SobrienChar * 79359243Sobrientw_file_next(dir, flags) 79459243Sobrien Char *dir; 79559243Sobrien int *flags; 79659243Sobrien{ 79759243Sobrien Char *ptr = tw_dir_next(tw_dir_fd); 79859243Sobrien if (ptr == NULL && (*flags & TW_DIR_OK) != 0) { 79959243Sobrien CLRDIR(tw_dir_fd) 80059243Sobrien while (tw_env && *tw_env) 80159243Sobrien if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL) 80259243Sobrien break; 80359243Sobrien else 80459243Sobrien tw_env++; 80559243Sobrien 80659243Sobrien if (tw_dir_fd) { 80759243Sobrien copyn(dir, *tw_env++, MAXPATHLEN); 80859243Sobrien catn(dir, STRslash, MAXPATHLEN); 80959243Sobrien ptr = tw_dir_next(tw_dir_fd); 81059243Sobrien } 81159243Sobrien } 81259243Sobrien return ptr; 81359243Sobrien} /* end tw_file_next */ 81459243Sobrien 81559243Sobrien 81659243Sobrien/* tw_dir_end(): 81759243Sobrien * Clear directory related lists 81859243Sobrien */ 81959243Sobrienvoid 82059243Sobrientw_dir_end() 82159243Sobrien{ 82259243Sobrien CLRDIR(tw_dir_fd) 82359243Sobrien CLRDIR(tw_cmd_state.dfd) 82459243Sobrien} /* end tw_dir_end */ 82559243Sobrien 82659243Sobrien 82759243Sobrien/* tw_item_free(): 82859243Sobrien * Free the item list 82959243Sobrien */ 83059243Sobrienvoid 83159243Sobrientw_item_free() 83259243Sobrien{ 83359243Sobrien tw_str_free(&tw_item); 83459243Sobrien} /* end tw_item_free */ 83559243Sobrien 83659243Sobrien 83759243Sobrien/* tw_item_get(): 83859243Sobrien * Return the list of items 83959243Sobrien */ 84059243SobrienChar ** 84159243Sobrientw_item_get() 84259243Sobrien{ 84359243Sobrien return tw_item.list; 84459243Sobrien} /* end tw_item_get */ 84559243Sobrien 84659243Sobrien 84759243Sobrien/* tw_item_add(): 84859243Sobrien * Return a new item 84959243Sobrien */ 85059243SobrienChar * 85159243Sobrientw_item_add(len) 85259243Sobrien int len; 85359243Sobrien{ 85459243Sobrien return tw_str_add(&tw_item, len); 85559243Sobrien} /* tw_item_add */ 85659243Sobrien 85759243Sobrien 85859243Sobrien/* tw_item_find(): 85959243Sobrien * Find the string if it exists in the item list 86059243Sobrien * end return it. 86159243Sobrien */ 86259243SobrienChar * 86359243Sobrientw_item_find(str) 86459243Sobrien Char *str; 86559243Sobrien{ 86659243Sobrien int i; 86759243Sobrien 86859243Sobrien if (tw_item.list == NULL || str == NULL) 86959243Sobrien return NULL; 87059243Sobrien 87159243Sobrien for (i = 0; i < tw_item.nlist; i++) 87259243Sobrien if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0) 87359243Sobrien return tw_item.list[i]; 87459243Sobrien return NULL; 87559243Sobrien} /* end tw_item_find */ 87659243Sobrien 87759243Sobrien 87859243Sobrien/* tw_vl_start(): 87959243Sobrien * Initialize a variable list 88059243Sobrien */ 88159243Sobrienvoid 88259243Sobrientw_vl_start(dfd, pat) 88359243Sobrien DIR *dfd; 88459243Sobrien Char *pat; 88559243Sobrien{ 88659243Sobrien SETDIR(dfd) 88759243Sobrien if ((tw_vptr = adrof(pat)) != NULL) { 88859243Sobrien tw_env = tw_vptr->vec; 88959243Sobrien tw_vptr = NULL; 89059243Sobrien } 89159243Sobrien else 89259243Sobrien tw_env = NULL; 89359243Sobrien} /* end tw_vl_start */ 89459243Sobrien 89559243Sobrien 89659243Sobrien/* 89759243Sobrien * Initialize a word list 89859243Sobrien */ 89959243Sobrienvoid 90059243Sobrientw_wl_start(dfd, pat) 90159243Sobrien DIR *dfd; 90259243Sobrien Char *pat; 90359243Sobrien{ 90459243Sobrien SETDIR(dfd); 90559243Sobrien tw_word = pat; 90659243Sobrien} /* end tw_wl_start */ 90759243Sobrien 90859243Sobrien 90959243Sobrien/* 91059243Sobrien * Return the next word from the word list 91159243Sobrien */ 91259243Sobrien/*ARGSUSED*/ 91359243SobrienChar * 91459243Sobrientw_wl_next(dir, flags) 91559243Sobrien Char *dir; 91659243Sobrien int *flags; 91759243Sobrien{ 91859243Sobrien USE(flags); 91959243Sobrien if (tw_word == NULL || tw_word[0] == '\0') 92059243Sobrien return NULL; 92159243Sobrien 92259243Sobrien while (*tw_word && Isspace(*tw_word)) tw_word++; 92359243Sobrien 92459243Sobrien for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++) 92559243Sobrien continue; 92659243Sobrien if (*tw_word) 92759243Sobrien *tw_word++ = '\0'; 92859243Sobrien return *dir ? dir : NULL; 92959243Sobrien} /* end tw_wl_next */ 93059243Sobrien 93159243Sobrien 93259243Sobrien/* tw_bind_start(): 93359243Sobrien * Begin the list of the shell bindings 93459243Sobrien */ 93559243Sobrien/*ARGSUSED*/ 93659243Sobrienvoid 93759243Sobrientw_bind_start(dfd, pat) 93859243Sobrien DIR *dfd; 93959243Sobrien Char *pat; 94059243Sobrien{ 94159243Sobrien USE(pat); 94259243Sobrien SETDIR(dfd) 94359243Sobrien tw_bind = FuncNames; 94459243Sobrien} /* end tw_bind_start */ 94559243Sobrien 94659243Sobrien 94759243Sobrien/* tw_bind_next(): 94859243Sobrien * Begin the list of the shell bindings 94959243Sobrien */ 95059243Sobrien/*ARGSUSED*/ 95159243SobrienChar * 95259243Sobrientw_bind_next(dir, flags) 95359243Sobrien Char *dir; 95459243Sobrien int *flags; 95559243Sobrien{ 95659243Sobrien char *ptr; 95759243Sobrien USE(flags); 95859243Sobrien if (tw_bind && tw_bind->name) { 95959243Sobrien for (ptr = tw_bind->name, dir = tw_retname; 96059243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 96159243Sobrien continue; 96259243Sobrien tw_bind++; 96359243Sobrien return(tw_retname); 96459243Sobrien } 96559243Sobrien return NULL; 96659243Sobrien} /* end tw_bind_next */ 96759243Sobrien 96859243Sobrien 96959243Sobrien/* tw_limit_start(): 97059243Sobrien * Begin the list of the shell limitings 97159243Sobrien */ 97259243Sobrien/*ARGSUSED*/ 97359243Sobrienvoid 97459243Sobrientw_limit_start(dfd, pat) 97559243Sobrien DIR *dfd; 97659243Sobrien Char *pat; 97759243Sobrien{ 97859243Sobrien USE(pat); 97959243Sobrien SETDIR(dfd) 98059243Sobrien#ifndef HAVENOLIMIT 98159243Sobrien tw_limit = limits; 98259243Sobrien#endif /* ! HAVENOLIMIT */ 98359243Sobrien} /* end tw_limit_start */ 98459243Sobrien 98559243Sobrien 98659243Sobrien/* tw_limit_next(): 98759243Sobrien * Begin the list of the shell limitings 98859243Sobrien */ 98959243Sobrien/*ARGSUSED*/ 99059243SobrienChar * 99159243Sobrientw_limit_next(dir, flags) 99259243Sobrien Char *dir; 99359243Sobrien int *flags; 99459243Sobrien{ 99559243Sobrien#ifndef HAVENOLIMIT 99659243Sobrien char *ptr; 99759243Sobrien if (tw_limit && tw_limit->limname) { 99859243Sobrien for (ptr = tw_limit->limname, dir = tw_retname; 99959243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 100059243Sobrien continue; 100159243Sobrien tw_limit++; 100259243Sobrien return(tw_retname); 100359243Sobrien } 100459243Sobrien#endif /* ! HAVENOLIMIT */ 100559243Sobrien USE(flags); 100659243Sobrien return NULL; 100759243Sobrien} /* end tw_limit_next */ 100859243Sobrien 100959243Sobrien 101059243Sobrien/* tw_sig_start(): 101159243Sobrien * Begin the list of the shell sigings 101259243Sobrien */ 101359243Sobrien/*ARGSUSED*/ 101459243Sobrienvoid 101559243Sobrientw_sig_start(dfd, pat) 101659243Sobrien DIR *dfd; 101759243Sobrien Char *pat; 101859243Sobrien{ 101959243Sobrien USE(pat); 102059243Sobrien SETDIR(dfd) 102159243Sobrien tw_index = 0; 102259243Sobrien} /* end tw_sig_start */ 102359243Sobrien 102459243Sobrien 102559243Sobrien/* tw_sig_next(): 102659243Sobrien * Begin the list of the shell sigings 102759243Sobrien */ 102859243Sobrien/*ARGSUSED*/ 102959243SobrienChar * 103059243Sobrientw_sig_next(dir, flags) 103159243Sobrien Char *dir; 103259243Sobrien int *flags; 103359243Sobrien{ 103459243Sobrien char *ptr; 103559243Sobrien extern int nsig; 103659243Sobrien USE(flags); 103759243Sobrien for (;tw_index < nsig; tw_index++) { 103859243Sobrien 103959243Sobrien if (mesg[tw_index].iname == NULL) 104059243Sobrien continue; 104159243Sobrien 104259243Sobrien for (ptr = mesg[tw_index].iname, dir = tw_retname; 104359243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 104459243Sobrien continue; 104559243Sobrien tw_index++; 104659243Sobrien return(tw_retname); 104759243Sobrien } 104859243Sobrien return NULL; 104959243Sobrien} /* end tw_sig_next */ 105059243Sobrien 105159243Sobrien 105259243Sobrien/* tw_job_start(): 105359243Sobrien * Begin the list of the shell jobings 105459243Sobrien */ 105559243Sobrien/*ARGSUSED*/ 105659243Sobrienvoid 105759243Sobrientw_job_start(dfd, pat) 105859243Sobrien DIR *dfd; 105959243Sobrien Char *pat; 106059243Sobrien{ 106159243Sobrien USE(pat); 106259243Sobrien SETDIR(dfd) 106359243Sobrien tw_index = 1; 106459243Sobrien} /* end tw_job_start */ 106559243Sobrien 106659243Sobrien 106759243Sobrien/* tw_job_next(): 106859243Sobrien * Begin the list of the shell jobings 106959243Sobrien */ 107059243Sobrien/*ARGSUSED*/ 107159243SobrienChar * 107259243Sobrientw_job_next(dir, flags) 107359243Sobrien Char *dir; 107459243Sobrien int *flags; 107559243Sobrien{ 107659243Sobrien Char *ptr; 107759243Sobrien struct process *j; 107859243Sobrien 107959243Sobrien USE(flags); 108059243Sobrien for (;tw_index <= pmaxindex; tw_index++) { 108159243Sobrien for (j = proclist.p_next; j != NULL; j = j->p_next) 108259243Sobrien if (j->p_index == tw_index && j->p_procid == j->p_jobid) 108359243Sobrien break; 108459243Sobrien if (j == NULL) 108559243Sobrien continue; 108659243Sobrien for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';) 108759243Sobrien continue; 108859243Sobrien *dir = '\0'; 108959243Sobrien tw_index++; 109059243Sobrien return(tw_retname); 109159243Sobrien } 109259243Sobrien return NULL; 109359243Sobrien} /* end tw_job_next */ 1094