xref: /freebsd/contrib/tcsh/tw.init.c (revision 45e5710b)
145e5710bSMark Peek /*
2c80476e4SDavid E. O'Brien  * tw.init.c: Handle lists of things to complete
3c80476e4SDavid E. O'Brien  */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien  * All rights reserved.
7c80476e4SDavid E. O'Brien  *
8c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien  * are met:
11c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
16c80476e4SDavid E. O'Brien  * 3. Neither the name of the University nor the names of its contributors
1729301572SMark Peek  *    may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien  *    without specific prior written permission.
19c80476e4SDavid E. O'Brien  *
20c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien  */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "tw.h"
34c80476e4SDavid E. O'Brien #include "ed.h"
3545e5710bSMark Peek #include "tc.h"
36c80476e4SDavid E. O'Brien #include "sh.proc.h"
37c80476e4SDavid E. O'Brien 
38c80476e4SDavid E. O'Brien #define TW_INCR	128
39c80476e4SDavid E. O'Brien 
40c80476e4SDavid E. O'Brien typedef struct {
41c80476e4SDavid E. O'Brien     Char **list, 			/* List of command names	*/
42c80476e4SDavid E. O'Brien 	  *buff;			/* Space holding command names	*/
43c80476e4SDavid E. O'Brien     size_t nlist, 			/* Number of items		*/
44c80476e4SDavid E. O'Brien            nbuff,			/* Current space in name buf	*/
45c80476e4SDavid E. O'Brien            tlist,			/* Total space in list		*/
46c80476e4SDavid E. O'Brien 	   tbuff;			/* Total space in name buf	*/
4745e5710bSMark Peek } stringlist_t;
48c80476e4SDavid E. O'Brien 
49c80476e4SDavid E. O'Brien 
50c80476e4SDavid E. O'Brien static struct varent *tw_vptr = NULL;	/* Current shell variable 	*/
51c80476e4SDavid E. O'Brien static Char **tw_env = NULL;		/* Current environment variable */
52c80476e4SDavid E. O'Brien static const Char *tw_word;		/* Current word pointer		*/
53c80476e4SDavid E. O'Brien static struct KeyFuncs *tw_bind = NULL;	/* List of the bindings		*/
54c80476e4SDavid E. O'Brien #ifndef HAVENOLIMIT
55c80476e4SDavid E. O'Brien static struct limits *tw_limit = NULL;	/* List of the resource limits	*/
5645e5710bSMark Peek #endif /* HAVENOLIMIT */
57c80476e4SDavid E. O'Brien static int tw_index = 0;		/* signal and job index		*/
58c80476e4SDavid E. O'Brien static DIR   *tw_dir_fd = NULL;		/* Current directory descriptor	*/
59c80476e4SDavid E. O'Brien static int    tw_cmd_got = 0;		/* What we need to do		*/
60c80476e4SDavid E. O'Brien static stringlist_t tw_cmd  = { NULL, NULL, 0, 0, 0, 0 };
61c80476e4SDavid E. O'Brien static stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 };
62c80476e4SDavid E. O'Brien #define TW_FL_CMD	0x01
63c80476e4SDavid E. O'Brien #define TW_FL_ALIAS	0x02
64c80476e4SDavid E. O'Brien #define TW_FL_BUILTIN	0x04
65c80476e4SDavid E. O'Brien #define TW_FL_SORT	0x08
66c80476e4SDavid E. O'Brien #define TW_FL_REL	0x10
67c80476e4SDavid E. O'Brien 
68c80476e4SDavid E. O'Brien static struct {				/* Current element pointer	*/
69c80476e4SDavid E. O'Brien     size_t cur;				/* Current element number	*/
70c80476e4SDavid E. O'Brien     Char **pathv;			/* Current element in path	*/
71c80476e4SDavid E. O'Brien     DIR   *dfd;				/* Current directory descriptor	*/
72c80476e4SDavid E. O'Brien } tw_cmd_state;
7345e5710bSMark Peek 
74c80476e4SDavid E. O'Brien 
75c80476e4SDavid E. O'Brien #define SETDIR(dfd) \
76c80476e4SDavid E. O'Brien     { \
77c80476e4SDavid E. O'Brien 	tw_dir_fd = dfd; \
78c80476e4SDavid E. O'Brien 	if (tw_dir_fd != NULL) \
79c80476e4SDavid E. O'Brien 	    rewinddir(tw_dir_fd); \
80c80476e4SDavid E. O'Brien     }
81c80476e4SDavid E. O'Brien 
82c80476e4SDavid E. O'Brien #define CLRDIR(dfd) \
83c80476e4SDavid E. O'Brien     if (dfd != NULL) { \
84c80476e4SDavid E. O'Brien 	pintr_disabled++; \
85c80476e4SDavid E. O'Brien 	xclosedir(dfd); \
86c80476e4SDavid E. O'Brien 	dfd = NULL; \
87c80476e4SDavid E. O'Brien 	disabled_cleanup(&pintr_disabled); \
8845e5710bSMark Peek     }
8945e5710bSMark Peek 
90c80476e4SDavid E. O'Brien static Char	*tw_str_add		(stringlist_t *, size_t);
9145e5710bSMark Peek static void	 tw_str_free		(stringlist_t *);
92c80476e4SDavid E. O'Brien static int       tw_dir_next		(struct Strbuf *, DIR *);
93c80476e4SDavid E. O'Brien static void	 tw_cmd_add 		(const Char *name);
9445e5710bSMark Peek static void 	 tw_cmd_cmd		(void);
9545e5710bSMark Peek static void	 tw_cmd_builtin		(void);
9645e5710bSMark Peek static void	 tw_cmd_alias		(void);
9745e5710bSMark Peek static void	 tw_cmd_sort		(void);
9845e5710bSMark Peek static void 	 tw_vptr_start		(struct varent *);
9945e5710bSMark Peek 
10045e5710bSMark Peek 
10145e5710bSMark Peek /* tw_str_add():
10245e5710bSMark Peek  *	Add an item to the string list
103c80476e4SDavid E. O'Brien  */
104c80476e4SDavid E. O'Brien static Char *
tw_str_add(stringlist_t * sl,size_t len)105c80476e4SDavid E. O'Brien tw_str_add(stringlist_t *sl, size_t len)
106c80476e4SDavid E. O'Brien {
107c80476e4SDavid E. O'Brien     Char *ptr;
108c80476e4SDavid E. O'Brien 
10945e5710bSMark Peek     if (sl->tlist <= sl->nlist) {
110c80476e4SDavid E. O'Brien 	pintr_disabled++;
111c80476e4SDavid E. O'Brien 	sl->tlist += TW_INCR;
112c80476e4SDavid E. O'Brien 	sl->list = xrealloc(sl->list, sl->tlist * sizeof(Char *));
113c80476e4SDavid E. O'Brien 	disabled_cleanup(&pintr_disabled);
11445e5710bSMark Peek     }
115c80476e4SDavid E. O'Brien     if (sl->tbuff <= sl->nbuff + len) {
11645e5710bSMark Peek 	size_t i;
11745e5710bSMark Peek 
118c80476e4SDavid E. O'Brien 	ptr = sl->buff;
119c80476e4SDavid E. O'Brien 	pintr_disabled++;
12045e5710bSMark Peek 	sl->tbuff += TW_INCR + len;
121c80476e4SDavid E. O'Brien 	sl->buff = xrealloc(sl->buff, sl->tbuff * sizeof(Char));
12245e5710bSMark Peek 	/* Re-thread the new pointer list, if changed */
12345e5710bSMark Peek 	if (ptr != NULL && ptr != sl->buff) {
124c80476e4SDavid E. O'Brien 	    for (i = 0; i < sl->nlist; i++)
12545e5710bSMark Peek 		sl->list[i] = sl->buff + (sl->list[i] - ptr);
126c80476e4SDavid E. O'Brien 	}
127c80476e4SDavid E. O'Brien 	disabled_cleanup(&pintr_disabled);
12823338178SMark Peek     }
129c80476e4SDavid E. O'Brien     ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff];
130c80476e4SDavid E. O'Brien     sl->nbuff += len;
131c80476e4SDavid E. O'Brien     return ptr;
13245e5710bSMark Peek } /* tw_str_add */
133c80476e4SDavid E. O'Brien 
134c80476e4SDavid E. O'Brien 
135c80476e4SDavid E. O'Brien /* tw_str_free():
136c80476e4SDavid E. O'Brien  *	Free a stringlist
137c80476e4SDavid E. O'Brien  */
138c80476e4SDavid E. O'Brien static void
tw_str_free(stringlist_t * sl)139c80476e4SDavid E. O'Brien tw_str_free(stringlist_t *sl)
140c80476e4SDavid E. O'Brien {
141c80476e4SDavid E. O'Brien     pintr_disabled++;
142c80476e4SDavid E. O'Brien     if (sl->list) {
143c80476e4SDavid E. O'Brien 	xfree(sl->list);
14445e5710bSMark Peek 	sl->list = NULL;
145c80476e4SDavid E. O'Brien 	sl->tlist = sl->nlist = 0;
14645e5710bSMark Peek     }
147c80476e4SDavid E. O'Brien     if (sl->buff) {
14845e5710bSMark Peek 	xfree(sl->buff);
149c80476e4SDavid E. O'Brien 	sl->buff = NULL;
150c80476e4SDavid E. O'Brien 	sl->tbuff = sl->nbuff = 0;
151c80476e4SDavid E. O'Brien     }
152c80476e4SDavid E. O'Brien     disabled_cleanup(&pintr_disabled);
15345e5710bSMark Peek } /* end tw_str_free */
154c80476e4SDavid E. O'Brien 
155c80476e4SDavid E. O'Brien 
156c80476e4SDavid E. O'Brien static int
tw_dir_next(struct Strbuf * res,DIR * dfd)15745e5710bSMark Peek tw_dir_next(struct Strbuf *res, DIR *dfd)
158c80476e4SDavid E. O'Brien {
159c80476e4SDavid E. O'Brien     struct dirent *dirp;
160c80476e4SDavid E. O'Brien 
16145e5710bSMark Peek     if (dfd == NULL)
16245e5710bSMark Peek 	return 0;
163c80476e4SDavid E. O'Brien 
16423338178SMark Peek     if ((dirp = readdir(dfd)) != NULL) {
165c80476e4SDavid E. O'Brien 	Strbuf_append(res, str2short(dirp->d_name));
166c80476e4SDavid E. O'Brien 	return 1;
16745e5710bSMark Peek     }
168c80476e4SDavid E. O'Brien     return 0;
169c80476e4SDavid E. O'Brien } /* end tw_dir_next */
17045e5710bSMark Peek 
17145e5710bSMark Peek 
172c80476e4SDavid E. O'Brien /* tw_cmd_add():
17345e5710bSMark Peek  *	Add the name to the command list
174c80476e4SDavid E. O'Brien  */
175c80476e4SDavid E. O'Brien static void
tw_cmd_add(const Char * name)176c80476e4SDavid E. O'Brien tw_cmd_add(const Char *name)
177c80476e4SDavid E. O'Brien {
178c80476e4SDavid E. O'Brien     size_t len;
179c80476e4SDavid E. O'Brien 
180c80476e4SDavid E. O'Brien     len = Strlen(name) + 2;
18145e5710bSMark Peek     (void) Strcpy(tw_str_add(&tw_cmd, len), name);
182c80476e4SDavid E. O'Brien } /* end tw_cmd_add */
18345e5710bSMark Peek 
184c80476e4SDavid E. O'Brien 
18545e5710bSMark Peek /* tw_cmd_free():
186c80476e4SDavid E. O'Brien  *	Free the command list
187c80476e4SDavid E. O'Brien  */
188c80476e4SDavid E. O'Brien void
tw_cmd_free(void)189c80476e4SDavid E. O'Brien tw_cmd_free(void)
190c80476e4SDavid E. O'Brien {
191c80476e4SDavid E. O'Brien     CLRDIR(tw_dir_fd)
192c80476e4SDavid E. O'Brien     tw_str_free(&tw_cmd);
193c80476e4SDavid E. O'Brien     tw_cmd_got = 0;
19445e5710bSMark Peek } /* end tw_cmd_free */
195c80476e4SDavid E. O'Brien 
196c80476e4SDavid E. O'Brien /* tw_cmd_cmd():
197c80476e4SDavid E. O'Brien  *	Add system commands to the command list
198c80476e4SDavid E. O'Brien  */
199c80476e4SDavid E. O'Brien static void
tw_cmd_cmd(void)200c80476e4SDavid E. O'Brien tw_cmd_cmd(void)
201c80476e4SDavid E. O'Brien {
202c80476e4SDavid E. O'Brien     DIR *dirp;
203c80476e4SDavid E. O'Brien     struct dirent *dp;
204c80476e4SDavid E. O'Brien     Char *dir = NULL, *name;
20545e5710bSMark Peek     Char **pv;
206c80476e4SDavid E. O'Brien     struct varent *v = adrof(STRpath);
20723338178SMark Peek     struct varent *recexec = adrof(STRrecognize_only_executables);
20823338178SMark Peek     size_t len;
20923338178SMark Peek 
21023338178SMark Peek 
211c80476e4SDavid E. O'Brien     if (v == NULL || v->vec == NULL) /* if no path */
212c80476e4SDavid E. O'Brien 	return;
21345e5710bSMark Peek 
214c80476e4SDavid E. O'Brien     for (pv = v->vec; *pv; pv++) {
215c80476e4SDavid E. O'Brien 	if (pv[0][0] != '/') {
21629301572SMark Peek 	    tw_cmd_got |= TW_FL_REL;
217c80476e4SDavid E. O'Brien 	    continue;
218c80476e4SDavid E. O'Brien 	}
219c80476e4SDavid E. O'Brien 
220c80476e4SDavid E. O'Brien 	if ((dirp = opendir(short2str(*pv))) == NULL)
221c80476e4SDavid E. O'Brien 	    continue;
222c80476e4SDavid E. O'Brien 
223c80476e4SDavid E. O'Brien 	cleanup_push(dirp, opendir_cleanup);
224c80476e4SDavid E. O'Brien 	if (recexec) {
225c80476e4SDavid E. O'Brien 	    dir = Strspl(*pv, STRslash);
226c80476e4SDavid E. O'Brien 	    cleanup_push(dir, xfree);
227c80476e4SDavid E. O'Brien 	}
22845e5710bSMark Peek 	while ((dp = readdir(dirp)) != NULL) {
22945e5710bSMark Peek #if defined(_UWIN) || defined(__CYGWIN__)
230c80476e4SDavid E. O'Brien 	    /* Turn foo.{exe,com,bat} into foo since UWIN's readdir returns
23145e5710bSMark Peek 	     * the file with the .exe, .com, .bat extension
23245e5710bSMark Peek 	     *
233c80476e4SDavid E. O'Brien 	     * Same for Cygwin, but only for .exe and .com extension.
2343b6eaa7bSAndrey A. Chernov 	     */
2353b6eaa7bSAndrey A. Chernov 	    len = strlen(dp->d_name);
2363b6eaa7bSAndrey A. Chernov 	    if (len > 4 && (strcmp(&dp->d_name[len - 4], ".exe") == 0 ||
2373b6eaa7bSAndrey A. Chernov #ifndef __CYGWIN__
23845e5710bSMark Peek 		strcmp(&dp->d_name[len - 4], ".bat") == 0 ||
23945e5710bSMark Peek #endif /* !__CYGWIN__ */
24045e5710bSMark Peek 		strcmp(&dp->d_name[len - 4], ".com") == 0))
24145e5710bSMark Peek 		dp->d_name[len - 4] = '\0';
24245e5710bSMark Peek #endif /* _UWIN || __CYGWIN__ */
2433b6eaa7bSAndrey A. Chernov 	    /* the call to executable() may make this a bit slow */
244c80476e4SDavid E. O'Brien 	    name = str2short(dp->d_name);
245c80476e4SDavid E. O'Brien 	    if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0)))
246c80476e4SDavid E. O'Brien 		continue;
247c80476e4SDavid E. O'Brien             len = Strlen(name);
24845e5710bSMark Peek             if (name[0] == '#' ||	/* emacs temp files	*/
249c80476e4SDavid E. O'Brien 		name[0] == '.' ||	/* .files		*/
250c80476e4SDavid E. O'Brien 		name[len - 1] == '~' ||	/* emacs backups	*/
25145e5710bSMark Peek 		name[len - 1] == '%')	/* textedit backups	*/
25245e5710bSMark Peek                 continue;		/* Ignore!		*/
253c80476e4SDavid E. O'Brien             tw_cmd_add(name);
254c80476e4SDavid E. O'Brien 	}
255c80476e4SDavid E. O'Brien 	cleanup_until(dirp);
25645e5710bSMark Peek     }
257c80476e4SDavid E. O'Brien } /* end tw_cmd_cmd */
258c80476e4SDavid E. O'Brien 
259c80476e4SDavid E. O'Brien 
260c80476e4SDavid E. O'Brien /* tw_cmd_builtin():
261c80476e4SDavid E. O'Brien  *	Add builtins to the command list
262c80476e4SDavid E. O'Brien  */
263c80476e4SDavid E. O'Brien static void
tw_cmd_builtin(void)264c80476e4SDavid E. O'Brien tw_cmd_builtin(void)
26545e5710bSMark Peek {
266c80476e4SDavid E. O'Brien     const struct biltins *bptr;
26745e5710bSMark Peek 
268c80476e4SDavid E. O'Brien     for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++)
269c80476e4SDavid E. O'Brien 	if (bptr->bname)
270c80476e4SDavid E. O'Brien 	    tw_cmd_add(str2short(bptr->bname));
271c80476e4SDavid E. O'Brien #ifdef WINNT_NATIVE
2723b6eaa7bSAndrey A. Chernov     for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++)
273c80476e4SDavid E. O'Brien 	if (bptr->bname)
274c80476e4SDavid E. O'Brien 	    tw_cmd_add(str2short(bptr->bname));
275c80476e4SDavid E. O'Brien #endif /* WINNT_NATIVE*/
2763b6eaa7bSAndrey A. Chernov } /* end tw_cmd_builtin */
277c80476e4SDavid E. O'Brien 
278c80476e4SDavid E. O'Brien 
279c80476e4SDavid E. O'Brien /* tw_cmd_alias():
280c80476e4SDavid E. O'Brien  *	Add aliases to the command list
281c80476e4SDavid E. O'Brien  */
282c80476e4SDavid E. O'Brien static void
tw_cmd_alias(void)283c80476e4SDavid E. O'Brien tw_cmd_alias(void)
28445e5710bSMark Peek {
285c80476e4SDavid E. O'Brien     struct varent *p;
28623338178SMark Peek     struct varent *c;
28723338178SMark Peek 
288c80476e4SDavid E. O'Brien     p = &aliases;
289c80476e4SDavid E. O'Brien     for (;;) {
290c80476e4SDavid E. O'Brien 	while (p->v_left)
291c80476e4SDavid E. O'Brien 	    p = p->v_left;
292c80476e4SDavid E. O'Brien x:
293c80476e4SDavid E. O'Brien 	if (p->v_parent == 0) /* is it the header? */
294c80476e4SDavid E. O'Brien 	    return;
295c80476e4SDavid E. O'Brien 	if (p->v_name)
296c80476e4SDavid E. O'Brien 	    tw_cmd_add(p->v_name);
297c80476e4SDavid E. O'Brien 	if (p->v_right) {
298c80476e4SDavid E. O'Brien 	    p = p->v_right;
299c80476e4SDavid E. O'Brien 	    continue;
300c80476e4SDavid E. O'Brien 	}
301c80476e4SDavid E. O'Brien 	do {
302c80476e4SDavid E. O'Brien 	    c = p;
303c80476e4SDavid E. O'Brien 	    p = p->v_parent;
304c80476e4SDavid E. O'Brien 	} while (p->v_right == c);
305c80476e4SDavid E. O'Brien 	goto x;
306c80476e4SDavid E. O'Brien     }
307c80476e4SDavid E. O'Brien } /* end tw_cmd_alias */
308c80476e4SDavid E. O'Brien 
309c80476e4SDavid E. O'Brien 
310c80476e4SDavid E. O'Brien /* tw_cmd_sort():
311c80476e4SDavid E. O'Brien  *	Sort the command list removing duplicate elements
312c80476e4SDavid E. O'Brien  */
313c80476e4SDavid E. O'Brien static void
tw_cmd_sort(void)314c80476e4SDavid E. O'Brien tw_cmd_sort(void)
31545e5710bSMark Peek {
316c80476e4SDavid E. O'Brien     size_t fwd, i;
31745e5710bSMark Peek 
318c80476e4SDavid E. O'Brien     pintr_disabled++;
31945e5710bSMark Peek     /* sort the list. */
320c80476e4SDavid E. O'Brien     qsort(tw_cmd.list, tw_cmd.nlist, sizeof(Char *), fcompare);
32145e5710bSMark Peek 
322c80476e4SDavid E. O'Brien     /* get rid of multiple entries */
323c80476e4SDavid E. O'Brien     for (i = 0, fwd = 0; i + 1 < tw_cmd.nlist; i++) {
32445e5710bSMark Peek 	if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */
325c80476e4SDavid E. O'Brien 	    fwd++;		/* increase the forward ref. count */
326c80476e4SDavid E. O'Brien 	else if (fwd)
327c80476e4SDavid E. O'Brien 	    tw_cmd.list[i - fwd] = tw_cmd.list[i];
328c80476e4SDavid E. O'Brien     }
329c80476e4SDavid E. O'Brien     /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */
330c80476e4SDavid E. O'Brien     if (fwd)
331c80476e4SDavid E. O'Brien 	tw_cmd.list[i - fwd] = tw_cmd.list[i];
332c80476e4SDavid E. O'Brien     tw_cmd.nlist -= fwd;
333c80476e4SDavid E. O'Brien     disabled_cleanup(&pintr_disabled);
33445e5710bSMark Peek } /* end tw_cmd_sort */
335c80476e4SDavid E. O'Brien 
336c80476e4SDavid E. O'Brien 
337c80476e4SDavid E. O'Brien /* tw_cmd_start():
338c80476e4SDavid E. O'Brien  *	Get the command list and sort it, if not done yet.
339c80476e4SDavid E. O'Brien  *	Reset the current pointer to the beginning of the command list
340c80476e4SDavid E. O'Brien  */
341c80476e4SDavid E. O'Brien /*ARGSUSED*/
342c80476e4SDavid E. O'Brien void
tw_cmd_start(DIR * dfd,const Char * pat)343c80476e4SDavid E. O'Brien tw_cmd_start(DIR *dfd, const Char *pat)
34445e5710bSMark Peek {
345c80476e4SDavid E. O'Brien     static Char *defpath[] = { STRNULL, 0 };
346c80476e4SDavid E. O'Brien     USE(pat);
347c80476e4SDavid E. O'Brien     SETDIR(dfd)
348c80476e4SDavid E. O'Brien     if ((tw_cmd_got & TW_FL_CMD) == 0) {
349c80476e4SDavid E. O'Brien 	tw_cmd_free();
350c80476e4SDavid E. O'Brien 	tw_cmd_cmd();
351c80476e4SDavid E. O'Brien 	tw_cmd_got |= TW_FL_CMD;
352c80476e4SDavid E. O'Brien     }
353c80476e4SDavid E. O'Brien     if ((tw_cmd_got & TW_FL_ALIAS) == 0) {
354c80476e4SDavid E. O'Brien 	tw_cmd_alias();
355c80476e4SDavid E. O'Brien 	tw_cmd_got &= ~TW_FL_SORT;
356c80476e4SDavid E. O'Brien 	tw_cmd_got |= TW_FL_ALIAS;
357c80476e4SDavid E. O'Brien     }
358c80476e4SDavid E. O'Brien     if ((tw_cmd_got & TW_FL_BUILTIN) == 0) {
359c80476e4SDavid E. O'Brien 	tw_cmd_builtin();
360c80476e4SDavid E. O'Brien 	tw_cmd_got &= ~TW_FL_SORT;
361c80476e4SDavid E. O'Brien 	tw_cmd_got |= TW_FL_BUILTIN;
362c80476e4SDavid E. O'Brien     }
363c80476e4SDavid E. O'Brien     if ((tw_cmd_got & TW_FL_SORT) == 0) {
364c80476e4SDavid E. O'Brien 	tw_cmd_sort();
365c80476e4SDavid E. O'Brien 	tw_cmd_got |= TW_FL_SORT;
366c80476e4SDavid E. O'Brien     }
367c80476e4SDavid E. O'Brien 
368c80476e4SDavid E. O'Brien     tw_cmd_state.cur = 0;
369c80476e4SDavid E. O'Brien     CLRDIR(tw_cmd_state.dfd)
370c80476e4SDavid E. O'Brien     if (tw_cmd_got & TW_FL_REL) {
371c80476e4SDavid E. O'Brien 	struct varent *vp = adrof(STRpath);
372c80476e4SDavid E. O'Brien 	if (vp && vp->vec)
373c80476e4SDavid E. O'Brien 	    tw_cmd_state.pathv = vp->vec;
374c80476e4SDavid E. O'Brien 	else
375c80476e4SDavid E. O'Brien 	    tw_cmd_state.pathv = defpath;
376c80476e4SDavid E. O'Brien     }
377c80476e4SDavid E. O'Brien     else
378c80476e4SDavid E. O'Brien 	tw_cmd_state.pathv = defpath;
379c80476e4SDavid E. O'Brien } /* tw_cmd_start */
380c80476e4SDavid E. O'Brien 
381c80476e4SDavid E. O'Brien 
382c80476e4SDavid E. O'Brien /* tw_cmd_next():
383c80476e4SDavid E. O'Brien  *	Return the next element in the command list or
384c80476e4SDavid E. O'Brien  *	Look for commands in the relative path components
385c80476e4SDavid E. O'Brien  */
386c80476e4SDavid E. O'Brien int
tw_cmd_next(struct Strbuf * res,struct Strbuf * dir,int * flags)38745e5710bSMark Peek tw_cmd_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
38845e5710bSMark Peek {
389c80476e4SDavid E. O'Brien     int ret = 0;
39045e5710bSMark Peek     Char *ptr;
39145e5710bSMark Peek 
392c80476e4SDavid E. O'Brien     if (tw_cmd_state.cur < tw_cmd.nlist) {
393c80476e4SDavid E. O'Brien 	*flags = TW_DIR_OK;
394c80476e4SDavid E. O'Brien 	Strbuf_append(res, tw_cmd.list[tw_cmd_state.cur++]);
39545e5710bSMark Peek 	return 1;
39645e5710bSMark Peek     }
397c80476e4SDavid E. O'Brien 
398c80476e4SDavid E. O'Brien     /*
399c80476e4SDavid E. O'Brien      * We need to process relatives in the path.
400c80476e4SDavid E. O'Brien      */
401c80476e4SDavid E. O'Brien     while ((tw_cmd_state.dfd == NULL ||
40245e5710bSMark Peek 	    (res->len = 0, ret = tw_dir_next(res, tw_cmd_state.dfd)) == 0) &&
40345e5710bSMark Peek 	   *tw_cmd_state.pathv != NULL) {
40445e5710bSMark Peek 
405c80476e4SDavid E. O'Brien         CLRDIR(tw_cmd_state.dfd)
406c80476e4SDavid E. O'Brien 
407c80476e4SDavid E. O'Brien 	while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/')
408c80476e4SDavid E. O'Brien 	    tw_cmd_state.pathv++;
409c80476e4SDavid E. O'Brien 	if ((ptr = *tw_cmd_state.pathv) != 0) {
410c80476e4SDavid E. O'Brien 	    res->len = 0;
41145e5710bSMark Peek 	    Strbuf_append(res, ptr);
41245e5710bSMark Peek 	    ret = 1;
413c80476e4SDavid E. O'Brien 	    /*
414c80476e4SDavid E. O'Brien 	     * We complete directories only on '.' should that
415c80476e4SDavid E. O'Brien 	     * be changed?
416c80476e4SDavid E. O'Brien 	     */
41745e5710bSMark Peek 	    dir->len = 0;
418c80476e4SDavid E. O'Brien 	    if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) {
419c80476e4SDavid E. O'Brien 		tw_cmd_state.dfd = opendir(".");
420c80476e4SDavid E. O'Brien 		*flags = TW_DIR_OK | TW_EXEC_CHK;
421c80476e4SDavid E. O'Brien 	    }
422c80476e4SDavid E. O'Brien 	    else {
42345e5710bSMark Peek 		Strbuf_append(dir, *tw_cmd_state.pathv);
42445e5710bSMark Peek 		Strbuf_append1(dir, '/');
425c80476e4SDavid E. O'Brien 		tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv));
426c80476e4SDavid E. O'Brien 		*flags = TW_EXEC_CHK;
427c80476e4SDavid E. O'Brien 	    }
42845e5710bSMark Peek 	    Strbuf_terminate(dir);
429c80476e4SDavid E. O'Brien 	    tw_cmd_state.pathv++;
430c80476e4SDavid E. O'Brien 	}
431c80476e4SDavid E. O'Brien     }
43245e5710bSMark Peek     return ret;
433c80476e4SDavid E. O'Brien } /* end tw_cmd_next */
434c80476e4SDavid E. O'Brien 
435c80476e4SDavid E. O'Brien 
436c80476e4SDavid E. O'Brien /* tw_vptr_start():
437c80476e4SDavid E. O'Brien  *	Find the first variable in the variable list
438c80476e4SDavid E. O'Brien  */
439c80476e4SDavid E. O'Brien static void
tw_vptr_start(struct varent * c)44045e5710bSMark Peek tw_vptr_start(struct varent *c)
441c80476e4SDavid E. O'Brien {
442c80476e4SDavid E. O'Brien     tw_vptr = c;		/* start at beginning of variable list */
443c80476e4SDavid E. O'Brien 
444c80476e4SDavid E. O'Brien     for (;;) {
445c80476e4SDavid E. O'Brien 	while (tw_vptr->v_left)
446c80476e4SDavid E. O'Brien 	    tw_vptr = tw_vptr->v_left;
447c80476e4SDavid E. O'Brien x:
448c80476e4SDavid E. O'Brien 	if (tw_vptr->v_parent == 0) {	/* is it the header? */
449c80476e4SDavid E. O'Brien 	    tw_vptr = NULL;
450c80476e4SDavid E. O'Brien 	    return;
451c80476e4SDavid E. O'Brien 	}
452c80476e4SDavid E. O'Brien 	if (tw_vptr->v_name)
453c80476e4SDavid E. O'Brien 	    return;		/* found first one */
454c80476e4SDavid E. O'Brien 	if (tw_vptr->v_right) {
455c80476e4SDavid E. O'Brien 	    tw_vptr = tw_vptr->v_right;
456c80476e4SDavid E. O'Brien 	    continue;
457c80476e4SDavid E. O'Brien 	}
458c80476e4SDavid E. O'Brien 	do {
459c80476e4SDavid E. O'Brien 	    c = tw_vptr;
460c80476e4SDavid E. O'Brien 	    tw_vptr = tw_vptr->v_parent;
461c80476e4SDavid E. O'Brien 	} while (tw_vptr->v_right == c);
462c80476e4SDavid E. O'Brien 	goto x;
463c80476e4SDavid E. O'Brien     }
464c80476e4SDavid E. O'Brien } /* end tw_shvar_start */
465c80476e4SDavid E. O'Brien 
466c80476e4SDavid E. O'Brien 
467c80476e4SDavid E. O'Brien /* tw_shvar_next():
468c80476e4SDavid E. O'Brien  *	Return the next shell variable
469c80476e4SDavid E. O'Brien  */
470c80476e4SDavid E. O'Brien /*ARGSUSED*/
47145e5710bSMark Peek int
tw_shvar_next(struct Strbuf * res,struct Strbuf * dir,int * flags)47245e5710bSMark Peek tw_shvar_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
473c80476e4SDavid E. O'Brien {
47423338178SMark Peek     struct varent *p;
47523338178SMark Peek     struct varent *c;
476c80476e4SDavid E. O'Brien 
477c80476e4SDavid E. O'Brien     USE(flags);
478c80476e4SDavid E. O'Brien     USE(dir);
479c80476e4SDavid E. O'Brien     if ((p = tw_vptr) == NULL)
48045e5710bSMark Peek 	return 0;		/* just in case */
481c80476e4SDavid E. O'Brien 
48245e5710bSMark Peek     Strbuf_append(res, p->v_name); /* we know that this name is here now */
483c80476e4SDavid E. O'Brien 
484c80476e4SDavid E. O'Brien     /* now find the next one */
485c80476e4SDavid E. O'Brien     for (;;) {
486c80476e4SDavid E. O'Brien 	if (p->v_right) {	/* if we can go right */
487c80476e4SDavid E. O'Brien 	    p = p->v_right;
488c80476e4SDavid E. O'Brien 	    while (p->v_left)
489c80476e4SDavid E. O'Brien 		p = p->v_left;
490c80476e4SDavid E. O'Brien 	}
491c80476e4SDavid E. O'Brien 	else {			/* else go up */
492c80476e4SDavid E. O'Brien 	    do {
493c80476e4SDavid E. O'Brien 		c = p;
494c80476e4SDavid E. O'Brien 		p = p->v_parent;
495c80476e4SDavid E. O'Brien 	    } while (p->v_right == c);
496c80476e4SDavid E. O'Brien 	}
497c80476e4SDavid E. O'Brien 	if (p->v_parent == 0) {	/* is it the header? */
498c80476e4SDavid E. O'Brien 	    tw_vptr = NULL;
49945e5710bSMark Peek 	    return 1;
500c80476e4SDavid E. O'Brien 	}
501c80476e4SDavid E. O'Brien 	if (p->v_name) {
502c80476e4SDavid E. O'Brien 	    tw_vptr = p;	/* save state for the next call */
50345e5710bSMark Peek 	    return 1;
504c80476e4SDavid E. O'Brien 	}
505c80476e4SDavid E. O'Brien     }
506c80476e4SDavid E. O'Brien } /* end tw_shvar_next */
507c80476e4SDavid E. O'Brien 
508c80476e4SDavid E. O'Brien 
509c80476e4SDavid E. O'Brien /* tw_envvar_next():
510c80476e4SDavid E. O'Brien  *	Return the next environment variable
511c80476e4SDavid E. O'Brien  */
512c80476e4SDavid E. O'Brien /*ARGSUSED*/
51345e5710bSMark Peek int
tw_envvar_next(struct Strbuf * res,struct Strbuf * dir,int * flags)51445e5710bSMark Peek tw_envvar_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
515c80476e4SDavid E. O'Brien {
51645e5710bSMark Peek     const Char *ps;
517c80476e4SDavid E. O'Brien 
518c80476e4SDavid E. O'Brien     USE(flags);
519c80476e4SDavid E. O'Brien     USE(dir);
520c80476e4SDavid E. O'Brien     if (tw_env == NULL || *tw_env == NULL)
52145e5710bSMark Peek 	return 0;
52245e5710bSMark Peek     for (ps = *tw_env; *ps && *ps != '='; ps++)
523c80476e4SDavid E. O'Brien 	continue;
52445e5710bSMark Peek     Strbuf_appendn(res, *tw_env, ps - *tw_env);
525c80476e4SDavid E. O'Brien     tw_env++;
52645e5710bSMark Peek     return 1;
527c80476e4SDavid E. O'Brien } /* end tw_envvar_next */
528c80476e4SDavid E. O'Brien 
529c80476e4SDavid E. O'Brien 
530c80476e4SDavid E. O'Brien /* tw_var_start():
531c80476e4SDavid E. O'Brien  *	Begin the list of the shell and environment variables
532c80476e4SDavid E. O'Brien  */
533c80476e4SDavid E. O'Brien /*ARGSUSED*/
534c80476e4SDavid E. O'Brien void
tw_var_start(DIR * dfd,const Char * pat)53545e5710bSMark Peek tw_var_start(DIR *dfd, const Char *pat)
536c80476e4SDavid E. O'Brien {
537c80476e4SDavid E. O'Brien     USE(pat);
538c80476e4SDavid E. O'Brien     SETDIR(dfd)
539c80476e4SDavid E. O'Brien     tw_vptr_start(&shvhed);
540c80476e4SDavid E. O'Brien     tw_env = STR_environ;
541c80476e4SDavid E. O'Brien } /* end tw_var_start */
542c80476e4SDavid E. O'Brien 
543c80476e4SDavid E. O'Brien 
544c80476e4SDavid E. O'Brien /* tw_alias_start():
545c80476e4SDavid E. O'Brien  *	Begin the list of the shell aliases
546c80476e4SDavid E. O'Brien  */
547c80476e4SDavid E. O'Brien /*ARGSUSED*/
548c80476e4SDavid E. O'Brien void
tw_alias_start(DIR * dfd,const Char * pat)54945e5710bSMark Peek tw_alias_start(DIR *dfd, const Char *pat)
550c80476e4SDavid E. O'Brien {
551c80476e4SDavid E. O'Brien     USE(pat);
552c80476e4SDavid E. O'Brien     SETDIR(dfd)
553c80476e4SDavid E. O'Brien     tw_vptr_start(&aliases);
554c80476e4SDavid E. O'Brien     tw_env = NULL;
555c80476e4SDavid E. O'Brien } /* tw_alias_start */
556c80476e4SDavid E. O'Brien 
557c80476e4SDavid E. O'Brien 
558c80476e4SDavid E. O'Brien /* tw_complete_start():
559c80476e4SDavid E. O'Brien  *	Begin the list of completions
560c80476e4SDavid E. O'Brien  */
561c80476e4SDavid E. O'Brien /*ARGSUSED*/
562c80476e4SDavid E. O'Brien void
tw_complete_start(DIR * dfd,const Char * pat)56345e5710bSMark Peek tw_complete_start(DIR *dfd, const Char *pat)
564c80476e4SDavid E. O'Brien {
565c80476e4SDavid E. O'Brien     USE(pat);
566c80476e4SDavid E. O'Brien     SETDIR(dfd)
567c80476e4SDavid E. O'Brien     tw_vptr_start(&completions);
568c80476e4SDavid E. O'Brien     tw_env = NULL;
569c80476e4SDavid E. O'Brien } /* end tw_complete_start */
570c80476e4SDavid E. O'Brien 
571c80476e4SDavid E. O'Brien 
572c80476e4SDavid E. O'Brien /* tw_var_next():
573c80476e4SDavid E. O'Brien  *	Return the next shell or environment variable
574c80476e4SDavid E. O'Brien  */
57545e5710bSMark Peek int
tw_var_next(struct Strbuf * res,struct Strbuf * dir,int * flags)57645e5710bSMark Peek tw_var_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
577c80476e4SDavid E. O'Brien {
57845e5710bSMark Peek     int ret = 0;
579c80476e4SDavid E. O'Brien 
580c80476e4SDavid E. O'Brien     if (tw_vptr)
58145e5710bSMark Peek 	ret = tw_shvar_next(res, dir, flags);
58245e5710bSMark Peek     if (ret == 0 && tw_env)
58345e5710bSMark Peek 	ret = tw_envvar_next(res, dir, flags);
58445e5710bSMark Peek     return ret;
585c80476e4SDavid E. O'Brien } /* end tw_var_next */
586c80476e4SDavid E. O'Brien 
587c80476e4SDavid E. O'Brien 
588c80476e4SDavid E. O'Brien /* tw_logname_start():
589c80476e4SDavid E. O'Brien  *	Initialize lognames to the beginning of the list
590c80476e4SDavid E. O'Brien  */
591c80476e4SDavid E. O'Brien /*ARGSUSED*/
592c80476e4SDavid E. O'Brien void
tw_logname_start(DIR * dfd,const Char * pat)59345e5710bSMark Peek tw_logname_start(DIR *dfd, const Char *pat)
594c80476e4SDavid E. O'Brien {
595c80476e4SDavid E. O'Brien     USE(pat);
596c80476e4SDavid E. O'Brien     SETDIR(dfd)
59723338178SMark Peek #ifdef HAVE_GETPWENT
598c80476e4SDavid E. O'Brien     (void) setpwent();	/* Open passwd file */
59923338178SMark Peek #endif
600c80476e4SDavid E. O'Brien } /* end tw_logname_start */
601c80476e4SDavid E. O'Brien 
602c80476e4SDavid E. O'Brien 
603c80476e4SDavid E. O'Brien /* tw_logname_next():
604c80476e4SDavid E. O'Brien  *	Return the next entry from the passwd file
605c80476e4SDavid E. O'Brien  */
606c80476e4SDavid E. O'Brien /*ARGSUSED*/
60745e5710bSMark Peek int
tw_logname_next(struct Strbuf * res,struct Strbuf * dir,int * flags)60845e5710bSMark Peek tw_logname_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
609c80476e4SDavid E. O'Brien {
610c80476e4SDavid E. O'Brien     struct passwd *pw;
61145e5710bSMark Peek 
612c80476e4SDavid E. O'Brien     /*
613c80476e4SDavid E. O'Brien      * We don't want to get interrupted inside getpwent()
614c80476e4SDavid E. O'Brien      * because the yellow pages code is not interruptible,
615c80476e4SDavid E. O'Brien      * and if we call endpwent() immediatetely after
616c80476e4SDavid E. O'Brien      * (in pintr()) we may be freeing an invalid pointer
617c80476e4SDavid E. O'Brien      */
618c80476e4SDavid E. O'Brien     USE(flags);
619c80476e4SDavid E. O'Brien     USE(dir);
62045e5710bSMark Peek     pintr_disabled++;
62123338178SMark Peek #ifdef HAVE_GETPWENT
62223338178SMark Peek     pw = getpwent();
62323338178SMark Peek #else
624c80476e4SDavid E. O'Brien     pw = NULL;
62523338178SMark Peek #endif
62645e5710bSMark Peek     disabled_cleanup(&pintr_disabled);
627c80476e4SDavid E. O'Brien 
628c80476e4SDavid E. O'Brien     if (pw == NULL) {
629c80476e4SDavid E. O'Brien #ifdef YPBUGS
630c80476e4SDavid E. O'Brien 	fix_yp_bugs();
631c80476e4SDavid E. O'Brien #endif
63245e5710bSMark Peek 	return 0;
633c80476e4SDavid E. O'Brien     }
63445e5710bSMark Peek     Strbuf_append(res, str2short(pw->pw_name));
63545e5710bSMark Peek     return 1;
636c80476e4SDavid E. O'Brien } /* end tw_logname_next */
637c80476e4SDavid E. O'Brien 
638c80476e4SDavid E. O'Brien 
639c80476e4SDavid E. O'Brien /* tw_logname_end():
640c80476e4SDavid E. O'Brien  *	Close the passwd file to finish the logname list
641c80476e4SDavid E. O'Brien  */
642c80476e4SDavid E. O'Brien void
tw_logname_end(void)64345e5710bSMark Peek tw_logname_end(void)
644c80476e4SDavid E. O'Brien {
645c80476e4SDavid E. O'Brien #ifdef YPBUGS
646c80476e4SDavid E. O'Brien     fix_yp_bugs();
647c80476e4SDavid E. O'Brien #endif
64823338178SMark Peek #ifdef HAVE_GETPWENT
649c80476e4SDavid E. O'Brien    (void) endpwent();
65023338178SMark Peek #endif
651c80476e4SDavid E. O'Brien } /* end tw_logname_end */
652c80476e4SDavid E. O'Brien 
653c80476e4SDavid E. O'Brien 
654c80476e4SDavid E. O'Brien /* tw_grpname_start():
655c80476e4SDavid E. O'Brien  *	Initialize grpnames to the beginning of the list
656c80476e4SDavid E. O'Brien  */
657c80476e4SDavid E. O'Brien /*ARGSUSED*/
658c80476e4SDavid E. O'Brien void
tw_grpname_start(DIR * dfd,const Char * pat)65945e5710bSMark Peek tw_grpname_start(DIR *dfd, const Char *pat)
660c80476e4SDavid E. O'Brien {
661c80476e4SDavid E. O'Brien     USE(pat);
662c80476e4SDavid E. O'Brien     SETDIR(dfd)
6633b6eaa7bSAndrey A. Chernov #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) && !defined (__ANDROID__)
664c80476e4SDavid E. O'Brien     (void) setgrent();	/* Open group file */
6653b6eaa7bSAndrey A. Chernov #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */
666c80476e4SDavid E. O'Brien } /* end tw_grpname_start */
667c80476e4SDavid E. O'Brien 
668c80476e4SDavid E. O'Brien 
669c80476e4SDavid E. O'Brien /* tw_grpname_next():
670c80476e4SDavid E. O'Brien  *	Return the next entry from the group file
671c80476e4SDavid E. O'Brien  */
672c80476e4SDavid E. O'Brien /*ARGSUSED*/
67345e5710bSMark Peek int
tw_grpname_next(struct Strbuf * res,struct Strbuf * dir,int * flags)67445e5710bSMark Peek tw_grpname_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
675c80476e4SDavid E. O'Brien {
676c80476e4SDavid E. O'Brien     struct group *gr;
67745e5710bSMark Peek 
678c80476e4SDavid E. O'Brien     /*
679c80476e4SDavid E. O'Brien      * We don't want to get interrupted inside getgrent()
680c80476e4SDavid E. O'Brien      * because the yellow pages code is not interruptible,
681c80476e4SDavid E. O'Brien      * and if we call endgrent() immediatetely after
682c80476e4SDavid E. O'Brien      * (in pintr()) we may be freeing an invalid pointer
683c80476e4SDavid E. O'Brien      */
684c80476e4SDavid E. O'Brien     USE(flags);
685c80476e4SDavid E. O'Brien     USE(dir);
68645e5710bSMark Peek     pintr_disabled++;
6873b6eaa7bSAndrey A. Chernov #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) && !defined(__ANDROID__)
68845e5710bSMark Peek     errno = 0;
68945e5710bSMark Peek     while ((gr = getgrent()) == NULL && errno == EINTR) {
69045e5710bSMark Peek 	handle_pending_signals();
69145e5710bSMark Peek 	errno = 0;
69245e5710bSMark Peek     }
6933b6eaa7bSAndrey A. Chernov #else /* _VMS_POSIX || _OSD_POSIX || WINNT_NATIVE */
694c80476e4SDavid E. O'Brien     gr = NULL;
6953b6eaa7bSAndrey A. Chernov #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */
69645e5710bSMark Peek     disabled_cleanup(&pintr_disabled);
697c80476e4SDavid E. O'Brien 
698c80476e4SDavid E. O'Brien     if (gr == NULL) {
699c80476e4SDavid E. O'Brien #ifdef YPBUGS
700c80476e4SDavid E. O'Brien 	fix_yp_bugs();
701c80476e4SDavid E. O'Brien #endif
70245e5710bSMark Peek 	return 0;
703c80476e4SDavid E. O'Brien     }
70445e5710bSMark Peek     Strbuf_append(res, str2short(gr->gr_name));
70545e5710bSMark Peek     return 1;
706c80476e4SDavid E. O'Brien } /* end tw_grpname_next */
707c80476e4SDavid E. O'Brien 
708c80476e4SDavid E. O'Brien 
709c80476e4SDavid E. O'Brien /* tw_grpname_end():
710c80476e4SDavid E. O'Brien  *	Close the group file to finish the groupname list
711c80476e4SDavid E. O'Brien  */
712c80476e4SDavid E. O'Brien void
tw_grpname_end(void)71345e5710bSMark Peek tw_grpname_end(void)
714c80476e4SDavid E. O'Brien {
715c80476e4SDavid E. O'Brien #ifdef YPBUGS
716c80476e4SDavid E. O'Brien     fix_yp_bugs();
717c80476e4SDavid E. O'Brien #endif
7183b6eaa7bSAndrey A. Chernov #if !defined(_VMS_POSIX) && !defined(_OSD_POSIX) && !defined(WINNT_NATIVE) && !defined (__ANDROID__)
719c80476e4SDavid E. O'Brien    (void) endgrent();
7203b6eaa7bSAndrey A. Chernov #endif /* !_VMS_POSIX && !_OSD_POSIX && !WINNT_NATIVE */
721c80476e4SDavid E. O'Brien } /* end tw_grpname_end */
722c80476e4SDavid E. O'Brien 
723c80476e4SDavid E. O'Brien /* tw_file_start():
724c80476e4SDavid E. O'Brien  *	Initialize the directory for the file list
725c80476e4SDavid E. O'Brien  */
726c80476e4SDavid E. O'Brien /*ARGSUSED*/
727c80476e4SDavid E. O'Brien void
tw_file_start(DIR * dfd,const Char * pat)72845e5710bSMark Peek tw_file_start(DIR *dfd, const Char *pat)
729c80476e4SDavid E. O'Brien {
730c80476e4SDavid E. O'Brien     struct varent *vp;
731c80476e4SDavid E. O'Brien     USE(pat);
732c80476e4SDavid E. O'Brien     SETDIR(dfd)
733c80476e4SDavid E. O'Brien     if ((vp = adrof(STRcdpath)) != NULL)
734c80476e4SDavid E. O'Brien 	tw_env = vp->vec;
735c80476e4SDavid E. O'Brien } /* end tw_file_start */
736c80476e4SDavid E. O'Brien 
737c80476e4SDavid E. O'Brien 
738c80476e4SDavid E. O'Brien /* tw_file_next():
739c80476e4SDavid E. O'Brien  *	Return the next file in the directory
740c80476e4SDavid E. O'Brien  */
74145e5710bSMark Peek int
tw_file_next(struct Strbuf * res,struct Strbuf * dir,int * flags)74245e5710bSMark Peek tw_file_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
743c80476e4SDavid E. O'Brien {
74445e5710bSMark Peek     int ret = tw_dir_next(res, tw_dir_fd);
74545e5710bSMark Peek     if (ret == 0 && (*flags & TW_DIR_OK) != 0) {
746c80476e4SDavid E. O'Brien 	CLRDIR(tw_dir_fd)
747c80476e4SDavid E. O'Brien 	while (tw_env && *tw_env)
748c80476e4SDavid E. O'Brien 	    if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL)
749c80476e4SDavid E. O'Brien 		break;
750c80476e4SDavid E. O'Brien 	    else
751c80476e4SDavid E. O'Brien 		tw_env++;
752c80476e4SDavid E. O'Brien 
753c80476e4SDavid E. O'Brien 	if (tw_dir_fd) {
75445e5710bSMark Peek 	    dir->len = 0;
75545e5710bSMark Peek 	    Strbuf_append(dir, *tw_env++);
75645e5710bSMark Peek 	    Strbuf_append1(dir, '/');
75745e5710bSMark Peek 	    Strbuf_terminate(dir);
75845e5710bSMark Peek 	    ret = tw_dir_next(res, tw_dir_fd);
759c80476e4SDavid E. O'Brien 	}
760c80476e4SDavid E. O'Brien     }
76145e5710bSMark Peek     return ret;
762c80476e4SDavid E. O'Brien } /* end tw_file_next */
763c80476e4SDavid E. O'Brien 
764c80476e4SDavid E. O'Brien 
765c80476e4SDavid E. O'Brien /* tw_dir_end():
766c80476e4SDavid E. O'Brien  *	Clear directory related lists
767c80476e4SDavid E. O'Brien  */
768c80476e4SDavid E. O'Brien void
tw_dir_end(void)76945e5710bSMark Peek tw_dir_end(void)
770c80476e4SDavid E. O'Brien {
771c80476e4SDavid E. O'Brien    CLRDIR(tw_dir_fd)
772c80476e4SDavid E. O'Brien    CLRDIR(tw_cmd_state.dfd)
773c80476e4SDavid E. O'Brien } /* end tw_dir_end */
774c80476e4SDavid E. O'Brien 
775c80476e4SDavid E. O'Brien 
776c80476e4SDavid E. O'Brien /* tw_item_free():
777c80476e4SDavid E. O'Brien  *	Free the item list
778c80476e4SDavid E. O'Brien  */
779c80476e4SDavid E. O'Brien void
tw_item_free(void)78045e5710bSMark Peek tw_item_free(void)
781c80476e4SDavid E. O'Brien {
782c80476e4SDavid E. O'Brien     tw_str_free(&tw_item);
783c80476e4SDavid E. O'Brien } /* end tw_item_free */
784c80476e4SDavid E. O'Brien 
785c80476e4SDavid E. O'Brien 
786c80476e4SDavid E. O'Brien /* tw_item_get():
787c80476e4SDavid E. O'Brien  *	Return the list of items
788c80476e4SDavid E. O'Brien  */
789c80476e4SDavid E. O'Brien Char **
tw_item_get(void)79045e5710bSMark Peek tw_item_get(void)
791c80476e4SDavid E. O'Brien {
792c80476e4SDavid E. O'Brien     return tw_item.list;
793c80476e4SDavid E. O'Brien } /* end tw_item_get */
794c80476e4SDavid E. O'Brien 
795c80476e4SDavid E. O'Brien 
796c80476e4SDavid E. O'Brien /* tw_item_add():
79745e5710bSMark Peek  *	Return a new item for a Strbuf_terminate()'d s
798c80476e4SDavid E. O'Brien  */
79945e5710bSMark Peek void
tw_item_add(const struct Strbuf * s)80045e5710bSMark Peek tw_item_add(const struct Strbuf *s)
801c80476e4SDavid E. O'Brien {
80245e5710bSMark Peek     Char *p;
80345e5710bSMark Peek 
80445e5710bSMark Peek     p = tw_str_add(&tw_item, s->len + 1);
80545e5710bSMark Peek     Strcpy(p, s->s);
806c80476e4SDavid E. O'Brien } /* tw_item_add */
807c80476e4SDavid E. O'Brien 
808c80476e4SDavid E. O'Brien 
809c80476e4SDavid E. O'Brien /* tw_item_find():
810c80476e4SDavid E. O'Brien  *      Find the string if it exists in the item list
811c80476e4SDavid E. O'Brien  *	end return it.
812c80476e4SDavid E. O'Brien  */
813c80476e4SDavid E. O'Brien Char *
tw_item_find(Char * str)81445e5710bSMark Peek tw_item_find(Char *str)
815c80476e4SDavid E. O'Brien {
81645e5710bSMark Peek     size_t i;
817c80476e4SDavid E. O'Brien 
818c80476e4SDavid E. O'Brien     if (tw_item.list == NULL || str == NULL)
819c80476e4SDavid E. O'Brien 	return NULL;
820c80476e4SDavid E. O'Brien 
821c80476e4SDavid E. O'Brien     for (i = 0; i < tw_item.nlist; i++)
822c80476e4SDavid E. O'Brien 	if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0)
823c80476e4SDavid E. O'Brien 	    return tw_item.list[i];
824c80476e4SDavid E. O'Brien     return NULL;
825c80476e4SDavid E. O'Brien } /* end tw_item_find */
826c80476e4SDavid E. O'Brien 
827c80476e4SDavid E. O'Brien 
828c80476e4SDavid E. O'Brien /* tw_vl_start():
829c80476e4SDavid E. O'Brien  *	Initialize a variable list
830c80476e4SDavid E. O'Brien  */
831c80476e4SDavid E. O'Brien void
tw_vl_start(DIR * dfd,const Char * pat)83245e5710bSMark Peek tw_vl_start(DIR *dfd, const Char *pat)
833c80476e4SDavid E. O'Brien {
834c80476e4SDavid E. O'Brien     SETDIR(dfd)
835c80476e4SDavid E. O'Brien     if ((tw_vptr = adrof(pat)) != NULL) {
836c80476e4SDavid E. O'Brien 	tw_env = tw_vptr->vec;
837c80476e4SDavid E. O'Brien 	tw_vptr = NULL;
838c80476e4SDavid E. O'Brien     }
839c80476e4SDavid E. O'Brien     else
840c80476e4SDavid E. O'Brien 	tw_env = NULL;
841c80476e4SDavid E. O'Brien } /* end tw_vl_start */
842c80476e4SDavid E. O'Brien 
843c80476e4SDavid E. O'Brien 
844c80476e4SDavid E. O'Brien /*
845c80476e4SDavid E. O'Brien  * Initialize a word list
846c80476e4SDavid E. O'Brien  */
847c80476e4SDavid E. O'Brien void
tw_wl_start(DIR * dfd,const Char * pat)84845e5710bSMark Peek tw_wl_start(DIR *dfd, const Char *pat)
849c80476e4SDavid E. O'Brien {
850c80476e4SDavid E. O'Brien     SETDIR(dfd);
851c80476e4SDavid E. O'Brien     tw_word = pat;
852c80476e4SDavid E. O'Brien } /* end tw_wl_start */
853c80476e4SDavid E. O'Brien 
854c80476e4SDavid E. O'Brien 
855c80476e4SDavid E. O'Brien /*
856c80476e4SDavid E. O'Brien  * Return the next word from the word list
857c80476e4SDavid E. O'Brien  */
858c80476e4SDavid E. O'Brien /*ARGSUSED*/
85945e5710bSMark Peek int
tw_wl_next(struct Strbuf * res,struct Strbuf * dir,int * flags)86045e5710bSMark Peek tw_wl_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
861c80476e4SDavid E. O'Brien {
86245e5710bSMark Peek     const Char *p;
86345e5710bSMark Peek 
86445e5710bSMark Peek     USE(dir);
865c80476e4SDavid E. O'Brien     USE(flags);
866c80476e4SDavid E. O'Brien     if (tw_word == NULL || tw_word[0] == '\0')
86745e5710bSMark Peek 	return 0;
868c80476e4SDavid E. O'Brien 
869c80476e4SDavid E. O'Brien     while (*tw_word && Isspace(*tw_word)) tw_word++;
870c80476e4SDavid E. O'Brien 
87145e5710bSMark Peek     for (p = tw_word; *tw_word && !Isspace(*tw_word); tw_word++)
872c80476e4SDavid E. O'Brien 	continue;
87345e5710bSMark Peek     if (tw_word == p)
87445e5710bSMark Peek 	return 0;
87545e5710bSMark Peek     Strbuf_appendn(res, p, tw_word - p);
876c80476e4SDavid E. O'Brien     if (*tw_word)
87745e5710bSMark Peek 	tw_word++;
87845e5710bSMark Peek     return 1;
879c80476e4SDavid E. O'Brien } /* end tw_wl_next */
880c80476e4SDavid E. O'Brien 
881c80476e4SDavid E. O'Brien 
882c80476e4SDavid E. O'Brien /* tw_bind_start():
883c80476e4SDavid E. O'Brien  *	Begin the list of the shell bindings
884c80476e4SDavid E. O'Brien  */
885c80476e4SDavid E. O'Brien /*ARGSUSED*/
886c80476e4SDavid E. O'Brien void
tw_bind_start(DIR * dfd,const Char * pat)88745e5710bSMark Peek tw_bind_start(DIR *dfd, const Char *pat)
888c80476e4SDavid E. O'Brien {
889c80476e4SDavid E. O'Brien     USE(pat);
890c80476e4SDavid E. O'Brien     SETDIR(dfd)
891c80476e4SDavid E. O'Brien     tw_bind = FuncNames;
892c80476e4SDavid E. O'Brien } /* end tw_bind_start */
893c80476e4SDavid E. O'Brien 
894c80476e4SDavid E. O'Brien 
895c80476e4SDavid E. O'Brien /* tw_bind_next():
896c80476e4SDavid E. O'Brien  *	Begin the list of the shell bindings
897c80476e4SDavid E. O'Brien  */
898c80476e4SDavid E. O'Brien /*ARGSUSED*/
89945e5710bSMark Peek int
tw_bind_next(struct Strbuf * res,struct Strbuf * dir,int * flags)90045e5710bSMark Peek tw_bind_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
901c80476e4SDavid E. O'Brien {
90245e5710bSMark Peek     USE(dir);
903c80476e4SDavid E. O'Brien     USE(flags);
904c80476e4SDavid E. O'Brien     if (tw_bind && tw_bind->name) {
90545e5710bSMark Peek 	const char *ptr;
90645e5710bSMark Peek 
90745e5710bSMark Peek 	for (ptr = tw_bind->name; *ptr != '\0'; ptr++)
90845e5710bSMark Peek 	    Strbuf_append1(res, *ptr);
909c80476e4SDavid E. O'Brien 	tw_bind++;
91045e5710bSMark Peek 	return 1;
911c80476e4SDavid E. O'Brien     }
91245e5710bSMark Peek     return 0;
913c80476e4SDavid E. O'Brien } /* end tw_bind_next */
914c80476e4SDavid E. O'Brien 
915c80476e4SDavid E. O'Brien 
916c80476e4SDavid E. O'Brien /* tw_limit_start():
917c80476e4SDavid E. O'Brien  *	Begin the list of the shell limitings
918c80476e4SDavid E. O'Brien  */
919c80476e4SDavid E. O'Brien /*ARGSUSED*/
920c80476e4SDavid E. O'Brien void
tw_limit_start(DIR * dfd,const Char * pat)92145e5710bSMark Peek tw_limit_start(DIR *dfd, const Char *pat)
922c80476e4SDavid E. O'Brien {
923c80476e4SDavid E. O'Brien     USE(pat);
924c80476e4SDavid E. O'Brien     SETDIR(dfd)
925c80476e4SDavid E. O'Brien #ifndef HAVENOLIMIT
926c80476e4SDavid E. O'Brien     tw_limit = limits;
927c80476e4SDavid E. O'Brien #endif /* ! HAVENOLIMIT */
928c80476e4SDavid E. O'Brien } /* end tw_limit_start */
929c80476e4SDavid E. O'Brien 
930c80476e4SDavid E. O'Brien 
931c80476e4SDavid E. O'Brien /* tw_limit_next():
932c80476e4SDavid E. O'Brien  *	Begin the list of the shell limitings
933c80476e4SDavid E. O'Brien  */
934c80476e4SDavid E. O'Brien /*ARGSUSED*/
93545e5710bSMark Peek int
tw_limit_next(struct Strbuf * res,struct Strbuf * dir,int * flags)93645e5710bSMark Peek tw_limit_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
937c80476e4SDavid E. O'Brien {
93845e5710bSMark Peek     USE(dir);
93945e5710bSMark Peek     USE(flags);
940c80476e4SDavid E. O'Brien #ifndef HAVENOLIMIT
941c80476e4SDavid E. O'Brien     if (tw_limit && tw_limit->limname) {
94245e5710bSMark Peek 	const char *ptr;
94345e5710bSMark Peek 
94445e5710bSMark Peek 	for (ptr = tw_limit->limname; *ptr != '\0'; ptr++)
94545e5710bSMark Peek 	    Strbuf_append1(res, *ptr);
946c80476e4SDavid E. O'Brien 	tw_limit++;
94745e5710bSMark Peek 	return 1;
948c80476e4SDavid E. O'Brien     }
949c80476e4SDavid E. O'Brien #endif /* ! HAVENOLIMIT */
95045e5710bSMark Peek     return 0;
951c80476e4SDavid E. O'Brien } /* end tw_limit_next */
952c80476e4SDavid E. O'Brien 
953c80476e4SDavid E. O'Brien 
954c80476e4SDavid E. O'Brien /* tw_sig_start():
955c80476e4SDavid E. O'Brien  *	Begin the list of the shell sigings
956c80476e4SDavid E. O'Brien  */
957c80476e4SDavid E. O'Brien /*ARGSUSED*/
958c80476e4SDavid E. O'Brien void
tw_sig_start(DIR * dfd,const Char * pat)95945e5710bSMark Peek tw_sig_start(DIR *dfd, const Char *pat)
960c80476e4SDavid E. O'Brien {
961c80476e4SDavid E. O'Brien     USE(pat);
962c80476e4SDavid E. O'Brien     SETDIR(dfd)
963c80476e4SDavid E. O'Brien     tw_index = 0;
964c80476e4SDavid E. O'Brien } /* end tw_sig_start */
965c80476e4SDavid E. O'Brien 
966c80476e4SDavid E. O'Brien 
967c80476e4SDavid E. O'Brien /* tw_sig_next():
968c80476e4SDavid E. O'Brien  *	Begin the list of the shell sigings
969c80476e4SDavid E. O'Brien  */
970c80476e4SDavid E. O'Brien /*ARGSUSED*/
97145e5710bSMark Peek int
tw_sig_next(struct Strbuf * res,struct Strbuf * dir,int * flags)97245e5710bSMark Peek tw_sig_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
973c80476e4SDavid E. O'Brien {
97445e5710bSMark Peek     USE(dir);
975c80476e4SDavid E. O'Brien     USE(flags);
976c80476e4SDavid E. O'Brien     for (;tw_index < nsig; tw_index++) {
97745e5710bSMark Peek 	const char *ptr;
978c80476e4SDavid E. O'Brien 
979c80476e4SDavid E. O'Brien 	if (mesg[tw_index].iname == NULL)
980c80476e4SDavid E. O'Brien 	    continue;
981c80476e4SDavid E. O'Brien 
98245e5710bSMark Peek 	for (ptr = mesg[tw_index].iname; *ptr != '\0'; ptr++)
98345e5710bSMark Peek 	    Strbuf_append1(res, *ptr);
984c80476e4SDavid E. O'Brien 	tw_index++;
98545e5710bSMark Peek 	return 1;
986c80476e4SDavid E. O'Brien     }
98745e5710bSMark Peek     return 0;
988c80476e4SDavid E. O'Brien } /* end tw_sig_next */
989c80476e4SDavid E. O'Brien 
990c80476e4SDavid E. O'Brien 
991c80476e4SDavid E. O'Brien /* tw_job_start():
992c80476e4SDavid E. O'Brien  *	Begin the list of the shell jobings
993c80476e4SDavid E. O'Brien  */
994c80476e4SDavid E. O'Brien /*ARGSUSED*/
995c80476e4SDavid E. O'Brien void
tw_job_start(DIR * dfd,const Char * pat)99645e5710bSMark Peek tw_job_start(DIR *dfd, const Char *pat)
997c80476e4SDavid E. O'Brien {
998c80476e4SDavid E. O'Brien     USE(pat);
999c80476e4SDavid E. O'Brien     SETDIR(dfd)
1000c80476e4SDavid E. O'Brien     tw_index = 1;
1001c80476e4SDavid E. O'Brien } /* end tw_job_start */
1002c80476e4SDavid E. O'Brien 
1003c80476e4SDavid E. O'Brien 
1004c80476e4SDavid E. O'Brien /* tw_job_next():
1005c80476e4SDavid E. O'Brien  *	Begin the list of the shell jobings
1006c80476e4SDavid E. O'Brien  */
1007c80476e4SDavid E. O'Brien /*ARGSUSED*/
100845e5710bSMark Peek int
tw_job_next(struct Strbuf * res,struct Strbuf * dir,int * flags)100945e5710bSMark Peek tw_job_next(struct Strbuf *res, struct Strbuf *dir, int *flags)
1010c80476e4SDavid E. O'Brien {
1011c80476e4SDavid E. O'Brien     struct process *j;
1012c80476e4SDavid E. O'Brien 
101345e5710bSMark Peek     USE(dir);
1014c80476e4SDavid E. O'Brien     USE(flags);
1015c80476e4SDavid E. O'Brien     for (;tw_index <= pmaxindex; tw_index++) {
1016c80476e4SDavid E. O'Brien 	for (j = proclist.p_next; j != NULL; j = j->p_next)
1017c80476e4SDavid E. O'Brien 	    if (j->p_index == tw_index && j->p_procid == j->p_jobid)
1018c80476e4SDavid E. O'Brien 		break;
1019c80476e4SDavid E. O'Brien 	if (j == NULL)
1020c80476e4SDavid E. O'Brien 	    continue;
102145e5710bSMark Peek 	Strbuf_append(res, j->p_command);
1022c80476e4SDavid E. O'Brien 	tw_index++;
102345e5710bSMark Peek 	return 1;
1024c80476e4SDavid E. O'Brien     }
102545e5710bSMark Peek     return 0;
1026c80476e4SDavid E. O'Brien } /* end tw_job_next */
1027