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