tw.init.c revision 59243
159243Sobrien/* $Header: /src/pub/tcsh/tw.init.c,v 3.25 1998/10/25 15:10:50 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 3959243SobrienRCSID("$Id: tw.init.c,v 3.25 1998/10/25 15:10:50 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) { 26359243Sobrien /* the call to executable() may make this a bit slow */ 26459243Sobrien name = str2short(dp->d_name); 26559243Sobrien if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0))) 26659243Sobrien continue; 26759243Sobrien len = (int) Strlen(name) + 2; 26859243Sobrien if (name[0] == '#' || /* emacs temp files */ 26959243Sobrien name[0] == '.' || /* .files */ 27059243Sobrien name[len - 3] == '~' || /* emacs backups */ 27159243Sobrien name[len - 3] == '%') /* textedit backups */ 27259243Sobrien continue; /* Ignore! */ 27359243Sobrien tw_cmd_add(name); 27459243Sobrien } 27559243Sobrien (void) closedir(dirp); 27659243Sobrien if (recexec) 27759243Sobrien xfree((ptr_t) dir); 27859243Sobrien } 27959243Sobrien} /* end tw_cmd_cmd */ 28059243Sobrien 28159243Sobrien 28259243Sobrien/* tw_cmd_builtin(): 28359243Sobrien * Add builtins to the command list 28459243Sobrien */ 28559243Sobrienstatic void 28659243Sobrientw_cmd_builtin() 28759243Sobrien{ 28859243Sobrien register struct biltins *bptr; 28959243Sobrien 29059243Sobrien for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) 29159243Sobrien if (bptr->bname) 29259243Sobrien tw_cmd_add(str2short(bptr->bname)); 29359243Sobrien#ifdef WINNT 29459243Sobrien for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) 29559243Sobrien if (bptr->bname) 29659243Sobrien tw_cmd_add(str2short(bptr->bname)); 29759243Sobrien#endif /* WINNT*/ 29859243Sobrien} /* end tw_cmd_builtin */ 29959243Sobrien 30059243Sobrien 30159243Sobrien/* tw_cmd_alias(): 30259243Sobrien * Add aliases to the command list 30359243Sobrien */ 30459243Sobrienstatic void 30559243Sobrientw_cmd_alias() 30659243Sobrien{ 30759243Sobrien register struct varent *p; 30859243Sobrien register struct varent *c; 30959243Sobrien 31059243Sobrien p = &aliases; 31159243Sobrien for (;;) { 31259243Sobrien while (p->v_left) 31359243Sobrien p = p->v_left; 31459243Sobrienx: 31559243Sobrien if (p->v_parent == 0) /* is it the header? */ 31659243Sobrien return; 31759243Sobrien if (p->v_name) 31859243Sobrien tw_cmd_add(p->v_name); 31959243Sobrien if (p->v_right) { 32059243Sobrien p = p->v_right; 32159243Sobrien continue; 32259243Sobrien } 32359243Sobrien do { 32459243Sobrien c = p; 32559243Sobrien p = p->v_parent; 32659243Sobrien } while (p->v_right == c); 32759243Sobrien goto x; 32859243Sobrien } 32959243Sobrien} /* end tw_cmd_alias */ 33059243Sobrien 33159243Sobrien 33259243Sobrien/* tw_cmd_sort(): 33359243Sobrien * Sort the command list removing duplicate elements 33459243Sobrien */ 33559243Sobrienstatic void 33659243Sobrientw_cmd_sort() 33759243Sobrien{ 33859243Sobrien int fwd, i; 33959243Sobrien 34059243Sobrien TW_HOLD(); 34159243Sobrien /* sort the list. */ 34259243Sobrien qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *), 34359243Sobrien (int (*) __P((const void *, const void *))) fcompare); 34459243Sobrien 34559243Sobrien /* get rid of multiple entries */ 34659243Sobrien for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) { 34759243Sobrien if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */ 34859243Sobrien fwd++; /* increase the forward ref. count */ 34959243Sobrien else if (fwd) 35059243Sobrien tw_cmd.list[i - fwd] = tw_cmd.list[i]; 35159243Sobrien } 35259243Sobrien /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */ 35359243Sobrien if (fwd) 35459243Sobrien tw_cmd.list[i - fwd] = tw_cmd.list[i]; 35559243Sobrien tw_cmd.nlist -= fwd; 35659243Sobrien TW_RELS(); 35759243Sobrien} /* end tw_cmd_sort */ 35859243Sobrien 35959243Sobrien 36059243Sobrien/* tw_cmd_start(): 36159243Sobrien * Get the command list and sort it, if not done yet. 36259243Sobrien * Reset the current pointer to the beginning of the command list 36359243Sobrien */ 36459243Sobrien/*ARGSUSED*/ 36559243Sobrienvoid 36659243Sobrientw_cmd_start(dfd, pat) 36759243Sobrien DIR *dfd; 36859243Sobrien Char *pat; 36959243Sobrien{ 37059243Sobrien static Char *defpath[] = { STRNULL, 0 }; 37159243Sobrien USE(pat); 37259243Sobrien SETDIR(dfd) 37359243Sobrien if ((tw_cmd_got & TW_FL_CMD) == 0) { 37459243Sobrien tw_cmd_free(); 37559243Sobrien tw_cmd_cmd(); 37659243Sobrien tw_cmd_got |= TW_FL_CMD; 37759243Sobrien } 37859243Sobrien if ((tw_cmd_got & TW_FL_ALIAS) == 0) { 37959243Sobrien tw_cmd_alias(); 38059243Sobrien tw_cmd_got &= ~TW_FL_SORT; 38159243Sobrien tw_cmd_got |= TW_FL_ALIAS; 38259243Sobrien } 38359243Sobrien if ((tw_cmd_got & TW_FL_BUILTIN) == 0) { 38459243Sobrien tw_cmd_builtin(); 38559243Sobrien tw_cmd_got &= ~TW_FL_SORT; 38659243Sobrien tw_cmd_got |= TW_FL_BUILTIN; 38759243Sobrien } 38859243Sobrien if ((tw_cmd_got & TW_FL_SORT) == 0) { 38959243Sobrien tw_cmd_sort(); 39059243Sobrien tw_cmd_got |= TW_FL_SORT; 39159243Sobrien } 39259243Sobrien 39359243Sobrien tw_cmd_state.cur = 0; 39459243Sobrien CLRDIR(tw_cmd_state.dfd) 39559243Sobrien if (tw_cmd_got & TW_FL_REL) { 39659243Sobrien struct varent *vp = adrof(STRpath); 39759243Sobrien if (vp && vp->vec) 39859243Sobrien tw_cmd_state.pathv = vp->vec; 39959243Sobrien else 40059243Sobrien tw_cmd_state.pathv = defpath; 40159243Sobrien } 40259243Sobrien else 40359243Sobrien tw_cmd_state.pathv = defpath; 40459243Sobrien} /* tw_cmd_start */ 40559243Sobrien 40659243Sobrien 40759243Sobrien/* tw_cmd_next(): 40859243Sobrien * Return the next element in the command list or 40959243Sobrien * Look for commands in the relative path components 41059243Sobrien */ 41159243SobrienChar * 41259243Sobrientw_cmd_next(dir, flags) 41359243Sobrien Char *dir; 41459243Sobrien int *flags; 41559243Sobrien{ 41659243Sobrien Char *ptr = NULL; 41759243Sobrien 41859243Sobrien if (tw_cmd_state.cur < tw_cmd.nlist) { 41959243Sobrien *flags = TW_DIR_OK; 42059243Sobrien return tw_cmd.list[tw_cmd_state.cur++]; 42159243Sobrien } 42259243Sobrien 42359243Sobrien /* 42459243Sobrien * We need to process relatives in the path. 42559243Sobrien */ 42659243Sobrien while (((tw_cmd_state.dfd == NULL) || 42759243Sobrien ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) && 42859243Sobrien (*tw_cmd_state.pathv != NULL)) { 42959243Sobrien 43059243Sobrien CLRDIR(tw_cmd_state.dfd) 43159243Sobrien 43259243Sobrien while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/') 43359243Sobrien tw_cmd_state.pathv++; 43459243Sobrien if ((ptr = *tw_cmd_state.pathv) != 0) { 43559243Sobrien /* 43659243Sobrien * We complete directories only on '.' should that 43759243Sobrien * be changed? 43859243Sobrien */ 43959243Sobrien if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) { 44059243Sobrien *dir = '\0'; 44159243Sobrien tw_cmd_state.dfd = opendir("."); 44259243Sobrien *flags = TW_DIR_OK | TW_EXEC_CHK; 44359243Sobrien } 44459243Sobrien else { 44559243Sobrien copyn(dir, *tw_cmd_state.pathv, FILSIZ); 44659243Sobrien catn(dir, STRslash, FILSIZ); 44759243Sobrien tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv)); 44859243Sobrien *flags = TW_EXEC_CHK; 44959243Sobrien } 45059243Sobrien tw_cmd_state.pathv++; 45159243Sobrien } 45259243Sobrien } 45359243Sobrien return ptr; 45459243Sobrien} /* end tw_cmd_next */ 45559243Sobrien 45659243Sobrien 45759243Sobrien/* tw_vptr_start(): 45859243Sobrien * Find the first variable in the variable list 45959243Sobrien */ 46059243Sobrienstatic void 46159243Sobrientw_vptr_start(c) 46259243Sobrien struct varent *c; 46359243Sobrien{ 46459243Sobrien tw_vptr = c; /* start at beginning of variable list */ 46559243Sobrien 46659243Sobrien for (;;) { 46759243Sobrien while (tw_vptr->v_left) 46859243Sobrien tw_vptr = tw_vptr->v_left; 46959243Sobrienx: 47059243Sobrien if (tw_vptr->v_parent == 0) { /* is it the header? */ 47159243Sobrien tw_vptr = NULL; 47259243Sobrien return; 47359243Sobrien } 47459243Sobrien if (tw_vptr->v_name) 47559243Sobrien return; /* found first one */ 47659243Sobrien if (tw_vptr->v_right) { 47759243Sobrien tw_vptr = tw_vptr->v_right; 47859243Sobrien continue; 47959243Sobrien } 48059243Sobrien do { 48159243Sobrien c = tw_vptr; 48259243Sobrien tw_vptr = tw_vptr->v_parent; 48359243Sobrien } while (tw_vptr->v_right == c); 48459243Sobrien goto x; 48559243Sobrien } 48659243Sobrien} /* end tw_shvar_start */ 48759243Sobrien 48859243Sobrien 48959243Sobrien/* tw_shvar_next(): 49059243Sobrien * Return the next shell variable 49159243Sobrien */ 49259243Sobrien/*ARGSUSED*/ 49359243SobrienChar * 49459243Sobrientw_shvar_next(dir, flags) 49559243Sobrien Char *dir; 49659243Sobrien int *flags; 49759243Sobrien{ 49859243Sobrien register struct varent *p; 49959243Sobrien register struct varent *c; 50059243Sobrien register Char *cp; 50159243Sobrien 50259243Sobrien USE(flags); 50359243Sobrien USE(dir); 50459243Sobrien if ((p = tw_vptr) == NULL) 50559243Sobrien return (NULL); /* just in case */ 50659243Sobrien 50759243Sobrien cp = p->v_name; /* we know that this name is here now */ 50859243Sobrien 50959243Sobrien /* now find the next one */ 51059243Sobrien for (;;) { 51159243Sobrien if (p->v_right) { /* if we can go right */ 51259243Sobrien p = p->v_right; 51359243Sobrien while (p->v_left) 51459243Sobrien p = p->v_left; 51559243Sobrien } 51659243Sobrien else { /* else go up */ 51759243Sobrien do { 51859243Sobrien c = p; 51959243Sobrien p = p->v_parent; 52059243Sobrien } while (p->v_right == c); 52159243Sobrien } 52259243Sobrien if (p->v_parent == 0) { /* is it the header? */ 52359243Sobrien tw_vptr = NULL; 52459243Sobrien return (cp); 52559243Sobrien } 52659243Sobrien if (p->v_name) { 52759243Sobrien tw_vptr = p; /* save state for the next call */ 52859243Sobrien return (cp); 52959243Sobrien } 53059243Sobrien } 53159243Sobrien} /* end tw_shvar_next */ 53259243Sobrien 53359243Sobrien 53459243Sobrien/* tw_envvar_next(): 53559243Sobrien * Return the next environment variable 53659243Sobrien */ 53759243Sobrien/*ARGSUSED*/ 53859243SobrienChar * 53959243Sobrientw_envvar_next(dir, flags) 54059243Sobrien Char *dir; 54159243Sobrien int *flags; 54259243Sobrien{ 54359243Sobrien Char *ps, *pd; 54459243Sobrien 54559243Sobrien USE(flags); 54659243Sobrien USE(dir); 54759243Sobrien if (tw_env == NULL || *tw_env == NULL) 54859243Sobrien return (NULL); 54959243Sobrien for (ps = *tw_env, pd = tw_retname; 55059243Sobrien *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++) 55159243Sobrien continue; 55259243Sobrien *pd = '\0'; 55359243Sobrien tw_env++; 55459243Sobrien return (tw_retname); 55559243Sobrien} /* end tw_envvar_next */ 55659243Sobrien 55759243Sobrien 55859243Sobrien/* tw_var_start(): 55959243Sobrien * Begin the list of the shell and environment variables 56059243Sobrien */ 56159243Sobrien/*ARGSUSED*/ 56259243Sobrienvoid 56359243Sobrientw_var_start(dfd, pat) 56459243Sobrien DIR *dfd; 56559243Sobrien Char *pat; 56659243Sobrien{ 56759243Sobrien USE(pat); 56859243Sobrien SETDIR(dfd) 56959243Sobrien tw_vptr_start(&shvhed); 57059243Sobrien tw_env = STR_environ; 57159243Sobrien} /* end tw_var_start */ 57259243Sobrien 57359243Sobrien 57459243Sobrien/* tw_alias_start(): 57559243Sobrien * Begin the list of the shell aliases 57659243Sobrien */ 57759243Sobrien/*ARGSUSED*/ 57859243Sobrienvoid 57959243Sobrientw_alias_start(dfd, pat) 58059243Sobrien DIR *dfd; 58159243Sobrien Char *pat; 58259243Sobrien{ 58359243Sobrien USE(pat); 58459243Sobrien SETDIR(dfd) 58559243Sobrien tw_vptr_start(&aliases); 58659243Sobrien tw_env = NULL; 58759243Sobrien} /* tw_alias_start */ 58859243Sobrien 58959243Sobrien 59059243Sobrien/* tw_complete_start(): 59159243Sobrien * Begin the list of completions 59259243Sobrien */ 59359243Sobrien/*ARGSUSED*/ 59459243Sobrienvoid 59559243Sobrientw_complete_start(dfd, pat) 59659243Sobrien DIR *dfd; 59759243Sobrien Char *pat; 59859243Sobrien{ 59959243Sobrien extern struct varent completions; 60059243Sobrien 60159243Sobrien USE(pat); 60259243Sobrien SETDIR(dfd) 60359243Sobrien tw_vptr_start(&completions); 60459243Sobrien tw_env = NULL; 60559243Sobrien} /* end tw_complete_start */ 60659243Sobrien 60759243Sobrien 60859243Sobrien/* tw_var_next(): 60959243Sobrien * Return the next shell or environment variable 61059243Sobrien */ 61159243SobrienChar * 61259243Sobrientw_var_next(dir, flags) 61359243Sobrien Char *dir; 61459243Sobrien int *flags; 61559243Sobrien{ 61659243Sobrien Char *ptr = NULL; 61759243Sobrien 61859243Sobrien if (tw_vptr) 61959243Sobrien ptr = tw_shvar_next(dir, flags); 62059243Sobrien if (!ptr && tw_env) 62159243Sobrien ptr = tw_envvar_next(dir, flags); 62259243Sobrien return ptr; 62359243Sobrien} /* end tw_var_next */ 62459243Sobrien 62559243Sobrien 62659243Sobrien/* tw_logname_start(): 62759243Sobrien * Initialize lognames to the beginning of the list 62859243Sobrien */ 62959243Sobrien/*ARGSUSED*/ 63059243Sobrienvoid 63159243Sobrientw_logname_start(dfd, pat) 63259243Sobrien DIR *dfd; 63359243Sobrien Char *pat; 63459243Sobrien{ 63559243Sobrien USE(pat); 63659243Sobrien SETDIR(dfd) 63759243Sobrien#if !defined(_VMS_POSIX) && !defined(WINNT) 63859243Sobrien (void) setpwent(); /* Open passwd file */ 63959243Sobrien#endif /* !_VMS_POSIX && !WINNT */ 64059243Sobrien} /* end tw_logname_start */ 64159243Sobrien 64259243Sobrien 64359243Sobrien/* tw_logname_next(): 64459243Sobrien * Return the next entry from the passwd file 64559243Sobrien */ 64659243Sobrien/*ARGSUSED*/ 64759243SobrienChar * 64859243Sobrientw_logname_next(dir, flags) 64959243Sobrien Char *dir; 65059243Sobrien int *flags; 65159243Sobrien{ 65259243Sobrien static Char retname[MAXPATHLEN]; 65359243Sobrien struct passwd *pw; 65459243Sobrien /* 65559243Sobrien * We don't want to get interrupted inside getpwent() 65659243Sobrien * because the yellow pages code is not interruptible, 65759243Sobrien * and if we call endpwent() immediatetely after 65859243Sobrien * (in pintr()) we may be freeing an invalid pointer 65959243Sobrien */ 66059243Sobrien USE(flags); 66159243Sobrien USE(dir); 66259243Sobrien TW_HOLD(); 66359243Sobrien#if !defined(_VMS_POSIX) && !defined(WINNT) 66459243Sobrien /* ISC does not declare getpwent()? */ 66559243Sobrien pw = (struct passwd *) getpwent(); 66659243Sobrien#else /* _VMS_POSIX || WINNT */ 66759243Sobrien pw = NULL; 66859243Sobrien#endif /* !_VMS_POSIX && !WINNT */ 66959243Sobrien TW_RELS(); 67059243Sobrien 67159243Sobrien if (pw == NULL) { 67259243Sobrien#ifdef YPBUGS 67359243Sobrien fix_yp_bugs(); 67459243Sobrien#endif 67559243Sobrien return (NULL); 67659243Sobrien } 67759243Sobrien (void) Strcpy(retname, str2short(pw->pw_name)); 67859243Sobrien return (retname); 67959243Sobrien} /* end tw_logname_next */ 68059243Sobrien 68159243Sobrien 68259243Sobrien/* tw_logname_end(): 68359243Sobrien * Close the passwd file to finish the logname list 68459243Sobrien */ 68559243Sobrienvoid 68659243Sobrientw_logname_end() 68759243Sobrien{ 68859243Sobrien#ifdef YPBUGS 68959243Sobrien fix_yp_bugs(); 69059243Sobrien#endif 69159243Sobrien#if !defined(_VMS_POSIX) && !defined(WINNT) 69259243Sobrien (void) endpwent(); 69359243Sobrien#endif /* !_VMS_POSIX && !WINNT */ 69459243Sobrien} /* end tw_logname_end */ 69559243Sobrien 69659243Sobrien 69759243Sobrien/* tw_grpname_start(): 69859243Sobrien * Initialize grpnames to the beginning of the list 69959243Sobrien */ 70059243Sobrien/*ARGSUSED*/ 70159243Sobrienvoid 70259243Sobrientw_grpname_start(dfd, pat) 70359243Sobrien DIR *dfd; 70459243Sobrien Char *pat; 70559243Sobrien{ 70659243Sobrien USE(pat); 70759243Sobrien SETDIR(dfd) 70859243Sobrien#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 70959243Sobrien (void) setgrent(); /* Open group file */ 71059243Sobrien#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 71159243Sobrien} /* end tw_grpname_start */ 71259243Sobrien 71359243Sobrien 71459243Sobrien/* tw_grpname_next(): 71559243Sobrien * Return the next entry from the group file 71659243Sobrien */ 71759243Sobrien/*ARGSUSED*/ 71859243SobrienChar * 71959243Sobrientw_grpname_next(dir, flags) 72059243Sobrien Char *dir; 72159243Sobrien int *flags; 72259243Sobrien{ 72359243Sobrien static Char retname[MAXPATHLEN]; 72459243Sobrien struct group *gr; 72559243Sobrien /* 72659243Sobrien * We don't want to get interrupted inside getgrent() 72759243Sobrien * because the yellow pages code is not interruptible, 72859243Sobrien * and if we call endgrent() immediatetely after 72959243Sobrien * (in pintr()) we may be freeing an invalid pointer 73059243Sobrien */ 73159243Sobrien USE(flags); 73259243Sobrien USE(dir); 73359243Sobrien TW_HOLD(); 73459243Sobrien#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 73559243Sobrien gr = (struct group *) getgrent(); 73659243Sobrien#else /* _VMS_POSIX || _OSD_POSIX || WINNT */ 73759243Sobrien gr = NULL; 73859243Sobrien#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 73959243Sobrien TW_RELS(); 74059243Sobrien 74159243Sobrien if (gr == NULL) { 74259243Sobrien#ifdef YPBUGS 74359243Sobrien fix_yp_bugs(); 74459243Sobrien#endif 74559243Sobrien return (NULL); 74659243Sobrien } 74759243Sobrien (void) Strcpy(retname, str2short(gr->gr_name)); 74859243Sobrien return (retname); 74959243Sobrien} /* end tw_grpname_next */ 75059243Sobrien 75159243Sobrien 75259243Sobrien/* tw_grpname_end(): 75359243Sobrien * Close the group file to finish the groupname list 75459243Sobrien */ 75559243Sobrienvoid 75659243Sobrientw_grpname_end() 75759243Sobrien{ 75859243Sobrien#ifdef YPBUGS 75959243Sobrien fix_yp_bugs(); 76059243Sobrien#endif 76159243Sobrien#if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT) 76259243Sobrien (void) endgrent(); 76359243Sobrien#endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT */ 76459243Sobrien} /* end tw_grpname_end */ 76559243Sobrien 76659243Sobrien/* tw_file_start(): 76759243Sobrien * Initialize the directory for the file list 76859243Sobrien */ 76959243Sobrien/*ARGSUSED*/ 77059243Sobrienvoid 77159243Sobrientw_file_start(dfd, pat) 77259243Sobrien DIR *dfd; 77359243Sobrien Char *pat; 77459243Sobrien{ 77559243Sobrien struct varent *vp; 77659243Sobrien USE(pat); 77759243Sobrien SETDIR(dfd) 77859243Sobrien if ((vp = adrof(STRcdpath)) != NULL) 77959243Sobrien tw_env = vp->vec; 78059243Sobrien} /* end tw_file_start */ 78159243Sobrien 78259243Sobrien 78359243Sobrien/* tw_file_next(): 78459243Sobrien * Return the next file in the directory 78559243Sobrien */ 78659243SobrienChar * 78759243Sobrientw_file_next(dir, flags) 78859243Sobrien Char *dir; 78959243Sobrien int *flags; 79059243Sobrien{ 79159243Sobrien Char *ptr = tw_dir_next(tw_dir_fd); 79259243Sobrien if (ptr == NULL && (*flags & TW_DIR_OK) != 0) { 79359243Sobrien CLRDIR(tw_dir_fd) 79459243Sobrien while (tw_env && *tw_env) 79559243Sobrien if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL) 79659243Sobrien break; 79759243Sobrien else 79859243Sobrien tw_env++; 79959243Sobrien 80059243Sobrien if (tw_dir_fd) { 80159243Sobrien copyn(dir, *tw_env++, MAXPATHLEN); 80259243Sobrien catn(dir, STRslash, MAXPATHLEN); 80359243Sobrien ptr = tw_dir_next(tw_dir_fd); 80459243Sobrien } 80559243Sobrien } 80659243Sobrien return ptr; 80759243Sobrien} /* end tw_file_next */ 80859243Sobrien 80959243Sobrien 81059243Sobrien/* tw_dir_end(): 81159243Sobrien * Clear directory related lists 81259243Sobrien */ 81359243Sobrienvoid 81459243Sobrientw_dir_end() 81559243Sobrien{ 81659243Sobrien CLRDIR(tw_dir_fd) 81759243Sobrien CLRDIR(tw_cmd_state.dfd) 81859243Sobrien} /* end tw_dir_end */ 81959243Sobrien 82059243Sobrien 82159243Sobrien/* tw_item_free(): 82259243Sobrien * Free the item list 82359243Sobrien */ 82459243Sobrienvoid 82559243Sobrientw_item_free() 82659243Sobrien{ 82759243Sobrien tw_str_free(&tw_item); 82859243Sobrien} /* end tw_item_free */ 82959243Sobrien 83059243Sobrien 83159243Sobrien/* tw_item_get(): 83259243Sobrien * Return the list of items 83359243Sobrien */ 83459243SobrienChar ** 83559243Sobrientw_item_get() 83659243Sobrien{ 83759243Sobrien return tw_item.list; 83859243Sobrien} /* end tw_item_get */ 83959243Sobrien 84059243Sobrien 84159243Sobrien/* tw_item_add(): 84259243Sobrien * Return a new item 84359243Sobrien */ 84459243SobrienChar * 84559243Sobrientw_item_add(len) 84659243Sobrien int len; 84759243Sobrien{ 84859243Sobrien return tw_str_add(&tw_item, len); 84959243Sobrien} /* tw_item_add */ 85059243Sobrien 85159243Sobrien 85259243Sobrien/* tw_item_find(): 85359243Sobrien * Find the string if it exists in the item list 85459243Sobrien * end return it. 85559243Sobrien */ 85659243SobrienChar * 85759243Sobrientw_item_find(str) 85859243Sobrien Char *str; 85959243Sobrien{ 86059243Sobrien int i; 86159243Sobrien 86259243Sobrien if (tw_item.list == NULL || str == NULL) 86359243Sobrien return NULL; 86459243Sobrien 86559243Sobrien for (i = 0; i < tw_item.nlist; i++) 86659243Sobrien if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0) 86759243Sobrien return tw_item.list[i]; 86859243Sobrien return NULL; 86959243Sobrien} /* end tw_item_find */ 87059243Sobrien 87159243Sobrien 87259243Sobrien/* tw_vl_start(): 87359243Sobrien * Initialize a variable list 87459243Sobrien */ 87559243Sobrienvoid 87659243Sobrientw_vl_start(dfd, pat) 87759243Sobrien DIR *dfd; 87859243Sobrien Char *pat; 87959243Sobrien{ 88059243Sobrien SETDIR(dfd) 88159243Sobrien if ((tw_vptr = adrof(pat)) != NULL) { 88259243Sobrien tw_env = tw_vptr->vec; 88359243Sobrien tw_vptr = NULL; 88459243Sobrien } 88559243Sobrien else 88659243Sobrien tw_env = NULL; 88759243Sobrien} /* end tw_vl_start */ 88859243Sobrien 88959243Sobrien 89059243Sobrien/* 89159243Sobrien * Initialize a word list 89259243Sobrien */ 89359243Sobrienvoid 89459243Sobrientw_wl_start(dfd, pat) 89559243Sobrien DIR *dfd; 89659243Sobrien Char *pat; 89759243Sobrien{ 89859243Sobrien SETDIR(dfd); 89959243Sobrien tw_word = pat; 90059243Sobrien} /* end tw_wl_start */ 90159243Sobrien 90259243Sobrien 90359243Sobrien/* 90459243Sobrien * Return the next word from the word list 90559243Sobrien */ 90659243Sobrien/*ARGSUSED*/ 90759243SobrienChar * 90859243Sobrientw_wl_next(dir, flags) 90959243Sobrien Char *dir; 91059243Sobrien int *flags; 91159243Sobrien{ 91259243Sobrien USE(flags); 91359243Sobrien if (tw_word == NULL || tw_word[0] == '\0') 91459243Sobrien return NULL; 91559243Sobrien 91659243Sobrien while (*tw_word && Isspace(*tw_word)) tw_word++; 91759243Sobrien 91859243Sobrien for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++) 91959243Sobrien continue; 92059243Sobrien if (*tw_word) 92159243Sobrien *tw_word++ = '\0'; 92259243Sobrien return *dir ? dir : NULL; 92359243Sobrien} /* end tw_wl_next */ 92459243Sobrien 92559243Sobrien 92659243Sobrien/* tw_bind_start(): 92759243Sobrien * Begin the list of the shell bindings 92859243Sobrien */ 92959243Sobrien/*ARGSUSED*/ 93059243Sobrienvoid 93159243Sobrientw_bind_start(dfd, pat) 93259243Sobrien DIR *dfd; 93359243Sobrien Char *pat; 93459243Sobrien{ 93559243Sobrien USE(pat); 93659243Sobrien SETDIR(dfd) 93759243Sobrien tw_bind = FuncNames; 93859243Sobrien} /* end tw_bind_start */ 93959243Sobrien 94059243Sobrien 94159243Sobrien/* tw_bind_next(): 94259243Sobrien * Begin the list of the shell bindings 94359243Sobrien */ 94459243Sobrien/*ARGSUSED*/ 94559243SobrienChar * 94659243Sobrientw_bind_next(dir, flags) 94759243Sobrien Char *dir; 94859243Sobrien int *flags; 94959243Sobrien{ 95059243Sobrien char *ptr; 95159243Sobrien USE(flags); 95259243Sobrien if (tw_bind && tw_bind->name) { 95359243Sobrien for (ptr = tw_bind->name, dir = tw_retname; 95459243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 95559243Sobrien continue; 95659243Sobrien tw_bind++; 95759243Sobrien return(tw_retname); 95859243Sobrien } 95959243Sobrien return NULL; 96059243Sobrien} /* end tw_bind_next */ 96159243Sobrien 96259243Sobrien 96359243Sobrien/* tw_limit_start(): 96459243Sobrien * Begin the list of the shell limitings 96559243Sobrien */ 96659243Sobrien/*ARGSUSED*/ 96759243Sobrienvoid 96859243Sobrientw_limit_start(dfd, pat) 96959243Sobrien DIR *dfd; 97059243Sobrien Char *pat; 97159243Sobrien{ 97259243Sobrien USE(pat); 97359243Sobrien SETDIR(dfd) 97459243Sobrien#ifndef HAVENOLIMIT 97559243Sobrien tw_limit = limits; 97659243Sobrien#endif /* ! HAVENOLIMIT */ 97759243Sobrien} /* end tw_limit_start */ 97859243Sobrien 97959243Sobrien 98059243Sobrien/* tw_limit_next(): 98159243Sobrien * Begin the list of the shell limitings 98259243Sobrien */ 98359243Sobrien/*ARGSUSED*/ 98459243SobrienChar * 98559243Sobrientw_limit_next(dir, flags) 98659243Sobrien Char *dir; 98759243Sobrien int *flags; 98859243Sobrien{ 98959243Sobrien#ifndef HAVENOLIMIT 99059243Sobrien char *ptr; 99159243Sobrien if (tw_limit && tw_limit->limname) { 99259243Sobrien for (ptr = tw_limit->limname, dir = tw_retname; 99359243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 99459243Sobrien continue; 99559243Sobrien tw_limit++; 99659243Sobrien return(tw_retname); 99759243Sobrien } 99859243Sobrien#endif /* ! HAVENOLIMIT */ 99959243Sobrien USE(flags); 100059243Sobrien return NULL; 100159243Sobrien} /* end tw_limit_next */ 100259243Sobrien 100359243Sobrien 100459243Sobrien/* tw_sig_start(): 100559243Sobrien * Begin the list of the shell sigings 100659243Sobrien */ 100759243Sobrien/*ARGSUSED*/ 100859243Sobrienvoid 100959243Sobrientw_sig_start(dfd, pat) 101059243Sobrien DIR *dfd; 101159243Sobrien Char *pat; 101259243Sobrien{ 101359243Sobrien USE(pat); 101459243Sobrien SETDIR(dfd) 101559243Sobrien tw_index = 0; 101659243Sobrien} /* end tw_sig_start */ 101759243Sobrien 101859243Sobrien 101959243Sobrien/* tw_sig_next(): 102059243Sobrien * Begin the list of the shell sigings 102159243Sobrien */ 102259243Sobrien/*ARGSUSED*/ 102359243SobrienChar * 102459243Sobrientw_sig_next(dir, flags) 102559243Sobrien Char *dir; 102659243Sobrien int *flags; 102759243Sobrien{ 102859243Sobrien char *ptr; 102959243Sobrien extern int nsig; 103059243Sobrien USE(flags); 103159243Sobrien for (;tw_index < nsig; tw_index++) { 103259243Sobrien 103359243Sobrien if (mesg[tw_index].iname == NULL) 103459243Sobrien continue; 103559243Sobrien 103659243Sobrien for (ptr = mesg[tw_index].iname, dir = tw_retname; 103759243Sobrien (*dir++ = (Char) *ptr++) != '\0';) 103859243Sobrien continue; 103959243Sobrien tw_index++; 104059243Sobrien return(tw_retname); 104159243Sobrien } 104259243Sobrien return NULL; 104359243Sobrien} /* end tw_sig_next */ 104459243Sobrien 104559243Sobrien 104659243Sobrien/* tw_job_start(): 104759243Sobrien * Begin the list of the shell jobings 104859243Sobrien */ 104959243Sobrien/*ARGSUSED*/ 105059243Sobrienvoid 105159243Sobrientw_job_start(dfd, pat) 105259243Sobrien DIR *dfd; 105359243Sobrien Char *pat; 105459243Sobrien{ 105559243Sobrien USE(pat); 105659243Sobrien SETDIR(dfd) 105759243Sobrien tw_index = 1; 105859243Sobrien} /* end tw_job_start */ 105959243Sobrien 106059243Sobrien 106159243Sobrien/* tw_job_next(): 106259243Sobrien * Begin the list of the shell jobings 106359243Sobrien */ 106459243Sobrien/*ARGSUSED*/ 106559243SobrienChar * 106659243Sobrientw_job_next(dir, flags) 106759243Sobrien Char *dir; 106859243Sobrien int *flags; 106959243Sobrien{ 107059243Sobrien Char *ptr; 107159243Sobrien struct process *j; 107259243Sobrien 107359243Sobrien USE(flags); 107459243Sobrien for (;tw_index <= pmaxindex; tw_index++) { 107559243Sobrien for (j = proclist.p_next; j != NULL; j = j->p_next) 107659243Sobrien if (j->p_index == tw_index && j->p_procid == j->p_jobid) 107759243Sobrien break; 107859243Sobrien if (j == NULL) 107959243Sobrien continue; 108059243Sobrien for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';) 108159243Sobrien continue; 108259243Sobrien *dir = '\0'; 108359243Sobrien tw_index++; 108459243Sobrien return(tw_retname); 108559243Sobrien } 108659243Sobrien return NULL; 108759243Sobrien} /* end tw_job_next */ 1088