BUS_CONFIG_INTR takes 2 devices now: parent and child
[dragonfly.git] / contrib / tcsh-6 / sh.misc.c
blob7c4094f19504f8aa7bef434d96aee33c9df294d1
1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.45 2006/10/14 17:57:21 christos Exp $ */
2 /*
3 * sh.misc.c: Miscelaneous functions
4 */
5 /*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 #include "sh.h"
35 RCSID("$tcsh: sh.misc.c,v 3.45 2006/10/14 17:57:21 christos Exp $")
37 static int renum (int, int);
38 static Char **blkend (Char **);
39 static Char **blkcat (Char **, Char **);
40 static int xdup2 (int, int);
43 * C Shell
46 int
47 any(const char *s, Char c)
49 if (!s)
50 return (0); /* Check for nil pointer */
51 while (*s)
52 if ((Char)*s++ == c)
53 return (1);
54 return (0);
57 void
58 setzero(void *p, size_t size)
60 memset(p, 0, size);
63 char *
64 strnsave(const char *s, size_t len)
66 char *r;
68 r = xmalloc(len + 1);
69 memcpy(r, s, len);
70 r[len] = '\0';
71 return r;
74 char *
75 strsave(const char *s)
77 char *r;
78 size_t size;
80 if (s == NULL)
81 s = "";
82 size = strlen(s) + 1;
83 r = xmalloc(size);
84 memcpy(r, s, size);
85 return (r);
88 static Char **
89 blkend(Char **up)
92 while (*up)
93 up++;
94 return (up);
98 void
99 blkpr(Char *const *av)
102 for (; *av; av++) {
103 xprintf("%S", *av);
104 if (av[1])
105 xprintf(" ");
109 Char *
110 blkexpand(Char *const *av)
112 struct Strbuf buf = Strbuf_INIT;
114 for (; *av; av++) {
115 Strbuf_append(&buf, *av);
116 if (av[1])
117 Strbuf_append1(&buf, ' ');
119 return Strbuf_finish(&buf);
123 blklen(Char **av)
125 int i = 0;
127 while (*av++)
128 i++;
129 return (i);
132 Char **
133 blkcpy(Char **oav, Char **bv)
135 Char **av = oav;
137 while ((*av++ = *bv++) != NULL)
138 continue;
139 return (oav);
142 static Char **
143 blkcat(Char **up, Char **vp)
146 (void) blkcpy(blkend(up), vp);
147 return (up);
150 void
151 blkfree(Char **av0)
153 Char **av = av0;
155 if (!av0)
156 return;
157 for (; *av; av++)
158 xfree(*av);
159 xfree(av0);
162 void
163 blk_cleanup(void *ptr)
165 blkfree(ptr);
168 void
169 blk_indirect_cleanup(void *xptr)
171 Char ***ptr;
173 ptr = xptr;
174 blkfree(*ptr);
175 xfree(ptr);
178 Char **
179 saveblk(Char **v)
181 Char **newv, **onewv;
183 if (v == NULL)
184 return NULL;
186 onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
188 while (*v)
189 *newv++ = Strsave(*v++);
190 return (onewv);
193 #ifndef HAVE_STRSTR
194 char *
195 strstr(const char *s, const char *t)
197 do {
198 const char *ss = s;
199 const char *tt = t;
202 if (*tt == '\0')
203 return (s);
204 while (*ss++ == *tt++);
205 } while (*s++ != '\0');
206 return (NULL);
208 #endif /* !HAVE_STRSTR */
210 char *
211 strspl(const char *cp, const char *dp)
213 char *ep;
214 size_t cl, dl;
216 if (!cp)
217 cp = "";
218 if (!dp)
219 dp = "";
220 cl = strlen(cp);
221 dl = strlen(dp);
222 ep = xmalloc((cl + dl + 1) * sizeof(char));
223 memcpy(ep, cp, cl);
224 memcpy(ep + cl, dp, dl + 1);
225 return (ep);
228 Char **
229 blkspl(Char **up, Char **vp)
231 Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
233 (void) blkcpy(wp, up);
234 return (blkcat(wp, vp));
237 Char
238 lastchr(Char *cp)
241 if (!cp)
242 return (0);
243 if (!*cp)
244 return (0);
245 while (cp[1])
246 cp++;
247 return (*cp);
251 * This routine is called after an error to close up
252 * any units which may have been left open accidentally.
254 void
255 closem(void)
257 int f, num_files;
259 #ifdef NLS_BUGS
260 #ifdef NLS_CATALOGS
261 nlsclose();
262 #endif /* NLS_CATALOGS */
263 #endif /* NLS_BUGS */
264 #ifdef YPBUGS
265 /* suggested by Justin Bur; thanks to Karl Kleinpaste */
266 fix_yp_bugs();
267 #endif /* YPBUGS */
268 num_files = NOFILE;
269 for (f = 0; f < num_files; f++)
270 if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
271 f != FSHTTY
272 #ifdef MALLOC_TRACE
273 && f != 25
274 #endif /* MALLOC_TRACE */
277 xclose(f);
278 #ifdef NISPLUS
279 if(f < 3)
280 (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
281 #endif /* NISPLUS */
283 #ifdef NLS_BUGS
284 #ifdef NLS_CATALOGS
285 nlsinit();
286 #endif /* NLS_CATALOGS */
287 #endif /* NLS_BUGS */
290 #ifndef CLOSE_ON_EXEC
292 * Close files before executing a file.
293 * We could be MUCH more intelligent, since (on a version 7 system)
294 * we need only close files here during a source, the other
295 * shell fd's being in units 16-19 which are closed automatically!
297 void
298 closech(void)
300 int f, num_files;
302 if (didcch)
303 return;
304 didcch = 1;
305 SHIN = 0;
306 SHOUT = 1;
307 SHDIAG = 2;
308 OLDSTD = 0;
309 isoutatty = isatty(SHOUT);
310 isdiagatty = isatty(SHDIAG);
311 num_files = NOFILE;
312 for (f = 3; f < num_files; f++)
313 xclose(f);
316 #endif /* CLOSE_ON_EXEC */
318 void
319 donefds(void)
322 xclose(0);
323 xclose(1);
324 xclose(2);
325 didfds = 0;
326 #ifdef NISPLUS
328 int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
329 (void)dcopy(fd, 1);
330 (void)dcopy(fd, 2);
331 (void)dmove(fd, 0);
333 #endif /*NISPLUS*/
337 * Move descriptor i to j.
338 * If j is -1 then we just want to get i to a safe place,
339 * i.e. to a unit > FSAFE. This also happens in dcopy.
342 dmove(int i, int j)
345 if (i == j || i < 0)
346 return (i);
347 #ifdef HAVE_DUP2
348 if (j >= 0) {
349 (void) xdup2(i, j);
350 if (j != i)
351 xclose(i);
352 return (j);
354 #endif
355 j = dcopy(i, j);
356 if (j != i)
357 xclose(i);
358 return (j);
362 dcopy(int i, int j)
365 if (i == j || i < 0 || (j < 0 && i > FSAFE))
366 return (i);
367 if (j >= 0) {
368 #ifdef HAVE_DUP2
369 (void) xdup2(i, j);
370 return (j);
371 #else
372 xclose(j);
373 #endif
375 return (renum(i, j));
378 static int
379 renum(int i, int j)
381 int k = dup(i);
383 if (k < 0)
384 return (-1);
385 if (j == -1 && k > FSAFE)
386 return (k);
387 if (k != j) {
388 j = renum(k, j);
389 xclose(k);
390 return (j);
392 return (k);
396 * Left shift a command argument list, discarding
397 * the first c arguments. Used in "shift" commands
398 * as well as by commands like "repeat".
400 void
401 lshift(Char **v, int c)
403 Char **u;
405 for (u = v; *u && --c >= 0; u++)
406 xfree(*u);
407 (void) blkcpy(v, u);
411 number(Char *cp)
413 if (!cp)
414 return (0);
415 if (*cp == '-') {
416 cp++;
417 if (!Isdigit(*cp))
418 return (0);
419 cp++;
421 while (*cp && Isdigit(*cp))
422 cp++;
423 return (*cp == 0);
426 Char **
427 copyblk(Char **v)
429 Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
431 return (blkcpy(nv, v));
434 char *
435 strend(const char *cp)
437 if (!cp)
438 return ((char *)(intptr_t)cp);
439 while (*cp)
440 cp++;
441 return ((char *)(intptr_t)cp);
444 Char *
445 strip(Char *cp)
447 Char *dp = cp;
449 if (!cp)
450 return (cp);
451 while ((*dp++ &= TRIM) != '\0')
452 continue;
453 return (cp);
456 Char *
457 quote(Char *cp)
459 Char *dp = cp;
461 if (!cp)
462 return (cp);
463 while (*dp != '\0')
464 *dp++ |= QUOTE;
465 return (cp);
468 const Char *
469 quote_meta(struct Strbuf *buf, const Char *s)
471 buf->len = 0;
472 while (*s != '\0') {
473 if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
474 Strbuf_append1(buf, '\\');
475 Strbuf_append1(buf, *s++);
477 Strbuf_terminate(buf);
478 return buf->s;
481 void
482 udvar(Char *name)
484 setname(short2str(name));
485 stderror(ERR_NAME | ERR_UNDVAR);
489 prefix(const Char *sub, const Char *str)
492 for (;;) {
493 if (*sub == 0)
494 return (1);
495 if (*str == 0)
496 return (0);
497 if ((*sub++ & TRIM) != (*str++ & TRIM))
498 return (0);
501 #ifndef WINNT_NATIVE
502 char *
503 areadlink(const char *path)
505 char *buf;
506 size_t size;
507 ssize_t res;
509 size = MAXPATHLEN + 1;
510 buf = xmalloc(size);
511 while ((size_t)(res = readlink(path, buf, size)) == size) {
512 size *= 2;
513 buf = xrealloc(buf, size);
515 if (res == -1) {
516 int err;
518 err = errno;
519 xfree(buf);
520 errno = err;
521 return NULL;
523 buf[res] = '\0';
524 return xrealloc(buf, res + 1);
526 #endif /*!WINNT_NATIVE*/
528 void
529 xclose(int fildes)
531 if (fildes < 0)
532 return;
533 while (close(fildes) == -1 && errno == EINTR)
534 handle_pending_signals();
537 void
538 xclosedir(DIR *dirp)
540 while (closedir(dirp) == -1 && errno == EINTR)
541 handle_pending_signals();
545 xcreat(const char *path, mode_t mode)
547 int res;
549 while ((res = creat(path, mode)) == -1 && errno == EINTR)
550 handle_pending_signals();
551 return res;
554 #ifdef HAVE_DUP2
555 static int
556 xdup2(int fildes, int fildes2)
558 int res;
560 while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
561 handle_pending_signals();
562 return res;
564 #endif
566 struct group *
567 xgetgrgid(gid_t xgid)
569 struct group *res;
571 errno = 0;
572 while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
573 handle_pending_signals();
574 errno = 0;
576 return res;
579 struct passwd *
580 xgetpwnam(const char *name)
582 struct passwd *res;
584 errno = 0;
585 while ((res = getpwnam(name)) == NULL && errno == EINTR) {
586 handle_pending_signals();
587 errno = 0;
589 return res;
592 struct passwd *
593 xgetpwuid(uid_t xuid)
595 struct passwd *res;
597 errno = 0;
598 while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
599 handle_pending_signals();
600 errno = 0;
602 return res;
606 xopen(const char *path, int oflag, ...)
608 int res;
610 if ((oflag & O_CREAT) == 0) {
611 while ((res = open(path, oflag)) == -1 && errno == EINTR)
612 handle_pending_signals();
613 } else {
614 va_list ap;
615 mode_t mode;
617 va_start(ap, oflag);
618 /* "int" should actually be "mode_t after default argument
619 promotions". "int" is the best guess we have, "mode_t" used to be
620 "unsigned short", which we obviously can't use. */
621 mode = va_arg(ap, int);
622 va_end(ap);
623 while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
624 handle_pending_signals();
626 return res;
629 ssize_t
630 xread(int fildes, void *buf, size_t nbyte)
632 ssize_t res;
634 /* This is where we will be blocked most of the time, so handle signals
635 that didn't interrupt any system call. */
637 handle_pending_signals();
638 while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
639 return res;
642 #ifdef POSIX
644 xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
646 int res;
648 while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
649 errno == EINTR)
650 handle_pending_signals();
651 return res;
653 #endif
655 ssize_t
656 xwrite(int fildes, const void *buf, size_t nbyte)
658 ssize_t res;
660 /* This is where we will be blocked most of the time, so handle signals
661 that didn't interrupt any system call. */
663 handle_pending_signals();
664 while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
665 return res;