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