xref: /freebsd/contrib/tcsh/sh.misc.c (revision 6560ac57ce879857203bc456cdc3849808dc0700)
1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien  * sh.misc.c: Miscelaneous functions
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.
1629301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien  *    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 
3445e5710bSMark Peek static	int	renum	(int, int);
3545e5710bSMark Peek static  Char  **blkend	(Char **);
3645e5710bSMark Peek static  Char  **blkcat	(Char **, Char **);
3745e5710bSMark Peek static	int	xdup2	(int, int);
38c80476e4SDavid E. O'Brien 
39c80476e4SDavid E. O'Brien /*
40c80476e4SDavid E. O'Brien  * C Shell
41c80476e4SDavid E. O'Brien  */
42c80476e4SDavid E. O'Brien 
43c80476e4SDavid E. O'Brien int
any(const char * s,Char c)4445e5710bSMark Peek any(const char *s, Char c)
45c80476e4SDavid E. O'Brien {
46c80476e4SDavid E. O'Brien     if (!s)
47c80476e4SDavid E. O'Brien 	return (0);		/* Check for nil pointer */
48c80476e4SDavid E. O'Brien     while (*s)
4923338178SMark Peek 	if ((Char)*s++ == c)
50c80476e4SDavid E. O'Brien 	    return (1);
51c80476e4SDavid E. O'Brien     return (0);
52c80476e4SDavid E. O'Brien }
53c80476e4SDavid E. O'Brien 
54c80476e4SDavid E. O'Brien void
setzero(void * p,size_t size)5545e5710bSMark Peek setzero(void *p, size_t size)
56c80476e4SDavid E. O'Brien {
5745e5710bSMark Peek     memset(p, 0, size);
58c80476e4SDavid E. O'Brien }
59c80476e4SDavid E. O'Brien 
609ccc37e3SMark Peek #ifndef SHORT_STRINGS
61c80476e4SDavid E. O'Brien char *
strnsave(const char * s,size_t len)6245e5710bSMark Peek strnsave(const char *s, size_t len)
63c80476e4SDavid E. O'Brien {
6445e5710bSMark Peek     char *r;
6545e5710bSMark Peek 
6645e5710bSMark Peek     r = xmalloc(len + 1);
6745e5710bSMark Peek     memcpy(r, s, len);
6845e5710bSMark Peek     r[len] = '\0';
6945e5710bSMark Peek     return r;
7045e5710bSMark Peek }
719ccc37e3SMark Peek #endif
7245e5710bSMark Peek 
7345e5710bSMark Peek char   *
strsave(const char * s)7445e5710bSMark Peek strsave(const char *s)
7545e5710bSMark Peek {
7645e5710bSMark Peek     char   *r;
7745e5710bSMark Peek     size_t size;
78c80476e4SDavid E. O'Brien 
79c80476e4SDavid E. O'Brien     if (s == NULL)
8023338178SMark Peek 	s = "";
8145e5710bSMark Peek     size = strlen(s) + 1;
8245e5710bSMark Peek     r = xmalloc(size);
8345e5710bSMark Peek     memcpy(r, s, size);
8423338178SMark Peek     return (r);
85c80476e4SDavid E. O'Brien }
86c80476e4SDavid E. O'Brien 
87c80476e4SDavid E. O'Brien static Char  **
blkend(Char ** up)8845e5710bSMark Peek blkend(Char **up)
89c80476e4SDavid E. O'Brien {
90c80476e4SDavid E. O'Brien 
91c80476e4SDavid E. O'Brien     while (*up)
92c80476e4SDavid E. O'Brien 	up++;
93c80476e4SDavid E. O'Brien     return (up);
94c80476e4SDavid E. O'Brien }
95c80476e4SDavid E. O'Brien 
96c80476e4SDavid E. O'Brien 
97c80476e4SDavid E. O'Brien void
blkpr(Char * const * av)9845e5710bSMark Peek blkpr(Char *const *av)
99c80476e4SDavid E. O'Brien {
100c80476e4SDavid E. O'Brien 
101c80476e4SDavid E. O'Brien     for (; *av; av++) {
102c80476e4SDavid E. O'Brien 	xprintf("%S", *av);
103c80476e4SDavid E. O'Brien 	if (av[1])
104c80476e4SDavid E. O'Brien 	    xprintf(" ");
105c80476e4SDavid E. O'Brien     }
106c80476e4SDavid E. O'Brien }
107c80476e4SDavid E. O'Brien 
10845e5710bSMark Peek Char *
blkexpand(Char * const * av)10945e5710bSMark Peek blkexpand(Char *const *av)
110c80476e4SDavid E. O'Brien {
11145e5710bSMark Peek     struct Strbuf buf = Strbuf_INIT;
11245e5710bSMark Peek 
113c80476e4SDavid E. O'Brien     for (; *av; av++) {
11445e5710bSMark Peek 	Strbuf_append(&buf, *av);
115c80476e4SDavid E. O'Brien 	if (av[1])
11645e5710bSMark Peek 	    Strbuf_append1(&buf, ' ');
117c80476e4SDavid E. O'Brien     }
11845e5710bSMark Peek     return Strbuf_finish(&buf);
119c80476e4SDavid E. O'Brien }
120c80476e4SDavid E. O'Brien 
121c80476e4SDavid E. O'Brien int
blklen(Char ** av)12245e5710bSMark Peek blklen(Char **av)
123c80476e4SDavid E. O'Brien {
12423338178SMark Peek     int i = 0;
125c80476e4SDavid E. O'Brien 
126c80476e4SDavid E. O'Brien     while (*av++)
127c80476e4SDavid E. O'Brien 	i++;
128c80476e4SDavid E. O'Brien     return (i);
129c80476e4SDavid E. O'Brien }
130c80476e4SDavid E. O'Brien 
131c80476e4SDavid E. O'Brien Char  **
blkcpy(Char ** oav,Char ** bv)13245e5710bSMark Peek blkcpy(Char **oav, Char **bv)
133c80476e4SDavid E. O'Brien {
13423338178SMark Peek     Char **av = oav;
135c80476e4SDavid E. O'Brien 
136c80476e4SDavid E. O'Brien     while ((*av++ = *bv++) != NULL)
137c80476e4SDavid E. O'Brien 	continue;
138c80476e4SDavid E. O'Brien     return (oav);
139c80476e4SDavid E. O'Brien }
140c80476e4SDavid E. O'Brien 
141c80476e4SDavid E. O'Brien static Char  **
blkcat(Char ** up,Char ** vp)14245e5710bSMark Peek blkcat(Char **up, Char **vp)
143c80476e4SDavid E. O'Brien {
144c80476e4SDavid E. O'Brien 
145c80476e4SDavid E. O'Brien     (void) blkcpy(blkend(up), vp);
146c80476e4SDavid E. O'Brien     return (up);
147c80476e4SDavid E. O'Brien }
148c80476e4SDavid E. O'Brien 
149c80476e4SDavid E. O'Brien void
blkfree(Char ** av0)15045e5710bSMark Peek blkfree(Char **av0)
151c80476e4SDavid E. O'Brien {
15223338178SMark Peek     Char **av = av0;
153c80476e4SDavid E. O'Brien 
154c80476e4SDavid E. O'Brien     if (!av0)
155c80476e4SDavid E. O'Brien 	return;
156c80476e4SDavid E. O'Brien     for (; *av; av++)
15745e5710bSMark Peek 	xfree(*av);
15845e5710bSMark Peek     xfree(av0);
15945e5710bSMark Peek }
16045e5710bSMark Peek 
16145e5710bSMark Peek void
blk_cleanup(void * ptr)16245e5710bSMark Peek blk_cleanup(void *ptr)
16345e5710bSMark Peek {
16445e5710bSMark Peek     blkfree(ptr);
16545e5710bSMark Peek }
16645e5710bSMark Peek 
16745e5710bSMark Peek void
blk_indirect_cleanup(void * xptr)16845e5710bSMark Peek blk_indirect_cleanup(void *xptr)
16945e5710bSMark Peek {
17045e5710bSMark Peek     Char ***ptr;
17145e5710bSMark Peek 
17245e5710bSMark Peek     ptr = xptr;
17345e5710bSMark Peek     blkfree(*ptr);
17445e5710bSMark Peek     xfree(ptr);
175c80476e4SDavid E. O'Brien }
176c80476e4SDavid E. O'Brien 
177c80476e4SDavid E. O'Brien Char  **
saveblk(Char ** v)17845e5710bSMark Peek saveblk(Char **v)
179c80476e4SDavid E. O'Brien {
18045e5710bSMark Peek     Char **newv, **onewv;
18145e5710bSMark Peek 
18245e5710bSMark Peek     if (v == NULL)
18345e5710bSMark Peek 	return NULL;
18445e5710bSMark Peek 
18545e5710bSMark Peek     onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
186c80476e4SDavid E. O'Brien 
187c80476e4SDavid E. O'Brien     while (*v)
188c80476e4SDavid E. O'Brien 	*newv++ = Strsave(*v++);
189c80476e4SDavid E. O'Brien     return (onewv);
190c80476e4SDavid E. O'Brien }
191c80476e4SDavid E. O'Brien 
19223338178SMark Peek #ifndef HAVE_STRSTR
193c80476e4SDavid E. O'Brien char   *
strstr(const char * s,const char * t)19445e5710bSMark Peek strstr(const char *s, const char *t)
195c80476e4SDavid E. O'Brien {
196c80476e4SDavid E. O'Brien     do {
19723338178SMark Peek 	const char *ss = s;
19823338178SMark Peek 	const char *tt = t;
199c80476e4SDavid E. O'Brien 
200c80476e4SDavid E. O'Brien 	do
201c80476e4SDavid E. O'Brien 	    if (*tt == '\0')
20245e5710bSMark Peek 		return (s);
203c80476e4SDavid E. O'Brien 	while (*ss++ == *tt++);
204c80476e4SDavid E. O'Brien     } while (*s++ != '\0');
205c80476e4SDavid E. O'Brien     return (NULL);
206c80476e4SDavid E. O'Brien }
20723338178SMark Peek #endif /* !HAVE_STRSTR */
208c80476e4SDavid E. O'Brien 
209c80476e4SDavid E. O'Brien char   *
strspl(const char * cp,const char * dp)21045e5710bSMark Peek strspl(const char *cp, const char *dp)
211c80476e4SDavid E. O'Brien {
212c80476e4SDavid E. O'Brien     char   *ep;
21323338178SMark Peek     size_t cl, dl;
214c80476e4SDavid E. O'Brien 
215c80476e4SDavid E. O'Brien     if (!cp)
216c80476e4SDavid E. O'Brien 	cp = "";
217c80476e4SDavid E. O'Brien     if (!dp)
218c80476e4SDavid E. O'Brien 	dp = "";
21923338178SMark Peek     cl = strlen(cp);
22023338178SMark Peek     dl = strlen(dp);
22145e5710bSMark Peek     ep = xmalloc((cl + dl + 1) * sizeof(char));
22223338178SMark Peek     memcpy(ep, cp, cl);
22323338178SMark Peek     memcpy(ep + cl, dp, dl + 1);
224c80476e4SDavid E. O'Brien     return (ep);
225c80476e4SDavid E. O'Brien }
226c80476e4SDavid E. O'Brien 
227c80476e4SDavid E. O'Brien Char  **
blkspl(Char ** up,Char ** vp)22845e5710bSMark Peek blkspl(Char **up, Char **vp)
229c80476e4SDavid E. O'Brien {
23045e5710bSMark Peek     Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
231c80476e4SDavid E. O'Brien 
232c80476e4SDavid E. O'Brien     (void) blkcpy(wp, up);
233c80476e4SDavid E. O'Brien     return (blkcat(wp, vp));
234c80476e4SDavid E. O'Brien }
235c80476e4SDavid E. O'Brien 
236c80476e4SDavid E. O'Brien Char
lastchr(Char * cp)23745e5710bSMark Peek lastchr(Char *cp)
238c80476e4SDavid E. O'Brien {
239c80476e4SDavid E. O'Brien 
240c80476e4SDavid E. O'Brien     if (!cp)
241c80476e4SDavid E. O'Brien 	return (0);
242c80476e4SDavid E. O'Brien     if (!*cp)
243c80476e4SDavid E. O'Brien 	return (0);
244c80476e4SDavid E. O'Brien     while (cp[1])
245c80476e4SDavid E. O'Brien 	cp++;
246c80476e4SDavid E. O'Brien     return (*cp);
247c80476e4SDavid E. O'Brien }
248c80476e4SDavid E. O'Brien 
249c80476e4SDavid E. O'Brien /*
250c80476e4SDavid E. O'Brien  * This routine is called after an error to close up
251c80476e4SDavid E. O'Brien  * any units which may have been left open accidentally.
252c80476e4SDavid E. O'Brien  */
253c80476e4SDavid E. O'Brien void
closem(void)25445e5710bSMark Peek closem(void)
255c80476e4SDavid E. O'Brien {
25645e5710bSMark Peek     int f, num_files;
257cc698b49SBrooks Davis #ifdef S_ISSOCK
258cc698b49SBrooks Davis     struct stat st;
259cc698b49SBrooks Davis #endif /*S_ISSOCK*/
260c80476e4SDavid E. O'Brien 
261b2d5d167SMark Peek #ifdef NLS_BUGS
262b2d5d167SMark Peek #ifdef NLS_CATALOGS
26323338178SMark Peek     nlsclose();
264b2d5d167SMark Peek #endif /* NLS_CATALOGS */
265b2d5d167SMark Peek #endif /* NLS_BUGS */
266c80476e4SDavid E. O'Brien #ifdef YPBUGS
267c80476e4SDavid E. O'Brien     /* suggested by Justin Bur; thanks to Karl Kleinpaste */
268c80476e4SDavid E. O'Brien     fix_yp_bugs();
269c80476e4SDavid E. O'Brien #endif /* YPBUGS */
27045e5710bSMark Peek     num_files = NOFILE;
27145e5710bSMark Peek     for (f = 0; f < num_files; f++)
272c80476e4SDavid E. O'Brien 	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
273c80476e4SDavid E. O'Brien 	    f != FSHTTY
274c80476e4SDavid E. O'Brien #ifdef MALLOC_TRACE
275c80476e4SDavid E. O'Brien 	    && f != 25
276c80476e4SDavid E. O'Brien #endif /* MALLOC_TRACE */
277cc698b49SBrooks Davis #ifdef S_ISSOCK
278cc698b49SBrooks Davis 	    /* NSS modules (e.g. Linux nss_ldap) might keep sockets open.
279cc698b49SBrooks Davis 	     * If we close such a socket, both the NSS module and tcsh think
280cc698b49SBrooks Davis 	     * they "own" the descriptor.
281cc698b49SBrooks Davis 	     *
282cc698b49SBrooks Davis 	     * Not closing sockets does not make the cleanup use of closem()
283cc698b49SBrooks Davis 	     * less reliable because tcsh never creates sockets.
284cc698b49SBrooks Davis 	     */
285cc698b49SBrooks Davis 	    && fstat(f, &st) == 0 && !S_ISSOCK(st.st_mode)
286cc698b49SBrooks Davis #endif
287c80476e4SDavid E. O'Brien 	    )
288c80476e4SDavid E. O'Brien 	  {
28945e5710bSMark Peek 	    xclose(f);
290c80476e4SDavid E. O'Brien #ifdef NISPLUS
291c80476e4SDavid E. O'Brien 	    if (f < 3)
29245e5710bSMark Peek 		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
293c80476e4SDavid E. O'Brien #endif /* NISPLUS */
294c80476e4SDavid E. O'Brien 	  }
295b2d5d167SMark Peek #ifdef NLS_BUGS
296b2d5d167SMark Peek #ifdef NLS_CATALOGS
297b2d5d167SMark Peek     nlsinit();
298b2d5d167SMark Peek #endif /* NLS_CATALOGS */
299b2d5d167SMark Peek #endif /* NLS_BUGS */
300c80476e4SDavid E. O'Brien }
301c80476e4SDavid E. O'Brien 
302c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC
303c80476e4SDavid E. O'Brien /*
304c80476e4SDavid E. O'Brien  * Close files before executing a file.
305c80476e4SDavid E. O'Brien  * We could be MUCH more intelligent, since (on a version 7 system)
306c80476e4SDavid E. O'Brien  * we need only close files here during a source, the other
307c80476e4SDavid E. O'Brien  * shell fd's being in units 16-19 which are closed automatically!
308c80476e4SDavid E. O'Brien  */
309c80476e4SDavid E. O'Brien void
closech(void)31045e5710bSMark Peek closech(void)
311c80476e4SDavid E. O'Brien {
31245e5710bSMark Peek     int f, num_files;
313c80476e4SDavid E. O'Brien 
314c80476e4SDavid E. O'Brien     if (didcch)
315c80476e4SDavid E. O'Brien 	return;
316c80476e4SDavid E. O'Brien     didcch = 1;
317c80476e4SDavid E. O'Brien     SHIN = 0;
318c80476e4SDavid E. O'Brien     SHOUT = 1;
319c80476e4SDavid E. O'Brien     SHDIAG = 2;
320c80476e4SDavid E. O'Brien     OLDSTD = 0;
321c80476e4SDavid E. O'Brien     isoutatty = isatty(SHOUT);
322c80476e4SDavid E. O'Brien     isdiagatty = isatty(SHDIAG);
32345e5710bSMark Peek     num_files = NOFILE;
32445e5710bSMark Peek     for (f = 3; f < num_files; f++)
32545e5710bSMark Peek 	xclose(f);
326c80476e4SDavid E. O'Brien }
327c80476e4SDavid E. O'Brien 
328c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */
329c80476e4SDavid E. O'Brien 
330c80476e4SDavid E. O'Brien void
donefds(void)33145e5710bSMark Peek donefds(void)
332c80476e4SDavid E. O'Brien {
333c80476e4SDavid E. O'Brien 
33445e5710bSMark Peek     xclose(0);
33545e5710bSMark Peek     xclose(1);
33645e5710bSMark Peek     xclose(2);
337c80476e4SDavid E. O'Brien     didfds = 0;
338c80476e4SDavid E. O'Brien #ifdef NISPLUS
339c80476e4SDavid E. O'Brien     {
34045e5710bSMark Peek 	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
34123338178SMark Peek 	(void)dcopy(fd, 1);
34223338178SMark Peek 	(void)dcopy(fd, 2);
34323338178SMark Peek 	(void)dmove(fd, 0);
344c80476e4SDavid E. O'Brien     }
345c80476e4SDavid E. O'Brien #endif /*NISPLUS*/
346c80476e4SDavid E. O'Brien }
347c80476e4SDavid E. O'Brien 
348c80476e4SDavid E. O'Brien /*
349c80476e4SDavid E. O'Brien  * Move descriptor i to j.
350c80476e4SDavid E. O'Brien  * If j is -1 then we just want to get i to a safe place,
35123338178SMark Peek  * i.e. to a unit > FSAFE.  This also happens in dcopy.
352c80476e4SDavid E. O'Brien  */
353c80476e4SDavid E. O'Brien int
dmove(int i,int j)35445e5710bSMark Peek dmove(int i, int j)
355c80476e4SDavid E. O'Brien {
356c80476e4SDavid E. O'Brien 
357c80476e4SDavid E. O'Brien     if (i == j || i < 0)
358c80476e4SDavid E. O'Brien 	return (i);
35923338178SMark Peek #ifdef HAVE_DUP2
360c80476e4SDavid E. O'Brien     if (j >= 0) {
36145e5710bSMark Peek 	(void) xdup2(i, j);
362c80476e4SDavid E. O'Brien 	if (j != i)
36345e5710bSMark Peek 	    xclose(i);
364c80476e4SDavid E. O'Brien 	return (j);
365c80476e4SDavid E. O'Brien     }
366c80476e4SDavid E. O'Brien #endif
367c80476e4SDavid E. O'Brien     j = dcopy(i, j);
368c80476e4SDavid E. O'Brien     if (j != i)
36945e5710bSMark Peek 	xclose(i);
370c80476e4SDavid E. O'Brien     return (j);
371c80476e4SDavid E. O'Brien }
372c80476e4SDavid E. O'Brien 
373c80476e4SDavid E. O'Brien int
dcopy(int i,int j)37445e5710bSMark Peek dcopy(int i, int j)
375c80476e4SDavid E. O'Brien {
376c80476e4SDavid E. O'Brien 
37723338178SMark Peek     if (i == j || i < 0 || (j < 0 && i > FSAFE))
378c80476e4SDavid E. O'Brien 	return (i);
379c80476e4SDavid E. O'Brien     if (j >= 0) {
38023338178SMark Peek #ifdef HAVE_DUP2
38145e5710bSMark Peek 	(void) xdup2(i, j);
382c80476e4SDavid E. O'Brien 	return (j);
383c80476e4SDavid E. O'Brien #else
38445e5710bSMark Peek 	xclose(j);
385c80476e4SDavid E. O'Brien #endif
386c80476e4SDavid E. O'Brien     }
387c80476e4SDavid E. O'Brien     return (renum(i, j));
388c80476e4SDavid E. O'Brien }
389c80476e4SDavid E. O'Brien 
390c80476e4SDavid E. O'Brien static int
renum(int i,int j)39145e5710bSMark Peek renum(int i, int j)
392c80476e4SDavid E. O'Brien {
39323338178SMark Peek     int k = dup(i);
394c80476e4SDavid E. O'Brien 
395c80476e4SDavid E. O'Brien     if (k < 0)
396c80476e4SDavid E. O'Brien 	return (-1);
39723338178SMark Peek     if (j == -1 && k > FSAFE)
398c80476e4SDavid E. O'Brien 	return (k);
399c80476e4SDavid E. O'Brien     if (k != j) {
400c80476e4SDavid E. O'Brien 	j = renum(k, j);
40145e5710bSMark Peek 	xclose(k);
402c80476e4SDavid E. O'Brien 	return (j);
403c80476e4SDavid E. O'Brien     }
404c80476e4SDavid E. O'Brien     return (k);
405c80476e4SDavid E. O'Brien }
406c80476e4SDavid E. O'Brien 
407c80476e4SDavid E. O'Brien /*
408c80476e4SDavid E. O'Brien  * Left shift a command argument list, discarding
409c80476e4SDavid E. O'Brien  * the first c arguments.  Used in "shift" commands
410c80476e4SDavid E. O'Brien  * as well as by commands like "repeat".
411c80476e4SDavid E. O'Brien  */
412c80476e4SDavid E. O'Brien void
lshift(Char ** v,int c)41345e5710bSMark Peek lshift(Char **v, int c)
414c80476e4SDavid E. O'Brien {
41523338178SMark Peek     Char **u;
416c80476e4SDavid E. O'Brien 
417c80476e4SDavid E. O'Brien     for (u = v; *u && --c >= 0; u++)
41845e5710bSMark Peek 	xfree(*u);
419c80476e4SDavid E. O'Brien     (void) blkcpy(v, u);
420c80476e4SDavid E. O'Brien }
421c80476e4SDavid E. O'Brien 
422c80476e4SDavid E. O'Brien int
number(Char * cp)42345e5710bSMark Peek number(Char *cp)
424c80476e4SDavid E. O'Brien {
425c80476e4SDavid E. O'Brien     if (!cp)
426c80476e4SDavid E. O'Brien 	return (0);
427c80476e4SDavid E. O'Brien     if (*cp == '-') {
428c80476e4SDavid E. O'Brien 	cp++;
429c80476e4SDavid E. O'Brien 	if (!Isdigit(*cp))
430c80476e4SDavid E. O'Brien 	    return (0);
431c80476e4SDavid E. O'Brien 	cp++;
432c80476e4SDavid E. O'Brien     }
433c80476e4SDavid E. O'Brien     while (*cp && Isdigit(*cp))
434c80476e4SDavid E. O'Brien 	cp++;
435c80476e4SDavid E. O'Brien     return (*cp == 0);
436c80476e4SDavid E. O'Brien }
437c80476e4SDavid E. O'Brien 
438c80476e4SDavid E. O'Brien Char  **
copyblk(Char ** v)43945e5710bSMark Peek copyblk(Char **v)
440c80476e4SDavid E. O'Brien {
44145e5710bSMark Peek     Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
442c80476e4SDavid E. O'Brien 
443c80476e4SDavid E. O'Brien     return (blkcpy(nv, v));
444c80476e4SDavid E. O'Brien }
445c80476e4SDavid E. O'Brien 
446c80476e4SDavid E. O'Brien char   *
strend(const char * cp)44745e5710bSMark Peek strend(const char *cp)
448c80476e4SDavid E. O'Brien {
449c80476e4SDavid E. O'Brien     if (!cp)
45045e5710bSMark Peek 	return ((char *)(intptr_t)cp);
451c80476e4SDavid E. O'Brien     while (*cp)
452c80476e4SDavid E. O'Brien 	cp++;
45345e5710bSMark Peek     return ((char *)(intptr_t)cp);
454c80476e4SDavid E. O'Brien }
455c80476e4SDavid E. O'Brien 
456c80476e4SDavid E. O'Brien Char   *
strip(Char * cp)45745e5710bSMark Peek strip(Char *cp)
458c80476e4SDavid E. O'Brien {
45923338178SMark Peek     Char *dp = cp;
460c80476e4SDavid E. O'Brien 
461c80476e4SDavid E. O'Brien     if (!cp)
462c80476e4SDavid E. O'Brien 	return (cp);
46319d2e3deSDmitry Chagin     while (*dp != '\0') {
46419d2e3deSDmitry Chagin #if INVALID_BYTE != 0
46519d2e3deSDmitry Chagin 	if ((*dp & INVALID_BYTE) != INVALID_BYTE)    /* *dp < INVALID_BYTE */
46619d2e3deSDmitry Chagin #endif
46719d2e3deSDmitry Chagin 		*dp &= TRIM;
46819d2e3deSDmitry Chagin 	dp++;
46919d2e3deSDmitry Chagin     }
470c80476e4SDavid E. O'Brien     return (cp);
471c80476e4SDavid E. O'Brien }
472c80476e4SDavid E. O'Brien 
473c80476e4SDavid E. O'Brien Char   *
quote(Char * cp)47445e5710bSMark Peek quote(Char *cp)
475c80476e4SDavid E. O'Brien {
47623338178SMark Peek     Char *dp = cp;
477c80476e4SDavid E. O'Brien 
478c80476e4SDavid E. O'Brien     if (!cp)
479c80476e4SDavid E. O'Brien 	return (cp);
48019d2e3deSDmitry Chagin     while (*dp != '\0') {
48119d2e3deSDmitry Chagin #ifdef WIDE_STRINGS
48219d2e3deSDmitry Chagin 	if ((*dp & 0xffffff80) == 0)	/* *dp < 0x80 */
48319d2e3deSDmitry Chagin #elif defined SHORT_STRINGS
48419d2e3deSDmitry Chagin 	if ((*dp & 0xff80) == 0)	/* *dp < 0x80 */
48519d2e3deSDmitry Chagin #else
48619d2e3deSDmitry Chagin 	if ((*dp & 0x80) == 0)		/* *dp < 0x80 */
48719d2e3deSDmitry Chagin #endif
48819d2e3deSDmitry Chagin 	    *dp |= QUOTE;
48919d2e3deSDmitry Chagin 	dp++;
49019d2e3deSDmitry Chagin     }
491c80476e4SDavid E. O'Brien     return (cp);
492c80476e4SDavid E. O'Brien }
493c80476e4SDavid E. O'Brien 
49445e5710bSMark Peek const Char *
quote_meta(struct Strbuf * buf,const Char * s)49545e5710bSMark Peek quote_meta(struct Strbuf *buf, const Char *s)
496c80476e4SDavid E. O'Brien {
49745e5710bSMark Peek     buf->len = 0;
498c80476e4SDavid E. O'Brien     while (*s != '\0') {
499c80476e4SDavid E. O'Brien 	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
50045e5710bSMark Peek 	    Strbuf_append1(buf, '\\');
50145e5710bSMark Peek 	Strbuf_append1(buf, *s++);
502c80476e4SDavid E. O'Brien     }
50345e5710bSMark Peek     Strbuf_terminate(buf);
50445e5710bSMark Peek     return buf->s;
505c80476e4SDavid E. O'Brien }
506c80476e4SDavid E. O'Brien 
507c80476e4SDavid E. O'Brien void
udvar(Char * name)50845e5710bSMark Peek udvar(Char *name)
509c80476e4SDavid E. O'Brien {
510c80476e4SDavid E. O'Brien     setname(short2str(name));
511c80476e4SDavid E. O'Brien     stderror(ERR_NAME | ERR_UNDVAR);
512c80476e4SDavid E. O'Brien }
513c80476e4SDavid E. O'Brien 
514c80476e4SDavid E. O'Brien int
prefix(const Char * sub,const Char * str)51545e5710bSMark Peek prefix(const Char *sub, const Char *str)
516c80476e4SDavid E. O'Brien {
517c80476e4SDavid E. O'Brien 
518c80476e4SDavid E. O'Brien     for (;;) {
519c80476e4SDavid E. O'Brien 	if (*sub == 0)
520c80476e4SDavid E. O'Brien 	    return (1);
521c80476e4SDavid E. O'Brien 	if (*str == 0)
522c80476e4SDavid E. O'Brien 	    return (0);
523c80476e4SDavid E. O'Brien 	if ((*sub++ & TRIM) != (*str++ & TRIM))
524c80476e4SDavid E. O'Brien 	    return (0);
525c80476e4SDavid E. O'Brien     }
526c80476e4SDavid E. O'Brien }
52745e5710bSMark Peek #ifndef WINNT_NATIVE
52845e5710bSMark Peek char *
areadlink(const char * path)52945e5710bSMark Peek areadlink(const char *path)
53045e5710bSMark Peek {
53145e5710bSMark Peek     char *buf;
53245e5710bSMark Peek     size_t size;
53345e5710bSMark Peek     ssize_t res;
534*5224c2a3SDmitry Chagin #ifdef __IBMC__
535*5224c2a3SDmitry Chagin     /*
536*5224c2a3SDmitry Chagin      * Prevent infinite recursion. Someone should tell me how to expand
537*5224c2a3SDmitry Chagin      * these...
538*5224c2a3SDmitry Chagin      */
539*5224c2a3SDmitry Chagin     size_t i;
540*5224c2a3SDmitry Chagin     static const char *vars[] = {
541*5224c2a3SDmitry Chagin 	"/$VERSION",
542*5224c2a3SDmitry Chagin 	"/$SYSNAME",
543*5224c2a3SDmitry Chagin 	"/$SYSSYMR",
544*5224c2a3SDmitry Chagin 	"/$SYSSYMA",
545*5224c2a3SDmitry Chagin     };
546*5224c2a3SDmitry Chagin     for (i = 0; i < sizeof(vars) / sizeof(vars[0]); i++) {
547*5224c2a3SDmitry Chagin 	if (strcmp(vars[i], path) == 0) {
548*5224c2a3SDmitry Chagin 	    return NULL;
549*5224c2a3SDmitry Chagin 	}
550*5224c2a3SDmitry Chagin     }
551*5224c2a3SDmitry Chagin #endif
552*5224c2a3SDmitry Chagin 
55345e5710bSMark Peek 
55445e5710bSMark Peek     size = MAXPATHLEN + 1;
55545e5710bSMark Peek     buf = xmalloc(size);
55645e5710bSMark Peek     while ((size_t)(res = readlink(path, buf, size)) == size) {
55745e5710bSMark Peek 	size *= 2;
55845e5710bSMark Peek 	buf = xrealloc(buf, size);
55945e5710bSMark Peek     }
56045e5710bSMark Peek     if (res == -1) {
56145e5710bSMark Peek 	int err;
56245e5710bSMark Peek 
56345e5710bSMark Peek 	err = errno;
56445e5710bSMark Peek 	xfree(buf);
56545e5710bSMark Peek 	errno = err;
56645e5710bSMark Peek 	return NULL;
56745e5710bSMark Peek     }
56845e5710bSMark Peek     buf[res] = '\0';
56945e5710bSMark Peek     return xrealloc(buf, res + 1);
57045e5710bSMark Peek }
57145e5710bSMark Peek #endif /*!WINNT_NATIVE*/
57245e5710bSMark Peek 
57345e5710bSMark Peek void
xclose(int fildes)57445e5710bSMark Peek xclose(int fildes)
57545e5710bSMark Peek {
57645e5710bSMark Peek     if (fildes < 0)
57745e5710bSMark Peek 	return;
57845e5710bSMark Peek     while (close(fildes) == -1 && errno == EINTR)
57919d2e3deSDmitry Chagin 	if (handle_pending_signals())
58019d2e3deSDmitry Chagin 	    break;
58145e5710bSMark Peek }
58245e5710bSMark Peek 
58345e5710bSMark Peek void
xclosedir(DIR * dirp)58445e5710bSMark Peek xclosedir(DIR *dirp)
58545e5710bSMark Peek {
58645e5710bSMark Peek     while (closedir(dirp) == -1 && errno == EINTR)
58719d2e3deSDmitry Chagin 	if (handle_pending_signals())
58819d2e3deSDmitry Chagin 	    break;
58945e5710bSMark Peek }
59045e5710bSMark Peek 
59145e5710bSMark Peek int
xcreat(const char * path,mode_t mode)59245e5710bSMark Peek xcreat(const char *path, mode_t mode)
59345e5710bSMark Peek {
59445e5710bSMark Peek     int res;
59545e5710bSMark Peek 
59645e5710bSMark Peek     while ((res = creat(path, mode)) == -1 && errno == EINTR)
59719d2e3deSDmitry Chagin 	if (handle_pending_signals())
59819d2e3deSDmitry Chagin 	    break;
59945e5710bSMark Peek     return res;
60045e5710bSMark Peek }
60145e5710bSMark Peek 
60245e5710bSMark Peek #ifdef HAVE_DUP2
60345e5710bSMark Peek static int
xdup2(int fildes,int fildes2)60445e5710bSMark Peek xdup2(int fildes, int fildes2)
60545e5710bSMark Peek {
60645e5710bSMark Peek     int res;
60745e5710bSMark Peek 
60845e5710bSMark Peek     while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
60919d2e3deSDmitry Chagin 	if (handle_pending_signals())
61019d2e3deSDmitry Chagin 	    break;
61145e5710bSMark Peek     return res;
61245e5710bSMark Peek }
61345e5710bSMark Peek #endif
61445e5710bSMark Peek 
61545e5710bSMark Peek struct group *
xgetgrgid(gid_t xgid)61645e5710bSMark Peek xgetgrgid(gid_t xgid)
61745e5710bSMark Peek {
61845e5710bSMark Peek     struct group *res;
61945e5710bSMark Peek 
62045e5710bSMark Peek     errno = 0;
62145e5710bSMark Peek     while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
62219d2e3deSDmitry Chagin 	if (handle_pending_signals())
62319d2e3deSDmitry Chagin 	    break;
62445e5710bSMark Peek 	errno = 0;
62545e5710bSMark Peek     }
62645e5710bSMark Peek     return res;
62745e5710bSMark Peek }
62845e5710bSMark Peek 
62945e5710bSMark Peek struct passwd *
xgetpwnam(const char * name)63045e5710bSMark Peek xgetpwnam(const char *name)
63145e5710bSMark Peek {
63245e5710bSMark Peek     struct passwd *res;
63345e5710bSMark Peek 
63445e5710bSMark Peek     errno = 0;
63545e5710bSMark Peek     while ((res = getpwnam(name)) == NULL && errno == EINTR) {
63619d2e3deSDmitry Chagin 	if (handle_pending_signals())
63719d2e3deSDmitry Chagin 	    break;
63845e5710bSMark Peek 	errno = 0;
63945e5710bSMark Peek     }
64045e5710bSMark Peek     return res;
64145e5710bSMark Peek }
64245e5710bSMark Peek 
64345e5710bSMark Peek struct passwd *
xgetpwuid(uid_t xuid)64445e5710bSMark Peek xgetpwuid(uid_t xuid)
64545e5710bSMark Peek {
64645e5710bSMark Peek     struct passwd *res;
64745e5710bSMark Peek 
64845e5710bSMark Peek     errno = 0;
64945e5710bSMark Peek     while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
65019d2e3deSDmitry Chagin 	if (handle_pending_signals())
65119d2e3deSDmitry Chagin 	    break;
65245e5710bSMark Peek 	errno = 0;
65345e5710bSMark Peek     }
65445e5710bSMark Peek     return res;
65545e5710bSMark Peek }
65645e5710bSMark Peek 
65745e5710bSMark Peek int
xopen(const char * path,int oflag,...)65845e5710bSMark Peek xopen(const char *path, int oflag, ...)
65945e5710bSMark Peek {
66045e5710bSMark Peek     int res;
66145e5710bSMark Peek 
66245e5710bSMark Peek     if ((oflag & O_CREAT) == 0) {
66345e5710bSMark Peek 	while ((res = open(path, oflag)) == -1 && errno == EINTR)
66419d2e3deSDmitry Chagin 	    if (handle_pending_signals())
66519d2e3deSDmitry Chagin 		break;
66645e5710bSMark Peek     } else {
66745e5710bSMark Peek 	va_list ap;
66845e5710bSMark Peek 	mode_t mode;
66945e5710bSMark Peek 
67045e5710bSMark Peek 	va_start(ap, oflag);
67145e5710bSMark Peek 	/* "int" should actually be "mode_t after default argument
67245e5710bSMark Peek 	   promotions". "int" is the best guess we have, "mode_t" used to be
67345e5710bSMark Peek 	   "unsigned short", which we obviously can't use. */
67445e5710bSMark Peek 	mode = va_arg(ap, int);
67545e5710bSMark Peek 	va_end(ap);
67645e5710bSMark Peek 	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
67719d2e3deSDmitry Chagin 	    if (handle_pending_signals())
67819d2e3deSDmitry Chagin 		break;
67945e5710bSMark Peek     }
68045e5710bSMark Peek     return res;
68145e5710bSMark Peek }
68245e5710bSMark Peek 
68345e5710bSMark Peek ssize_t
xread(int fildes,void * buf,size_t nbyte)68445e5710bSMark Peek xread(int fildes, void *buf, size_t nbyte)
68545e5710bSMark Peek {
686cc698b49SBrooks Davis     ssize_t res = -1;
68745e5710bSMark Peek 
68845e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
68945e5710bSMark Peek        that didn't interrupt any system call. */
69045e5710bSMark Peek     do
69119d2e3deSDmitry Chagin       if (handle_pending_signals())
69219d2e3deSDmitry Chagin 	  break;
69345e5710bSMark Peek     while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
69445e5710bSMark Peek     return res;
69545e5710bSMark Peek }
69645e5710bSMark Peek 
69745e5710bSMark Peek #ifdef POSIX
69845e5710bSMark Peek int
xtcsetattr(int fildes,int optional_actions,const struct termios * termios_p)69945e5710bSMark Peek xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
70045e5710bSMark Peek {
70145e5710bSMark Peek     int res;
70245e5710bSMark Peek 
70345e5710bSMark Peek     while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
70445e5710bSMark Peek 	   errno == EINTR)
70519d2e3deSDmitry Chagin 	if (handle_pending_signals())
70619d2e3deSDmitry Chagin 	    break;
70745e5710bSMark Peek     return res;
70845e5710bSMark Peek }
70945e5710bSMark Peek #endif
71045e5710bSMark Peek 
71145e5710bSMark Peek ssize_t
xwrite(int fildes,const void * buf,size_t nbyte)71245e5710bSMark Peek xwrite(int fildes, const void *buf, size_t nbyte)
71345e5710bSMark Peek {
714cc698b49SBrooks Davis     ssize_t res = -1;
71545e5710bSMark Peek 
71645e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
71745e5710bSMark Peek        that didn't interrupt any system call. */
71845e5710bSMark Peek     do
71919d2e3deSDmitry Chagin       if (handle_pending_signals())
72019d2e3deSDmitry Chagin 	  break;
72145e5710bSMark Peek     while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
72245e5710bSMark Peek     return res;
72345e5710bSMark Peek }
724