xref: /freebsd/contrib/tcsh/sh.misc.c (revision 45e5710bbb3676c9d945e9df78019b2c58930a59)
145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.45 2006/10/14 17:57:21 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 
3545e5710bSMark Peek RCSID("$tcsh: sh.misc.c,v 3.45 2006/10/14 17:57:21 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 
63c80476e4SDavid E. O'Brien char *
6445e5710bSMark Peek strnsave(const char *s, size_t len)
65c80476e4SDavid E. O'Brien {
6645e5710bSMark Peek     char *r;
6745e5710bSMark Peek 
6845e5710bSMark Peek     r = xmalloc(len + 1);
6945e5710bSMark Peek     memcpy(r, s, len);
7045e5710bSMark Peek     r[len] = '\0';
7145e5710bSMark Peek     return r;
7245e5710bSMark Peek }
7345e5710bSMark Peek 
7445e5710bSMark Peek char   *
7545e5710bSMark Peek strsave(const char *s)
7645e5710bSMark Peek {
7745e5710bSMark Peek     char   *r;
7845e5710bSMark Peek     size_t size;
79c80476e4SDavid E. O'Brien 
80c80476e4SDavid E. O'Brien     if (s == NULL)
8123338178SMark Peek 	s = "";
8245e5710bSMark Peek     size = strlen(s) + 1;
8345e5710bSMark Peek     r = xmalloc(size);
8445e5710bSMark Peek     memcpy(r, s, size);
8523338178SMark Peek     return (r);
86c80476e4SDavid E. O'Brien }
87c80476e4SDavid E. O'Brien 
88c80476e4SDavid E. O'Brien static Char  **
8945e5710bSMark Peek blkend(Char **up)
90c80476e4SDavid E. O'Brien {
91c80476e4SDavid E. O'Brien 
92c80476e4SDavid E. O'Brien     while (*up)
93c80476e4SDavid E. O'Brien 	up++;
94c80476e4SDavid E. O'Brien     return (up);
95c80476e4SDavid E. O'Brien }
96c80476e4SDavid E. O'Brien 
97c80476e4SDavid E. O'Brien 
98c80476e4SDavid E. O'Brien void
9945e5710bSMark Peek blkpr(Char *const *av)
100c80476e4SDavid E. O'Brien {
101c80476e4SDavid E. O'Brien 
102c80476e4SDavid E. O'Brien     for (; *av; av++) {
103c80476e4SDavid E. O'Brien 	xprintf("%S", *av);
104c80476e4SDavid E. O'Brien 	if (av[1])
105c80476e4SDavid E. O'Brien 	    xprintf(" ");
106c80476e4SDavid E. O'Brien     }
107c80476e4SDavid E. O'Brien }
108c80476e4SDavid E. O'Brien 
10945e5710bSMark Peek Char *
11045e5710bSMark Peek blkexpand(Char *const *av)
111c80476e4SDavid E. O'Brien {
11245e5710bSMark Peek     struct Strbuf buf = Strbuf_INIT;
11345e5710bSMark Peek 
114c80476e4SDavid E. O'Brien     for (; *av; av++) {
11545e5710bSMark Peek 	Strbuf_append(&buf, *av);
116c80476e4SDavid E. O'Brien 	if (av[1])
11745e5710bSMark Peek 	    Strbuf_append1(&buf, ' ');
118c80476e4SDavid E. O'Brien     }
11945e5710bSMark Peek     return Strbuf_finish(&buf);
120c80476e4SDavid E. O'Brien }
121c80476e4SDavid E. O'Brien 
122c80476e4SDavid E. O'Brien int
12345e5710bSMark Peek blklen(Char **av)
124c80476e4SDavid E. O'Brien {
12523338178SMark Peek     int i = 0;
126c80476e4SDavid E. O'Brien 
127c80476e4SDavid E. O'Brien     while (*av++)
128c80476e4SDavid E. O'Brien 	i++;
129c80476e4SDavid E. O'Brien     return (i);
130c80476e4SDavid E. O'Brien }
131c80476e4SDavid E. O'Brien 
132c80476e4SDavid E. O'Brien Char  **
13345e5710bSMark Peek blkcpy(Char **oav, Char **bv)
134c80476e4SDavid E. O'Brien {
13523338178SMark Peek     Char **av = oav;
136c80476e4SDavid E. O'Brien 
137c80476e4SDavid E. O'Brien     while ((*av++ = *bv++) != NULL)
138c80476e4SDavid E. O'Brien 	continue;
139c80476e4SDavid E. O'Brien     return (oav);
140c80476e4SDavid E. O'Brien }
141c80476e4SDavid E. O'Brien 
142c80476e4SDavid E. O'Brien static Char  **
14345e5710bSMark Peek blkcat(Char **up, Char **vp)
144c80476e4SDavid E. O'Brien {
145c80476e4SDavid E. O'Brien 
146c80476e4SDavid E. O'Brien     (void) blkcpy(blkend(up), vp);
147c80476e4SDavid E. O'Brien     return (up);
148c80476e4SDavid E. O'Brien }
149c80476e4SDavid E. O'Brien 
150c80476e4SDavid E. O'Brien void
15145e5710bSMark Peek blkfree(Char **av0)
152c80476e4SDavid E. O'Brien {
15323338178SMark Peek     Char **av = av0;
154c80476e4SDavid E. O'Brien 
155c80476e4SDavid E. O'Brien     if (!av0)
156c80476e4SDavid E. O'Brien 	return;
157c80476e4SDavid E. O'Brien     for (; *av; av++)
15845e5710bSMark Peek 	xfree(*av);
15945e5710bSMark Peek     xfree(av0);
16045e5710bSMark Peek }
16145e5710bSMark Peek 
16245e5710bSMark Peek void
16345e5710bSMark Peek blk_cleanup(void *ptr)
16445e5710bSMark Peek {
16545e5710bSMark Peek     blkfree(ptr);
16645e5710bSMark Peek }
16745e5710bSMark Peek 
16845e5710bSMark Peek void
16945e5710bSMark Peek blk_indirect_cleanup(void *xptr)
17045e5710bSMark Peek {
17145e5710bSMark Peek     Char ***ptr;
17245e5710bSMark Peek 
17345e5710bSMark Peek     ptr = xptr;
17445e5710bSMark Peek     blkfree(*ptr);
17545e5710bSMark Peek     xfree(ptr);
176c80476e4SDavid E. O'Brien }
177c80476e4SDavid E. O'Brien 
178c80476e4SDavid E. O'Brien Char  **
17945e5710bSMark Peek saveblk(Char **v)
180c80476e4SDavid E. O'Brien {
18145e5710bSMark Peek     Char **newv, **onewv;
18245e5710bSMark Peek 
18345e5710bSMark Peek     if (v == NULL)
18445e5710bSMark Peek 	return NULL;
18545e5710bSMark Peek 
18645e5710bSMark Peek     onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
187c80476e4SDavid E. O'Brien 
188c80476e4SDavid E. O'Brien     while (*v)
189c80476e4SDavid E. O'Brien 	*newv++ = Strsave(*v++);
190c80476e4SDavid E. O'Brien     return (onewv);
191c80476e4SDavid E. O'Brien }
192c80476e4SDavid E. O'Brien 
19323338178SMark Peek #ifndef HAVE_STRSTR
194c80476e4SDavid E. O'Brien char   *
19545e5710bSMark Peek strstr(const char *s, const char *t)
196c80476e4SDavid E. O'Brien {
197c80476e4SDavid E. O'Brien     do {
19823338178SMark Peek 	const char *ss = s;
19923338178SMark Peek 	const char *tt = t;
200c80476e4SDavid E. O'Brien 
201c80476e4SDavid E. O'Brien 	do
202c80476e4SDavid E. O'Brien 	    if (*tt == '\0')
20345e5710bSMark Peek 		return (s);
204c80476e4SDavid E. O'Brien 	while (*ss++ == *tt++);
205c80476e4SDavid E. O'Brien     } while (*s++ != '\0');
206c80476e4SDavid E. O'Brien     return (NULL);
207c80476e4SDavid E. O'Brien }
20823338178SMark Peek #endif /* !HAVE_STRSTR */
209c80476e4SDavid E. O'Brien 
210c80476e4SDavid E. O'Brien char   *
21145e5710bSMark Peek strspl(const char *cp, const char *dp)
212c80476e4SDavid E. O'Brien {
213c80476e4SDavid E. O'Brien     char   *ep;
21423338178SMark Peek     size_t cl, dl;
215c80476e4SDavid E. O'Brien 
216c80476e4SDavid E. O'Brien     if (!cp)
217c80476e4SDavid E. O'Brien 	cp = "";
218c80476e4SDavid E. O'Brien     if (!dp)
219c80476e4SDavid E. O'Brien 	dp = "";
22023338178SMark Peek     cl = strlen(cp);
22123338178SMark Peek     dl = strlen(dp);
22245e5710bSMark Peek     ep = xmalloc((cl + dl + 1) * sizeof(char));
22323338178SMark Peek     memcpy(ep, cp, cl);
22423338178SMark Peek     memcpy(ep + cl, dp, dl + 1);
225c80476e4SDavid E. O'Brien     return (ep);
226c80476e4SDavid E. O'Brien }
227c80476e4SDavid E. O'Brien 
228c80476e4SDavid E. O'Brien Char  **
22945e5710bSMark Peek blkspl(Char **up, Char **vp)
230c80476e4SDavid E. O'Brien {
23145e5710bSMark Peek     Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
232c80476e4SDavid E. O'Brien 
233c80476e4SDavid E. O'Brien     (void) blkcpy(wp, up);
234c80476e4SDavid E. O'Brien     return (blkcat(wp, vp));
235c80476e4SDavid E. O'Brien }
236c80476e4SDavid E. O'Brien 
237c80476e4SDavid E. O'Brien Char
23845e5710bSMark Peek lastchr(Char *cp)
239c80476e4SDavid E. O'Brien {
240c80476e4SDavid E. O'Brien 
241c80476e4SDavid E. O'Brien     if (!cp)
242c80476e4SDavid E. O'Brien 	return (0);
243c80476e4SDavid E. O'Brien     if (!*cp)
244c80476e4SDavid E. O'Brien 	return (0);
245c80476e4SDavid E. O'Brien     while (cp[1])
246c80476e4SDavid E. O'Brien 	cp++;
247c80476e4SDavid E. O'Brien     return (*cp);
248c80476e4SDavid E. O'Brien }
249c80476e4SDavid E. O'Brien 
250c80476e4SDavid E. O'Brien /*
251c80476e4SDavid E. O'Brien  * This routine is called after an error to close up
252c80476e4SDavid E. O'Brien  * any units which may have been left open accidentally.
253c80476e4SDavid E. O'Brien  */
254c80476e4SDavid E. O'Brien void
25545e5710bSMark Peek closem(void)
256c80476e4SDavid E. O'Brien {
25745e5710bSMark Peek     int f, num_files;
258c80476e4SDavid E. O'Brien 
259b2d5d167SMark Peek #ifdef NLS_BUGS
260b2d5d167SMark Peek #ifdef NLS_CATALOGS
26123338178SMark Peek     nlsclose();
262b2d5d167SMark Peek #endif /* NLS_CATALOGS */
263b2d5d167SMark Peek #endif /* NLS_BUGS */
264c80476e4SDavid E. O'Brien #ifdef YPBUGS
265c80476e4SDavid E. O'Brien     /* suggested by Justin Bur; thanks to Karl Kleinpaste */
266c80476e4SDavid E. O'Brien     fix_yp_bugs();
267c80476e4SDavid E. O'Brien #endif /* YPBUGS */
26845e5710bSMark Peek     num_files = NOFILE;
26945e5710bSMark Peek     for (f = 0; f < num_files; f++)
270c80476e4SDavid E. O'Brien 	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
271c80476e4SDavid E. O'Brien 	    f != FSHTTY
272c80476e4SDavid E. O'Brien #ifdef MALLOC_TRACE
273c80476e4SDavid E. O'Brien 	    && f != 25
274c80476e4SDavid E. O'Brien #endif /* MALLOC_TRACE */
275c80476e4SDavid E. O'Brien 	    )
276c80476e4SDavid E. O'Brien 	  {
27745e5710bSMark Peek 	    xclose(f);
278c80476e4SDavid E. O'Brien #ifdef NISPLUS
279c80476e4SDavid E. O'Brien 	    if(f < 3)
28045e5710bSMark Peek 		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
281c80476e4SDavid E. O'Brien #endif /* NISPLUS */
282c80476e4SDavid E. O'Brien 	  }
283b2d5d167SMark Peek #ifdef NLS_BUGS
284b2d5d167SMark Peek #ifdef NLS_CATALOGS
285b2d5d167SMark Peek     nlsinit();
286b2d5d167SMark Peek #endif /* NLS_CATALOGS */
287b2d5d167SMark Peek #endif /* NLS_BUGS */
288c80476e4SDavid E. O'Brien }
289c80476e4SDavid E. O'Brien 
290c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC
291c80476e4SDavid E. O'Brien /*
292c80476e4SDavid E. O'Brien  * Close files before executing a file.
293c80476e4SDavid E. O'Brien  * We could be MUCH more intelligent, since (on a version 7 system)
294c80476e4SDavid E. O'Brien  * we need only close files here during a source, the other
295c80476e4SDavid E. O'Brien  * shell fd's being in units 16-19 which are closed automatically!
296c80476e4SDavid E. O'Brien  */
297c80476e4SDavid E. O'Brien void
29845e5710bSMark Peek closech(void)
299c80476e4SDavid E. O'Brien {
30045e5710bSMark Peek     int f, num_files;
301c80476e4SDavid E. O'Brien 
302c80476e4SDavid E. O'Brien     if (didcch)
303c80476e4SDavid E. O'Brien 	return;
304c80476e4SDavid E. O'Brien     didcch = 1;
305c80476e4SDavid E. O'Brien     SHIN = 0;
306c80476e4SDavid E. O'Brien     SHOUT = 1;
307c80476e4SDavid E. O'Brien     SHDIAG = 2;
308c80476e4SDavid E. O'Brien     OLDSTD = 0;
309c80476e4SDavid E. O'Brien     isoutatty = isatty(SHOUT);
310c80476e4SDavid E. O'Brien     isdiagatty = isatty(SHDIAG);
31145e5710bSMark Peek     num_files = NOFILE;
31245e5710bSMark Peek     for (f = 3; f < num_files; f++)
31345e5710bSMark Peek 	xclose(f);
314c80476e4SDavid E. O'Brien }
315c80476e4SDavid E. O'Brien 
316c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */
317c80476e4SDavid E. O'Brien 
318c80476e4SDavid E. O'Brien void
31945e5710bSMark Peek donefds(void)
320c80476e4SDavid E. O'Brien {
321c80476e4SDavid E. O'Brien 
32245e5710bSMark Peek     xclose(0);
32345e5710bSMark Peek     xclose(1);
32445e5710bSMark Peek     xclose(2);
325c80476e4SDavid E. O'Brien     didfds = 0;
326c80476e4SDavid E. O'Brien #ifdef NISPLUS
327c80476e4SDavid E. O'Brien     {
32845e5710bSMark Peek 	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
32923338178SMark Peek 	(void)dcopy(fd, 1);
33023338178SMark Peek 	(void)dcopy(fd, 2);
33123338178SMark Peek 	(void)dmove(fd, 0);
332c80476e4SDavid E. O'Brien     }
333c80476e4SDavid E. O'Brien #endif /*NISPLUS*/
334c80476e4SDavid E. O'Brien }
335c80476e4SDavid E. O'Brien 
336c80476e4SDavid E. O'Brien /*
337c80476e4SDavid E. O'Brien  * Move descriptor i to j.
338c80476e4SDavid E. O'Brien  * If j is -1 then we just want to get i to a safe place,
33923338178SMark Peek  * i.e. to a unit > FSAFE.  This also happens in dcopy.
340c80476e4SDavid E. O'Brien  */
341c80476e4SDavid E. O'Brien int
34245e5710bSMark Peek dmove(int i, int j)
343c80476e4SDavid E. O'Brien {
344c80476e4SDavid E. O'Brien 
345c80476e4SDavid E. O'Brien     if (i == j || i < 0)
346c80476e4SDavid E. O'Brien 	return (i);
34723338178SMark Peek #ifdef HAVE_DUP2
348c80476e4SDavid E. O'Brien     if (j >= 0) {
34945e5710bSMark Peek 	(void) xdup2(i, j);
350c80476e4SDavid E. O'Brien 	if (j != i)
35145e5710bSMark Peek 	    xclose(i);
352c80476e4SDavid E. O'Brien 	return (j);
353c80476e4SDavid E. O'Brien     }
354c80476e4SDavid E. O'Brien #endif
355c80476e4SDavid E. O'Brien     j = dcopy(i, j);
356c80476e4SDavid E. O'Brien     if (j != i)
35745e5710bSMark Peek 	xclose(i);
358c80476e4SDavid E. O'Brien     return (j);
359c80476e4SDavid E. O'Brien }
360c80476e4SDavid E. O'Brien 
361c80476e4SDavid E. O'Brien int
36245e5710bSMark Peek dcopy(int i, int j)
363c80476e4SDavid E. O'Brien {
364c80476e4SDavid E. O'Brien 
36523338178SMark Peek     if (i == j || i < 0 || (j < 0 && i > FSAFE))
366c80476e4SDavid E. O'Brien 	return (i);
367c80476e4SDavid E. O'Brien     if (j >= 0) {
36823338178SMark Peek #ifdef HAVE_DUP2
36945e5710bSMark Peek 	(void) xdup2(i, j);
370c80476e4SDavid E. O'Brien 	return (j);
371c80476e4SDavid E. O'Brien #else
37245e5710bSMark Peek 	xclose(j);
373c80476e4SDavid E. O'Brien #endif
374c80476e4SDavid E. O'Brien     }
375c80476e4SDavid E. O'Brien     return (renum(i, j));
376c80476e4SDavid E. O'Brien }
377c80476e4SDavid E. O'Brien 
378c80476e4SDavid E. O'Brien static int
37945e5710bSMark Peek renum(int i, int j)
380c80476e4SDavid E. O'Brien {
38123338178SMark Peek     int k = dup(i);
382c80476e4SDavid E. O'Brien 
383c80476e4SDavid E. O'Brien     if (k < 0)
384c80476e4SDavid E. O'Brien 	return (-1);
38523338178SMark Peek     if (j == -1 && k > FSAFE)
386c80476e4SDavid E. O'Brien 	return (k);
387c80476e4SDavid E. O'Brien     if (k != j) {
388c80476e4SDavid E. O'Brien 	j = renum(k, j);
38945e5710bSMark Peek 	xclose(k);
390c80476e4SDavid E. O'Brien 	return (j);
391c80476e4SDavid E. O'Brien     }
392c80476e4SDavid E. O'Brien     return (k);
393c80476e4SDavid E. O'Brien }
394c80476e4SDavid E. O'Brien 
395c80476e4SDavid E. O'Brien /*
396c80476e4SDavid E. O'Brien  * Left shift a command argument list, discarding
397c80476e4SDavid E. O'Brien  * the first c arguments.  Used in "shift" commands
398c80476e4SDavid E. O'Brien  * as well as by commands like "repeat".
399c80476e4SDavid E. O'Brien  */
400c80476e4SDavid E. O'Brien void
40145e5710bSMark Peek lshift(Char **v, int c)
402c80476e4SDavid E. O'Brien {
40323338178SMark Peek     Char **u;
404c80476e4SDavid E. O'Brien 
405c80476e4SDavid E. O'Brien     for (u = v; *u && --c >= 0; u++)
40645e5710bSMark Peek 	xfree(*u);
407c80476e4SDavid E. O'Brien     (void) blkcpy(v, u);
408c80476e4SDavid E. O'Brien }
409c80476e4SDavid E. O'Brien 
410c80476e4SDavid E. O'Brien int
41145e5710bSMark Peek number(Char *cp)
412c80476e4SDavid E. O'Brien {
413c80476e4SDavid E. O'Brien     if (!cp)
414c80476e4SDavid E. O'Brien 	return (0);
415c80476e4SDavid E. O'Brien     if (*cp == '-') {
416c80476e4SDavid E. O'Brien 	cp++;
417c80476e4SDavid E. O'Brien 	if (!Isdigit(*cp))
418c80476e4SDavid E. O'Brien 	    return (0);
419c80476e4SDavid E. O'Brien 	cp++;
420c80476e4SDavid E. O'Brien     }
421c80476e4SDavid E. O'Brien     while (*cp && Isdigit(*cp))
422c80476e4SDavid E. O'Brien 	cp++;
423c80476e4SDavid E. O'Brien     return (*cp == 0);
424c80476e4SDavid E. O'Brien }
425c80476e4SDavid E. O'Brien 
426c80476e4SDavid E. O'Brien Char  **
42745e5710bSMark Peek copyblk(Char **v)
428c80476e4SDavid E. O'Brien {
42945e5710bSMark Peek     Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
430c80476e4SDavid E. O'Brien 
431c80476e4SDavid E. O'Brien     return (blkcpy(nv, v));
432c80476e4SDavid E. O'Brien }
433c80476e4SDavid E. O'Brien 
434c80476e4SDavid E. O'Brien char   *
43545e5710bSMark Peek strend(const char *cp)
436c80476e4SDavid E. O'Brien {
437c80476e4SDavid E. O'Brien     if (!cp)
43845e5710bSMark Peek 	return ((char *)(intptr_t)cp);
439c80476e4SDavid E. O'Brien     while (*cp)
440c80476e4SDavid E. O'Brien 	cp++;
44145e5710bSMark Peek     return ((char *)(intptr_t)cp);
442c80476e4SDavid E. O'Brien }
443c80476e4SDavid E. O'Brien 
444c80476e4SDavid E. O'Brien Char   *
44545e5710bSMark Peek strip(Char *cp)
446c80476e4SDavid E. O'Brien {
44723338178SMark Peek     Char *dp = cp;
448c80476e4SDavid E. O'Brien 
449c80476e4SDavid E. O'Brien     if (!cp)
450c80476e4SDavid E. O'Brien 	return (cp);
451c80476e4SDavid E. O'Brien     while ((*dp++ &= TRIM) != '\0')
452c80476e4SDavid E. O'Brien 	continue;
453c80476e4SDavid E. O'Brien     return (cp);
454c80476e4SDavid E. O'Brien }
455c80476e4SDavid E. O'Brien 
456c80476e4SDavid E. O'Brien Char   *
45745e5710bSMark Peek quote(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);
463c80476e4SDavid E. O'Brien     while (*dp != '\0')
464c80476e4SDavid E. O'Brien 	*dp++ |= QUOTE;
465c80476e4SDavid E. O'Brien     return (cp);
466c80476e4SDavid E. O'Brien }
467c80476e4SDavid E. O'Brien 
46845e5710bSMark Peek const Char *
46945e5710bSMark Peek quote_meta(struct Strbuf *buf, const Char *s)
470c80476e4SDavid E. O'Brien {
47145e5710bSMark Peek     buf->len = 0;
472c80476e4SDavid E. O'Brien     while (*s != '\0') {
473c80476e4SDavid E. O'Brien 	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
47445e5710bSMark Peek 	    Strbuf_append1(buf, '\\');
47545e5710bSMark Peek 	Strbuf_append1(buf, *s++);
476c80476e4SDavid E. O'Brien     }
47745e5710bSMark Peek     Strbuf_terminate(buf);
47845e5710bSMark Peek     return buf->s;
479c80476e4SDavid E. O'Brien }
480c80476e4SDavid E. O'Brien 
481c80476e4SDavid E. O'Brien void
48245e5710bSMark Peek udvar(Char *name)
483c80476e4SDavid E. O'Brien {
484c80476e4SDavid E. O'Brien     setname(short2str(name));
485c80476e4SDavid E. O'Brien     stderror(ERR_NAME | ERR_UNDVAR);
486c80476e4SDavid E. O'Brien }
487c80476e4SDavid E. O'Brien 
488c80476e4SDavid E. O'Brien int
48945e5710bSMark Peek prefix(const Char *sub, const Char *str)
490c80476e4SDavid E. O'Brien {
491c80476e4SDavid E. O'Brien 
492c80476e4SDavid E. O'Brien     for (;;) {
493c80476e4SDavid E. O'Brien 	if (*sub == 0)
494c80476e4SDavid E. O'Brien 	    return (1);
495c80476e4SDavid E. O'Brien 	if (*str == 0)
496c80476e4SDavid E. O'Brien 	    return (0);
497c80476e4SDavid E. O'Brien 	if ((*sub++ & TRIM) != (*str++ & TRIM))
498c80476e4SDavid E. O'Brien 	    return (0);
499c80476e4SDavid E. O'Brien     }
500c80476e4SDavid E. O'Brien }
50145e5710bSMark Peek #ifndef WINNT_NATIVE
50245e5710bSMark Peek char *
50345e5710bSMark Peek areadlink(const char *path)
50445e5710bSMark Peek {
50545e5710bSMark Peek     char *buf;
50645e5710bSMark Peek     size_t size;
50745e5710bSMark Peek     ssize_t res;
50845e5710bSMark Peek 
50945e5710bSMark Peek     size = MAXPATHLEN + 1;
51045e5710bSMark Peek     buf = xmalloc(size);
51145e5710bSMark Peek     while ((size_t)(res = readlink(path, buf, size)) == size) {
51245e5710bSMark Peek 	size *= 2;
51345e5710bSMark Peek 	buf = xrealloc(buf, size);
51445e5710bSMark Peek     }
51545e5710bSMark Peek     if (res == -1) {
51645e5710bSMark Peek 	int err;
51745e5710bSMark Peek 
51845e5710bSMark Peek 	err = errno;
51945e5710bSMark Peek 	xfree(buf);
52045e5710bSMark Peek 	errno = err;
52145e5710bSMark Peek 	return NULL;
52245e5710bSMark Peek     }
52345e5710bSMark Peek     buf[res] = '\0';
52445e5710bSMark Peek     return xrealloc(buf, res + 1);
52545e5710bSMark Peek }
52645e5710bSMark Peek #endif /*!WINNT_NATIVE*/
52745e5710bSMark Peek 
52845e5710bSMark Peek void
52945e5710bSMark Peek xclose(int fildes)
53045e5710bSMark Peek {
53145e5710bSMark Peek     if (fildes < 0)
53245e5710bSMark Peek 	return;
53345e5710bSMark Peek     while (close(fildes) == -1 && errno == EINTR)
53445e5710bSMark Peek 	handle_pending_signals();
53545e5710bSMark Peek }
53645e5710bSMark Peek 
53745e5710bSMark Peek void
53845e5710bSMark Peek xclosedir(DIR *dirp)
53945e5710bSMark Peek {
54045e5710bSMark Peek     while (closedir(dirp) == -1 && errno == EINTR)
54145e5710bSMark Peek 	handle_pending_signals();
54245e5710bSMark Peek }
54345e5710bSMark Peek 
54445e5710bSMark Peek int
54545e5710bSMark Peek xcreat(const char *path, mode_t mode)
54645e5710bSMark Peek {
54745e5710bSMark Peek     int res;
54845e5710bSMark Peek 
54945e5710bSMark Peek     while ((res = creat(path, mode)) == -1 && errno == EINTR)
55045e5710bSMark Peek 	handle_pending_signals();
55145e5710bSMark Peek     return res;
55245e5710bSMark Peek }
55345e5710bSMark Peek 
55445e5710bSMark Peek #ifdef HAVE_DUP2
55545e5710bSMark Peek static int
55645e5710bSMark Peek xdup2(int fildes, int fildes2)
55745e5710bSMark Peek {
55845e5710bSMark Peek     int res;
55945e5710bSMark Peek 
56045e5710bSMark Peek     while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
56145e5710bSMark Peek 	handle_pending_signals();
56245e5710bSMark Peek     return res;
56345e5710bSMark Peek }
56445e5710bSMark Peek #endif
56545e5710bSMark Peek 
56645e5710bSMark Peek struct group *
56745e5710bSMark Peek xgetgrgid(gid_t xgid)
56845e5710bSMark Peek {
56945e5710bSMark Peek     struct group *res;
57045e5710bSMark Peek 
57145e5710bSMark Peek     errno = 0;
57245e5710bSMark Peek     while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
57345e5710bSMark Peek 	handle_pending_signals();
57445e5710bSMark Peek 	errno = 0;
57545e5710bSMark Peek     }
57645e5710bSMark Peek     return res;
57745e5710bSMark Peek }
57845e5710bSMark Peek 
57945e5710bSMark Peek struct passwd *
58045e5710bSMark Peek xgetpwnam(const char *name)
58145e5710bSMark Peek {
58245e5710bSMark Peek     struct passwd *res;
58345e5710bSMark Peek 
58445e5710bSMark Peek     errno = 0;
58545e5710bSMark Peek     while ((res = getpwnam(name)) == NULL && errno == EINTR) {
58645e5710bSMark Peek 	handle_pending_signals();
58745e5710bSMark Peek 	errno = 0;
58845e5710bSMark Peek     }
58945e5710bSMark Peek     return res;
59045e5710bSMark Peek }
59145e5710bSMark Peek 
59245e5710bSMark Peek struct passwd *
59345e5710bSMark Peek xgetpwuid(uid_t xuid)
59445e5710bSMark Peek {
59545e5710bSMark Peek     struct passwd *res;
59645e5710bSMark Peek 
59745e5710bSMark Peek     errno = 0;
59845e5710bSMark Peek     while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
59945e5710bSMark Peek 	handle_pending_signals();
60045e5710bSMark Peek 	errno = 0;
60145e5710bSMark Peek     }
60245e5710bSMark Peek     return res;
60345e5710bSMark Peek }
60445e5710bSMark Peek 
60545e5710bSMark Peek int
60645e5710bSMark Peek xopen(const char *path, int oflag, ...)
60745e5710bSMark Peek {
60845e5710bSMark Peek     int res;
60945e5710bSMark Peek 
61045e5710bSMark Peek     if ((oflag & O_CREAT) == 0) {
61145e5710bSMark Peek 	while ((res = open(path, oflag)) == -1 && errno == EINTR)
61245e5710bSMark Peek 	    handle_pending_signals();
61345e5710bSMark Peek     } else {
61445e5710bSMark Peek 	va_list ap;
61545e5710bSMark Peek 	mode_t mode;
61645e5710bSMark Peek 
61745e5710bSMark Peek 	va_start(ap, oflag);
61845e5710bSMark Peek 	/* "int" should actually be "mode_t after default argument
61945e5710bSMark Peek 	   promotions". "int" is the best guess we have, "mode_t" used to be
62045e5710bSMark Peek 	   "unsigned short", which we obviously can't use. */
62145e5710bSMark Peek 	mode = va_arg(ap, int);
62245e5710bSMark Peek 	va_end(ap);
62345e5710bSMark Peek 	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
62445e5710bSMark Peek 	    handle_pending_signals();
62545e5710bSMark Peek     }
62645e5710bSMark Peek     return res;
62745e5710bSMark Peek }
62845e5710bSMark Peek 
62945e5710bSMark Peek ssize_t
63045e5710bSMark Peek xread(int fildes, void *buf, size_t nbyte)
63145e5710bSMark Peek {
63245e5710bSMark Peek     ssize_t res;
63345e5710bSMark Peek 
63445e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
63545e5710bSMark Peek        that didn't interrupt any system call. */
63645e5710bSMark Peek     do
63745e5710bSMark Peek       handle_pending_signals();
63845e5710bSMark Peek     while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
63945e5710bSMark Peek     return res;
64045e5710bSMark Peek }
64145e5710bSMark Peek 
64245e5710bSMark Peek #ifdef POSIX
64345e5710bSMark Peek int
64445e5710bSMark Peek xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
64545e5710bSMark Peek {
64645e5710bSMark Peek     int res;
64745e5710bSMark Peek 
64845e5710bSMark Peek     while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
64945e5710bSMark Peek 	   errno == EINTR)
65045e5710bSMark Peek 	handle_pending_signals();
65145e5710bSMark Peek     return res;
65245e5710bSMark Peek }
65345e5710bSMark Peek #endif
65445e5710bSMark Peek 
65545e5710bSMark Peek ssize_t
65645e5710bSMark Peek xwrite(int fildes, const void *buf, size_t nbyte)
65745e5710bSMark Peek {
65845e5710bSMark Peek     ssize_t res;
65945e5710bSMark Peek 
66045e5710bSMark Peek     /* This is where we will be blocked most of the time, so handle signals
66145e5710bSMark Peek        that didn't interrupt any system call. */
66245e5710bSMark Peek     do
66345e5710bSMark Peek       handle_pending_signals();
66445e5710bSMark Peek     while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
66545e5710bSMark Peek     return res;
66645e5710bSMark Peek }
667