xref: /freebsd/contrib/tcsh/sh.misc.c (revision 9ccc37e32070303fb293a2a1697ffa71eeb49b25)
1*9ccc37e3SMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $ */
2c80476e4SDavid E. O'Brien /*
3c80476e4SDavid E. O'Brien  * sh.misc.c: Miscelaneous functions
4c80476e4SDavid E. O'Brien  */
5c80476e4SDavid E. O'Brien /*-
6c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
7c80476e4SDavid E. O'Brien  * All rights reserved.
8c80476e4SDavid E. O'Brien  *
9c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
10c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
11c80476e4SDavid E. O'Brien  * are met:
12c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
13c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
14c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
15c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
16c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1729301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
18c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
19c80476e4SDavid E. O'Brien  *    without specific prior written permission.
20c80476e4SDavid E. O'Brien  *
21c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
32c80476e4SDavid E. O'Brien  */
33c80476e4SDavid E. O'Brien #include "sh.h"
34c80476e4SDavid E. O'Brien 
35*9ccc37e3SMark Peek RCSID("$tcsh: sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $")
36c80476e4SDavid E. O'Brien 
3745e5710bSMark Peek static	int	renum	(int, int);
3845e5710bSMark Peek static  Char  **blkend	(Char **);
3945e5710bSMark Peek static  Char  **blkcat	(Char **, Char **);
4045e5710bSMark Peek static	int	xdup2	(int, int);
41c80476e4SDavid E. O'Brien 
42c80476e4SDavid E. O'Brien /*
43c80476e4SDavid E. O'Brien  * C Shell
44c80476e4SDavid E. O'Brien  */
45c80476e4SDavid E. O'Brien 
46c80476e4SDavid E. O'Brien int
4745e5710bSMark Peek any(const char *s, Char c)
48c80476e4SDavid E. O'Brien {
49c80476e4SDavid E. O'Brien     if (!s)
50c80476e4SDavid E. O'Brien 	return (0);		/* Check for nil pointer */
51c80476e4SDavid E. O'Brien     while (*s)
5223338178SMark Peek 	if ((Char)*s++ == c)
53c80476e4SDavid E. O'Brien 	    return (1);
54c80476e4SDavid E. O'Brien     return (0);
55c80476e4SDavid E. O'Brien }
56c80476e4SDavid E. O'Brien 
57c80476e4SDavid E. O'Brien void
5845e5710bSMark Peek setzero(void *p, size_t size)
59c80476e4SDavid E. O'Brien {
6045e5710bSMark Peek     memset(p, 0, size);
61c80476e4SDavid E. O'Brien }
62c80476e4SDavid E. O'Brien 
63*9ccc37e3SMark Peek #ifndef SHORT_STRINGS
64c80476e4SDavid E. O'Brien char *
6545e5710bSMark Peek strnsave(const char *s, size_t len)
66c80476e4SDavid E. O'Brien {
6745e5710bSMark Peek     char *r;
6845e5710bSMark Peek 
6945e5710bSMark Peek     r = xmalloc(len + 1);
7045e5710bSMark Peek     memcpy(r, s, len);
7145e5710bSMark Peek     r[len] = '\0';
7245e5710bSMark Peek     return r;
7345e5710bSMark Peek }
74*9ccc37e3SMark Peek #endif
7545e5710bSMark Peek 
7645e5710bSMark Peek char   *
7745e5710bSMark Peek strsave(const char *s)
7845e5710bSMark Peek {
7945e5710bSMark Peek     char   *r;
8045e5710bSMark Peek     size_t size;
81c80476e4SDavid E. O'Brien 
82c80476e4SDavid E. O'Brien     if (s == NULL)
8323338178SMark Peek 	s = "";
8445e5710bSMark Peek     size = strlen(s) + 1;
8545e5710bSMark Peek     r = xmalloc(size);
8645e5710bSMark Peek     memcpy(r, s, size);
8723338178SMark Peek     return (r);
88c80476e4SDavid E. O'Brien }
89c80476e4SDavid E. O'Brien 
90c80476e4SDavid E. O'Brien static Char  **
9145e5710bSMark Peek blkend(Char **up)
92c80476e4SDavid E. O'Brien {
93c80476e4SDavid E. O'Brien 
94c80476e4SDavid E. O'Brien     while (*up)
95c80476e4SDavid E. O'Brien 	up++;
96c80476e4SDavid E. O'Brien     return (up);
97c80476e4SDavid E. O'Brien }
98c80476e4SDavid E. O'Brien 
99c80476e4SDavid E. O'Brien 
100c80476e4SDavid E. O'Brien void
10145e5710bSMark Peek blkpr(Char *const *av)
102c80476e4SDavid E. O'Brien {
103c80476e4SDavid E. O'Brien 
104c80476e4SDavid E. O'Brien     for (; *av; av++) {
105c80476e4SDavid E. O'Brien 	xprintf("%S", *av);
106c80476e4SDavid E. O'Brien 	if (av[1])
107c80476e4SDavid E. O'Brien 	    xprintf(" ");
108c80476e4SDavid E. O'Brien     }
109c80476e4SDavid E. O'Brien }
110c80476e4SDavid E. O'Brien 
11145e5710bSMark Peek Char *
11245e5710bSMark Peek blkexpand(Char *const *av)
113c80476e4SDavid E. O'Brien {
11445e5710bSMark Peek     struct Strbuf buf = Strbuf_INIT;
11545e5710bSMark Peek 
116c80476e4SDavid E. O'Brien     for (; *av; av++) {
11745e5710bSMark Peek 	Strbuf_append(&buf, *av);
118c80476e4SDavid E. O'Brien 	if (av[1])
11945e5710bSMark Peek 	    Strbuf_append1(&buf, ' ');
120c80476e4SDavid E. O'Brien     }
12145e5710bSMark Peek     return Strbuf_finish(&buf);
122c80476e4SDavid E. O'Brien }
123c80476e4SDavid E. O'Brien 
124c80476e4SDavid E. O'Brien int
12545e5710bSMark Peek blklen(Char **av)
126c80476e4SDavid E. O'Brien {
12723338178SMark Peek     int i = 0;
128c80476e4SDavid E. O'Brien 
129c80476e4SDavid E. O'Brien     while (*av++)
130c80476e4SDavid E. O'Brien 	i++;
131c80476e4SDavid E. O'Brien     return (i);
132c80476e4SDavid E. O'Brien }
133c80476e4SDavid E. O'Brien 
134c80476e4SDavid E. O'Brien Char  **
13545e5710bSMark Peek blkcpy(Char **oav, Char **bv)
136c80476e4SDavid E. O'Brien {
13723338178SMark Peek     Char **av = oav;
138c80476e4SDavid E. O'Brien 
139c80476e4SDavid E. O'Brien     while ((*av++ = *bv++) != NULL)
140c80476e4SDavid E. O'Brien 	continue;
141c80476e4SDavid E. O'Brien     return (oav);
142c80476e4SDavid E. O'Brien }
143c80476e4SDavid E. O'Brien 
144c80476e4SDavid E. O'Brien static Char  **
14545e5710bSMark Peek blkcat(Char **up, Char **vp)
146c80476e4SDavid E. O'Brien {
147c80476e4SDavid E. O'Brien 
148c80476e4SDavid E. O'Brien     (void) blkcpy(blkend(up), vp);
149c80476e4SDavid E. O'Brien     return (up);
150c80476e4SDavid E. O'Brien }
151c80476e4SDavid E. O'Brien 
152c80476e4SDavid E. O'Brien void
15345e5710bSMark Peek blkfree(Char **av0)
154c80476e4SDavid E. O'Brien {
15523338178SMark Peek     Char **av = av0;
156c80476e4SDavid E. O'Brien 
157c80476e4SDavid E. O'Brien     if (!av0)
158c80476e4SDavid E. O'Brien 	return;
159c80476e4SDavid E. O'Brien     for (; *av; av++)
16045e5710bSMark Peek 	xfree(*av);
16145e5710bSMark Peek     xfree(av0);
16245e5710bSMark Peek }
16345e5710bSMark Peek 
16445e5710bSMark Peek void
16545e5710bSMark Peek blk_cleanup(void *ptr)
16645e5710bSMark Peek {
16745e5710bSMark Peek     blkfree(ptr);
16845e5710bSMark Peek }
16945e5710bSMark Peek 
17045e5710bSMark Peek void
17145e5710bSMark Peek blk_indirect_cleanup(void *xptr)
17245e5710bSMark Peek {
17345e5710bSMark Peek     Char ***ptr;
17445e5710bSMark Peek 
17545e5710bSMark Peek     ptr = xptr;
17645e5710bSMark Peek     blkfree(*ptr);
17745e5710bSMark Peek     xfree(ptr);
178c80476e4SDavid E. O'Brien }
179c80476e4SDavid E. O'Brien 
180c80476e4SDavid E. O'Brien Char  **
18145e5710bSMark Peek saveblk(Char **v)
182c80476e4SDavid E. O'Brien {
18345e5710bSMark Peek     Char **newv, **onewv;
18445e5710bSMark Peek 
18545e5710bSMark Peek     if (v == NULL)
18645e5710bSMark Peek 	return NULL;
18745e5710bSMark Peek 
18845e5710bSMark Peek     onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
189c80476e4SDavid E. O'Brien 
190c80476e4SDavid E. O'Brien     while (*v)
191c80476e4SDavid E. O'Brien 	*newv++ = Strsave(*v++);
192c80476e4SDavid E. O'Brien     return (onewv);
193c80476e4SDavid E. O'Brien }
194c80476e4SDavid E. O'Brien 
19523338178SMark Peek #ifndef HAVE_STRSTR
196c80476e4SDavid E. O'Brien char   *
19745e5710bSMark Peek strstr(const char *s, const char *t)
198c80476e4SDavid E. O'Brien {
199c80476e4SDavid E. O'Brien     do {
20023338178SMark Peek 	const char *ss = s;
20123338178SMark Peek 	const char *tt = t;
202c80476e4SDavid E. O'Brien 
203c80476e4SDavid E. O'Brien 	do
204c80476e4SDavid E. O'Brien 	    if (*tt == '\0')
20545e5710bSMark Peek 		return (s);
206c80476e4SDavid E. O'Brien 	while (*ss++ == *tt++);
207c80476e4SDavid E. O'Brien     } while (*s++ != '\0');
208c80476e4SDavid E. O'Brien     return (NULL);
209c80476e4SDavid E. O'Brien }
21023338178SMark Peek #endif /* !HAVE_STRSTR */
211c80476e4SDavid E. O'Brien 
212c80476e4SDavid E. O'Brien char   *
21345e5710bSMark Peek strspl(const char *cp, const char *dp)
214c80476e4SDavid E. O'Brien {
215c80476e4SDavid E. O'Brien     char   *ep;
21623338178SMark Peek     size_t cl, dl;
217c80476e4SDavid E. O'Brien 
218c80476e4SDavid E. O'Brien     if (!cp)
219c80476e4SDavid E. O'Brien 	cp = "";
220c80476e4SDavid E. O'Brien     if (!dp)
221c80476e4SDavid E. O'Brien 	dp = "";
22223338178SMark Peek     cl = strlen(cp);
22323338178SMark Peek     dl = strlen(dp);
22445e5710bSMark Peek     ep = xmalloc((cl + dl + 1) * sizeof(char));
22523338178SMark Peek     memcpy(ep, cp, cl);
22623338178SMark Peek     memcpy(ep + cl, dp, dl + 1);
227c80476e4SDavid E. O'Brien     return (ep);
228c80476e4SDavid E. O'Brien }
229c80476e4SDavid E. O'Brien 
230c80476e4SDavid E. O'Brien Char  **
23145e5710bSMark Peek blkspl(Char **up, Char **vp)
232c80476e4SDavid E. O'Brien {
23345e5710bSMark Peek     Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
234c80476e4SDavid E. O'Brien 
235c80476e4SDavid E. O'Brien     (void) blkcpy(wp, up);
236c80476e4SDavid E. O'Brien     return (blkcat(wp, vp));
237c80476e4SDavid E. O'Brien }
238c80476e4SDavid E. O'Brien 
239c80476e4SDavid E. O'Brien Char
24045e5710bSMark Peek lastchr(Char *cp)
241c80476e4SDavid E. O'Brien {
242c80476e4SDavid E. O'Brien 
243c80476e4SDavid E. O'Brien     if (!cp)
244c80476e4SDavid E. O'Brien 	return (0);
245c80476e4SDavid E. O'Brien     if (!*cp)
246c80476e4SDavid E. O'Brien 	return (0);
247c80476e4SDavid E. O'Brien     while (cp[1])
248c80476e4SDavid E. O'Brien 	cp++;
249c80476e4SDavid E. O'Brien     return (*cp);
250c80476e4SDavid E. O'Brien }
251c80476e4SDavid E. O'Brien 
252c80476e4SDavid E. O'Brien /*
253c80476e4SDavid E. O'Brien  * This routine is called after an error to close up
254c80476e4SDavid E. O'Brien  * any units which may have been left open accidentally.
255c80476e4SDavid E. O'Brien  */
256c80476e4SDavid E. O'Brien void
25745e5710bSMark Peek closem(void)
258c80476e4SDavid E. O'Brien {
25945e5710bSMark Peek     int f, num_files;
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 */
277c80476e4SDavid E. O'Brien 	    )
278c80476e4SDavid E. O'Brien 	  {
27945e5710bSMark Peek 	    xclose(f);
280c80476e4SDavid E. O'Brien #ifdef NISPLUS
281c80476e4SDavid E. O'Brien 	    if(f < 3)
28245e5710bSMark Peek 		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
283c80476e4SDavid E. O'Brien #endif /* NISPLUS */
284c80476e4SDavid E. O'Brien 	  }
285b2d5d167SMark Peek #ifdef NLS_BUGS
286b2d5d167SMark Peek #ifdef NLS_CATALOGS
287b2d5d167SMark Peek     nlsinit();
288b2d5d167SMark Peek #endif /* NLS_CATALOGS */
289b2d5d167SMark Peek #endif /* NLS_BUGS */
290c80476e4SDavid E. O'Brien }
291c80476e4SDavid E. O'Brien 
292c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC
293c80476e4SDavid E. O'Brien /*
294c80476e4SDavid E. O'Brien  * Close files before executing a file.
295c80476e4SDavid E. O'Brien  * We could be MUCH more intelligent, since (on a version 7 system)
296c80476e4SDavid E. O'Brien  * we need only close files here during a source, the other
297c80476e4SDavid E. O'Brien  * shell fd's being in units 16-19 which are closed automatically!
298c80476e4SDavid E. O'Brien  */
299c80476e4SDavid E. O'Brien void
30045e5710bSMark Peek closech(void)
301c80476e4SDavid E. O'Brien {
30245e5710bSMark Peek     int f, num_files;
303c80476e4SDavid E. O'Brien 
304c80476e4SDavid E. O'Brien     if (didcch)
305c80476e4SDavid E. O'Brien 	return;
306c80476e4SDavid E. O'Brien     didcch = 1;
307c80476e4SDavid E. O'Brien     SHIN = 0;
308c80476e4SDavid E. O'Brien     SHOUT = 1;
309c80476e4SDavid E. O'Brien     SHDIAG = 2;
310c80476e4SDavid E. O'Brien     OLDSTD = 0;
311c80476e4SDavid E. O'Brien     isoutatty = isatty(SHOUT);
312c80476e4SDavid E. O'Brien     isdiagatty = isatty(SHDIAG);
31345e5710bSMark Peek     num_files = NOFILE;
31445e5710bSMark Peek     for (f = 3; f < num_files; f++)
31545e5710bSMark Peek 	xclose(f);
316c80476e4SDavid E. O'Brien }
317c80476e4SDavid E. O'Brien 
318c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */
319c80476e4SDavid E. O'Brien 
320c80476e4SDavid E. O'Brien void
32145e5710bSMark Peek donefds(void)
322c80476e4SDavid E. O'Brien {
323c80476e4SDavid E. O'Brien 
32445e5710bSMark Peek     xclose(0);
32545e5710bSMark Peek     xclose(1);
32645e5710bSMark Peek     xclose(2);
327c80476e4SDavid E. O'Brien     didfds = 0;
328c80476e4SDavid E. O'Brien #ifdef NISPLUS
329c80476e4SDavid E. O'Brien     {
33045e5710bSMark Peek 	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
33123338178SMark Peek 	(void)dcopy(fd, 1);
33223338178SMark Peek 	(void)dcopy(fd, 2);
33323338178SMark Peek 	(void)dmove(fd, 0);
334c80476e4SDavid E. O'Brien     }
335c80476e4SDavid E. O'Brien #endif /*NISPLUS*/
336c80476e4SDavid E. O'Brien }
337c80476e4SDavid E. O'Brien 
338c80476e4SDavid E. O'Brien /*
339c80476e4SDavid E. O'Brien  * Move descriptor i to j.
340c80476e4SDavid E. O'Brien  * If j is -1 then we just want to get i to a safe place,
34123338178SMark Peek  * i.e. to a unit > FSAFE.  This also happens in dcopy.
342c80476e4SDavid E. O'Brien  */
343c80476e4SDavid E. O'Brien int
34445e5710bSMark Peek dmove(int i, int j)
345c80476e4SDavid E. O'Brien {
346c80476e4SDavid E. O'Brien 
347c80476e4SDavid E. O'Brien     if (i == j || i < 0)
348c80476e4SDavid E. O'Brien 	return (i);
34923338178SMark Peek #ifdef HAVE_DUP2
350c80476e4SDavid E. O'Brien     if (j >= 0) {
35145e5710bSMark Peek 	(void) xdup2(i, j);
352c80476e4SDavid E. O'Brien 	if (j != i)
35345e5710bSMark Peek 	    xclose(i);
354c80476e4SDavid E. O'Brien 	return (j);
355c80476e4SDavid E. O'Brien     }
356c80476e4SDavid E. O'Brien #endif
357c80476e4SDavid E. O'Brien     j = dcopy(i, j);
358c80476e4SDavid E. O'Brien     if (j != i)
35945e5710bSMark Peek 	xclose(i);
360c80476e4SDavid E. O'Brien     return (j);
361c80476e4SDavid E. O'Brien }
362c80476e4SDavid E. O'Brien 
363c80476e4SDavid E. O'Brien int
36445e5710bSMark Peek dcopy(int i, int j)
365c80476e4SDavid E. O'Brien {
366c80476e4SDavid E. O'Brien 
36723338178SMark Peek     if (i == j || i < 0 || (j < 0 && i > FSAFE))
368c80476e4SDavid E. O'Brien 	return (i);
369c80476e4SDavid E. O'Brien     if (j >= 0) {
37023338178SMark Peek #ifdef HAVE_DUP2
37145e5710bSMark Peek 	(void) xdup2(i, j);
372c80476e4SDavid E. O'Brien 	return (j);
373c80476e4SDavid E. O'Brien #else
37445e5710bSMark Peek 	xclose(j);
375c80476e4SDavid E. O'Brien #endif
376c80476e4SDavid E. O'Brien     }
377c80476e4SDavid E. O'Brien     return (renum(i, j));
378c80476e4SDavid E. O'Brien }
379c80476e4SDavid E. O'Brien 
380c80476e4SDavid E. O'Brien static int
38145e5710bSMark Peek renum(int i, int j)
382c80476e4SDavid E. O'Brien {
38323338178SMark Peek     int k = dup(i);
384c80476e4SDavid E. O'Brien 
385c80476e4SDavid E. O'Brien     if (k < 0)
386c80476e4SDavid E. O'Brien 	return (-1);
38723338178SMark Peek     if (j == -1 && k > FSAFE)
388c80476e4SDavid E. O'Brien 	return (k);
389c80476e4SDavid E. O'Brien     if (k != j) {
390c80476e4SDavid E. O'Brien 	j = renum(k, j);
39145e5710bSMark Peek 	xclose(k);
392c80476e4SDavid E. O'Brien 	return (j);
393c80476e4SDavid E. O'Brien     }
394c80476e4SDavid E. O'Brien     return (k);
395c80476e4SDavid E. O'Brien }
396c80476e4SDavid E. O'Brien 
397c80476e4SDavid E. O'Brien /*
398c80476e4SDavid E. O'Brien  * Left shift a command argument list, discarding
399c80476e4SDavid E. O'Brien  * the first c arguments.  Used in "shift" commands
400c80476e4SDavid E. O'Brien  * as well as by commands like "repeat".
401c80476e4SDavid E. O'Brien  */
402c80476e4SDavid E. O'Brien void
40345e5710bSMark Peek lshift(Char **v, int c)
404c80476e4SDavid E. O'Brien {
40523338178SMark Peek     Char **u;
406c80476e4SDavid E. O'Brien 
407c80476e4SDavid E. O'Brien     for (u = v; *u && --c >= 0; u++)
40845e5710bSMark Peek 	xfree(*u);
409c80476e4SDavid E. O'Brien     (void) blkcpy(v, u);
410c80476e4SDavid E. O'Brien }
411c80476e4SDavid E. O'Brien 
412c80476e4SDavid E. O'Brien int
41345e5710bSMark Peek number(Char *cp)
414c80476e4SDavid E. O'Brien {
415c80476e4SDavid E. O'Brien     if (!cp)
416c80476e4SDavid E. O'Brien 	return (0);
417c80476e4SDavid E. O'Brien     if (*cp == '-') {
418c80476e4SDavid E. O'Brien 	cp++;
419c80476e4SDavid E. O'Brien 	if (!Isdigit(*cp))
420c80476e4SDavid E. O'Brien 	    return (0);
421c80476e4SDavid E. O'Brien 	cp++;
422c80476e4SDavid E. O'Brien     }
423c80476e4SDavid E. O'Brien     while (*cp && Isdigit(*cp))
424c80476e4SDavid E. O'Brien 	cp++;
425c80476e4SDavid E. O'Brien     return (*cp == 0);
426c80476e4SDavid E. O'Brien }
427c80476e4SDavid E. O'Brien 
428c80476e4SDavid E. O'Brien Char  **
42945e5710bSMark Peek copyblk(Char **v)
430c80476e4SDavid E. O'Brien {
43145e5710bSMark Peek     Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
432c80476e4SDavid E. O'Brien 
433c80476e4SDavid E. O'Brien     return (blkcpy(nv, v));
434c80476e4SDavid E. O'Brien }
435c80476e4SDavid E. O'Brien 
436c80476e4SDavid E. O'Brien char   *
43745e5710bSMark Peek strend(const char *cp)
438c80476e4SDavid E. O'Brien {
439c80476e4SDavid E. O'Brien     if (!cp)
44045e5710bSMark Peek 	return ((char *)(intptr_t)cp);
441c80476e4SDavid E. O'Brien     while (*cp)
442c80476e4SDavid E. O'Brien 	cp++;
44345e5710bSMark Peek     return ((char *)(intptr_t)cp);
444c80476e4SDavid E. O'Brien }
445c80476e4SDavid E. O'Brien 
446c80476e4SDavid E. O'Brien Char   *
44745e5710bSMark Peek strip(Char *cp)
448c80476e4SDavid E. O'Brien {
44923338178SMark Peek     Char *dp = cp;
450c80476e4SDavid E. O'Brien 
451c80476e4SDavid E. O'Brien     if (!cp)
452c80476e4SDavid E. O'Brien 	return (cp);
453c80476e4SDavid E. O'Brien     while ((*dp++ &= TRIM) != '\0')
454c80476e4SDavid E. O'Brien 	continue;
455c80476e4SDavid E. O'Brien     return (cp);
456c80476e4SDavid E. O'Brien }
457c80476e4SDavid E. O'Brien 
458c80476e4SDavid E. O'Brien Char   *
45945e5710bSMark Peek quote(Char *cp)
460c80476e4SDavid E. O'Brien {
46123338178SMark Peek     Char *dp = cp;
462c80476e4SDavid E. O'Brien 
463c80476e4SDavid E. O'Brien     if (!cp)
464c80476e4SDavid E. O'Brien 	return (cp);
465c80476e4SDavid E. O'Brien     while (*dp != '\0')
466c80476e4SDavid E. O'Brien 	*dp++ |= QUOTE;
467c80476e4SDavid E. O'Brien     return (cp);
468c80476e4SDavid E. O'Brien }
469c80476e4SDavid E. O'Brien 
47045e5710bSMark Peek const Char *
47145e5710bSMark Peek quote_meta(struct Strbuf *buf, const Char *s)
472c80476e4SDavid E. O'Brien {
47345e5710bSMark Peek     buf->len = 0;
474c80476e4SDavid E. O'Brien     while (*s != '\0') {
475c80476e4SDavid E. O'Brien 	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
47645e5710bSMark Peek 	    Strbuf_append1(buf, '\\');
47745e5710bSMark Peek 	Strbuf_append1(buf, *s++);
478c80476e4SDavid E. O'Brien     }
47945e5710bSMark Peek     Strbuf_terminate(buf);
48045e5710bSMark Peek     return buf->s;
481c80476e4SDavid E. O'Brien }
482c80476e4SDavid E. O'Brien 
483c80476e4SDavid E. O'Brien void
48445e5710bSMark Peek udvar(Char *name)
485c80476e4SDavid E. O'Brien {
486c80476e4SDavid E. O'Brien     setname(short2str(name));
487c80476e4SDavid E. O'Brien     stderror(ERR_NAME | ERR_UNDVAR);
488c80476e4SDavid E. O'Brien }
489c80476e4SDavid E. O'Brien 
490c80476e4SDavid E. O'Brien int
49145e5710bSMark Peek prefix(const Char *sub, const Char *str)
492c80476e4SDavid E. O'Brien {
493c80476e4SDavid E. O'Brien 
494c80476e4SDavid E. O'Brien     for (;;) {
495c80476e4SDavid E. O'Brien 	if (*sub == 0)
496c80476e4SDavid E. O'Brien 	    return (1);
497c80476e4SDavid E. O'Brien 	if (*str == 0)
498c80476e4SDavid E. O'Brien 	    return (0);
499c80476e4SDavid E. O'Brien 	if ((*sub++ & TRIM) != (*str++ & TRIM))
500c80476e4SDavid E. O'Brien 	    return (0);
501c80476e4SDavid E. O'Brien     }
502c80476e4SDavid E. O'Brien }
50345e5710bSMark Peek #ifndef WINNT_NATIVE
50445e5710bSMark Peek char *
50545e5710bSMark Peek areadlink(const char *path)
50645e5710bSMark Peek {
50745e5710bSMark Peek     char *buf;
50845e5710bSMark Peek     size_t size;
50945e5710bSMark Peek     ssize_t res;
51045e5710bSMark Peek 
51145e5710bSMark Peek     size = MAXPATHLEN + 1;
51245e5710bSMark Peek     buf = xmalloc(size);
51345e5710bSMark Peek     while ((size_t)(res = readlink(path, buf, size)) == size) {
51445e5710bSMark Peek 	size *= 2;
51545e5710bSMark Peek 	buf = xrealloc(buf, size);
51645e5710bSMark Peek     }
51745e5710bSMark Peek     if (res == -1) {
51845e5710bSMark Peek 	int err;
51945e5710bSMark Peek 
52045e5710bSMark Peek 	err = errno;
52145e5710bSMark Peek 	xfree(buf);
52245e5710bSMark Peek 	errno = err;
52345e5710bSMark Peek 	return NULL;
52445e5710bSMark Peek     }
52545e5710bSMark Peek     buf[res] = '\0';
52645e5710bSMark Peek     return xrealloc(buf, res + 1);
52745e5710bSMark Peek }
52845e5710bSMark Peek #endif /*!WINNT_NATIVE*/
52945e5710bSMark Peek 
53045e5710bSMark Peek void
53145e5710bSMark Peek xclose(int fildes)
53245e5710bSMark Peek {
53345e5710bSMark Peek     if (fildes < 0)
53445e5710bSMark Peek 	return;
53545e5710bSMark Peek     while (close(fildes) == -1 && errno == EINTR)
53645e5710bSMark Peek 	handle_pending_signals();
53745e5710bSMark Peek }
53845e5710bSMark Peek 
53945e5710bSMark Peek void
54045e5710bSMark Peek xclosedir(DIR *dirp)
54145e5710bSMark Peek {
54245e5710bSMark Peek     while (closedir(dirp) == -1 && errno == EINTR)
54345e5710bSMark Peek 	handle_pending_signals();
54445e5710bSMark Peek }
54545e5710bSMark Peek 
54645e5710bSMark Peek int
54745e5710bSMark Peek xcreat(const char *path, mode_t mode)
54845e5710bSMark Peek {
54945e5710bSMark Peek     int res;
55045e5710bSMark Peek 
55145e5710bSMark Peek     while ((res = creat(path, mode)) == -1 && errno == EINTR)
55245e5710bSMark Peek 	handle_pending_signals();
55345e5710bSMark Peek     return res;
55445e5710bSMark Peek }
55545e5710bSMark Peek 
55645e5710bSMark Peek #ifdef HAVE_DUP2
55745e5710bSMark Peek static int
55845e5710bSMark Peek xdup2(int fildes, int fildes2)
55945e5710bSMark Peek {
56045e5710bSMark Peek     int res;
56145e5710bSMark Peek 
56245e5710bSMark Peek     while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
56345e5710bSMark Peek 	handle_pending_signals();
56445e5710bSMark Peek     return res;
56545e5710bSMark Peek }
56645e5710bSMark Peek #endif
56745e5710bSMark Peek 
56845e5710bSMark Peek struct group *
56945e5710bSMark Peek xgetgrgid(gid_t xgid)
57045e5710bSMark Peek {
57145e5710bSMark Peek     struct group *res;
57245e5710bSMark Peek 
57345e5710bSMark Peek     errno = 0;
57445e5710bSMark Peek     while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
57545e5710bSMark Peek 	handle_pending_signals();
57645e5710bSMark Peek 	errno = 0;
57745e5710bSMark Peek     }
57845e5710bSMark Peek     return res;
57945e5710bSMark Peek }
58045e5710bSMark Peek 
58145e5710bSMark Peek struct passwd *
58245e5710bSMark Peek xgetpwnam(const char *name)
58345e5710bSMark Peek {
58445e5710bSMark Peek     struct passwd *res;
58545e5710bSMark Peek 
58645e5710bSMark Peek     errno = 0;
58745e5710bSMark Peek     while ((res = getpwnam(name)) == NULL && errno == EINTR) {
58845e5710bSMark Peek 	handle_pending_signals();
58945e5710bSMark Peek 	errno = 0;
59045e5710bSMark Peek     }
59145e5710bSMark Peek     return res;
59245e5710bSMark Peek }
59345e5710bSMark Peek 
59445e5710bSMark Peek struct passwd *
59545e5710bSMark Peek xgetpwuid(uid_t xuid)
59645e5710bSMark Peek {
59745e5710bSMark Peek     struct passwd *res;
59845e5710bSMark Peek 
59945e5710bSMark Peek     errno = 0;
60045e5710bSMark Peek     while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
60145e5710bSMark Peek 	handle_pending_signals();
60245e5710bSMark Peek 	errno = 0;
60345e5710bSMark Peek     }
60445e5710bSMark Peek     return res;
60545e5710bSMark Peek }
60645e5710bSMark Peek 
60745e5710bSMark Peek int
60845e5710bSMark Peek xopen(const char *path, int oflag, ...)
60945e5710bSMark Peek {
61045e5710bSMark Peek     int res;
61145e5710bSMark Peek 
61245e5710bSMark Peek     if ((oflag & O_CREAT) == 0) {
61345e5710bSMark Peek 	while ((res = open(path, oflag)) == -1 && errno == EINTR)
61445e5710bSMark Peek 	    handle_pending_signals();
61545e5710bSMark Peek     } else {
61645e5710bSMark Peek 	va_list ap;
61745e5710bSMark Peek 	mode_t mode;
61845e5710bSMark Peek 
61945e5710bSMark Peek 	va_start(ap, oflag);
62045e5710bSMark Peek 	/* "int" should actually be "mode_t after default argument
62145e5710bSMark Peek 	   promotions". "int" is the best guess we have, "mode_t" used to be
62245e5710bSMark Peek 	   "unsigned short", which we obviously can't use. */
62345e5710bSMark Peek 	mode = va_arg(ap, int);
62445e5710bSMark Peek 	va_end(ap);
62545e5710bSMark Peek 	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
62645e5710bSMark Peek 	    handle_pending_signals();
62745e5710bSMark Peek     }
62845e5710bSMark Peek     return res;
62945e5710bSMark Peek }
63045e5710bSMark Peek 
63145e5710bSMark Peek ssize_t
63245e5710bSMark Peek xread(int fildes, void *buf, size_t nbyte)
63345e5710bSMark Peek {
63445e5710bSMark Peek     ssize_t res;
63545e5710bSMark Peek 
63645e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
63745e5710bSMark Peek        that didn't interrupt any system call. */
63845e5710bSMark Peek     do
63945e5710bSMark Peek       handle_pending_signals();
64045e5710bSMark Peek     while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
64145e5710bSMark Peek     return res;
64245e5710bSMark Peek }
64345e5710bSMark Peek 
64445e5710bSMark Peek #ifdef POSIX
64545e5710bSMark Peek int
64645e5710bSMark Peek xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
64745e5710bSMark Peek {
64845e5710bSMark Peek     int res;
64945e5710bSMark Peek 
65045e5710bSMark Peek     while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
65145e5710bSMark Peek 	   errno == EINTR)
65245e5710bSMark Peek 	handle_pending_signals();
65345e5710bSMark Peek     return res;
65445e5710bSMark Peek }
65545e5710bSMark Peek #endif
65645e5710bSMark Peek 
65745e5710bSMark Peek ssize_t
65845e5710bSMark Peek xwrite(int fildes, const void *buf, size_t nbyte)
65945e5710bSMark Peek {
66045e5710bSMark Peek     ssize_t res;
66145e5710bSMark Peek 
66245e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
66345e5710bSMark Peek        that didn't interrupt any system call. */
66445e5710bSMark Peek     do
66545e5710bSMark Peek       handle_pending_signals();
66645e5710bSMark Peek     while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
66745e5710bSMark Peek     return res;
66845e5710bSMark Peek }
669