sh.misc.c revision 256281
167754Smsmith/* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $ */
267754Smsmith/*
367754Smsmith * sh.misc.c: Miscelaneous functions
467754Smsmith */
567754Smsmith/*-
667754Smsmith * Copyright (c) 1980, 1991 The Regents of the University of California.
767754Smsmith * All rights reserved.
867754Smsmith *
967754Smsmith * Redistribution and use in source and binary forms, with or without
1067754Smsmith * modification, are permitted provided that the following conditions
1167754Smsmith * are met:
12193267Sjkim * 1. Redistributions of source code must retain the above copyright
1370243Smsmith *    notice, this list of conditions and the following disclaimer.
1467754Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1567754Smsmith *    notice, this list of conditions and the following disclaimer in the
1667754Smsmith *    documentation and/or other materials provided with the distribution.
1767754Smsmith * 3. Neither the name of the University nor the names of its contributors
1867754Smsmith *    may be used to endorse or promote products derived from this software
1967754Smsmith *    without specific prior written permission.
2067754Smsmith *
2167754Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2267754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2367754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2467754Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2567754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2667754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2767754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2867754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2967754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3067754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3167754Smsmith * SUCH DAMAGE.
3267754Smsmith */
3367754Smsmith#include "sh.h"
3467754Smsmith
3567754SmsmithRCSID("$tcsh: sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $")
3667754Smsmith
3767754Smsmithstatic	int	renum	(int, int);
3867754Smsmithstatic  Char  **blkend	(Char **);
3967754Smsmithstatic  Char  **blkcat	(Char **, Char **);
4067754Smsmithstatic	int	xdup2	(int, int);
4167754Smsmith
4267754Smsmith/*
4367754Smsmith * C Shell
4467754Smsmith */
4567754Smsmith
4667754Smsmithint
4767754Smsmithany(const char *s, Char c)
4867754Smsmith{
4967754Smsmith    if (!s)
5067754Smsmith	return (0);		/* Check for nil pointer */
5167754Smsmith    while (*s)
5267754Smsmith	if ((Char)*s++ == c)
5367754Smsmith	    return (1);
5467754Smsmith    return (0);
5567754Smsmith}
5667754Smsmith
5767754Smsmithvoid
5867754Smsmithsetzero(void *p, size_t size)
5967754Smsmith{
6067754Smsmith    memset(p, 0, size);
6167754Smsmith}
6267754Smsmith
6367754Smsmith#ifndef SHORT_STRINGS
6467754Smsmithchar *
6567754Smsmithstrnsave(const char *s, size_t len)
6667754Smsmith{
6767754Smsmith    char *r;
6867754Smsmith
6967754Smsmith    r = xmalloc(len + 1);
7067754Smsmith    memcpy(r, s, len);
7167754Smsmith    r[len] = '\0';
7267754Smsmith    return r;
7367754Smsmith}
7467754Smsmith#endif
7567754Smsmith
7667754Smsmithchar   *
7767754Smsmithstrsave(const char *s)
7867754Smsmith{
7967754Smsmith    char   *r;
8067754Smsmith    size_t size;
8167754Smsmith
8267754Smsmith    if (s == NULL)
8367754Smsmith	s = "";
8467754Smsmith    size = strlen(s) + 1;
8567754Smsmith    r = xmalloc(size);
8667754Smsmith    memcpy(r, s, size);
8767754Smsmith    return (r);
8867754Smsmith}
8967754Smsmith
9067754Smsmithstatic Char  **
9167754Smsmithblkend(Char **up)
9267754Smsmith{
9367754Smsmith
9467754Smsmith    while (*up)
9567754Smsmith	up++;
9667754Smsmith    return (up);
9767754Smsmith}
9867754Smsmith
9967754Smsmith
10067754Smsmithvoid
10167754Smsmithblkpr(Char *const *av)
10267754Smsmith{
10367754Smsmith
10467754Smsmith    for (; *av; av++) {
10567754Smsmith	xprintf("%S", *av);
10667754Smsmith	if (av[1])
10767754Smsmith	    xprintf(" ");
10867754Smsmith    }
10967754Smsmith}
11067754Smsmith
11167754SmsmithChar *
11267754Smsmithblkexpand(Char *const *av)
11367754Smsmith{
11467754Smsmith    struct Strbuf buf = Strbuf_INIT;
11567754Smsmith
11667754Smsmith    for (; *av; av++) {
11767754Smsmith	Strbuf_append(&buf, *av);
11867754Smsmith	if (av[1])
119193251Sjkim	    Strbuf_append1(&buf, ' ');
120193267Sjkim    }
121193251Sjkim    return Strbuf_finish(&buf);
122193267Sjkim}
123193267Sjkim
12467754Smsmithint
12567754Smsmithblklen(Char **av)
12677424Smsmith{
12791116Smsmith    int i = 0;
12867754Smsmith
12967754Smsmith    while (*av++)
130117521Snjl	i++;
13167754Smsmith    return (i);
13267754Smsmith}
13367754Smsmith
13467754SmsmithChar  **
135151937Sjkimblkcpy(Char **oav, Char **bv)
136151937Sjkim{
137151937Sjkim    Char **av = oav;
13867754Smsmith
13967754Smsmith    while ((*av++ = *bv++) != NULL)
14067754Smsmith	continue;
14167754Smsmith    return (oav);
14267754Smsmith}
14367754Smsmith
14467754Smsmithstatic Char  **
14567754Smsmithblkcat(Char **up, Char **vp)
14667754Smsmith{
14767754Smsmith
14867754Smsmith    (void) blkcpy(blkend(up), vp);
14967754Smsmith    return (up);
15067754Smsmith}
15167754Smsmith
15267754Smsmithvoid
15367754Smsmithblkfree(Char **av0)
15467754Smsmith{
15569450Smsmith    Char **av = av0;
15667754Smsmith
15767754Smsmith    if (!av0)
15867754Smsmith	return;
15991116Smsmith    for (; *av; av++)
16083174Smsmith	xfree(*av);
16183174Smsmith    xfree(av0);
16277424Smsmith}
16377424Smsmith
16467754Smsmithvoid
16567754Smsmithblk_cleanup(void *ptr)
16667754Smsmith{
16767754Smsmith    blkfree(ptr);
16867754Smsmith}
16969746Smsmith
17069746Smsmithvoid
17167754Smsmithblk_indirect_cleanup(void *xptr)
17267754Smsmith{
17385756Smsmith    Char ***ptr;
17469450Smsmith
17567754Smsmith    ptr = xptr;
17667754Smsmith    blkfree(*ptr);
17767754Smsmith    xfree(ptr);
178167802Sjkim}
17967754Smsmith
180167802SjkimChar  **
181167802Sjkimsaveblk(Char **v)
182167802Sjkim{
183167802Sjkim    Char **newv, **onewv;
184167802Sjkim
185167802Sjkim    if (v == NULL)
186167802Sjkim	return NULL;
187167802Sjkim
188167802Sjkim    onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
189167802Sjkim
190167802Sjkim    while (*v)
191167802Sjkim	*newv++ = Strsave(*v++);
192167802Sjkim    return (onewv);
193167802Sjkim}
19491116Smsmith
195167802Sjkim#ifndef HAVE_STRSTR
196167802Sjkimchar   *
19791116Smsmithstrstr(const char *s, const char *t)
19867754Smsmith{
199167802Sjkim    do {
200167802Sjkim	const char *ss = s;
201167802Sjkim	const char *tt = t;
20267754Smsmith
203167802Sjkim	do
20467754Smsmith	    if (*tt == '\0')
20567754Smsmith		return (s);
206167802Sjkim	while (*ss++ == *tt++);
20767754Smsmith    } while (*s++ != '\0');
208167802Sjkim    return (NULL);
20969746Smsmith}
21067754Smsmith#endif /* !HAVE_STRSTR */
21167754Smsmith
21267754Smsmithchar   *
21367754Smsmithstrspl(const char *cp, const char *dp)
21467754Smsmith{
21567754Smsmith    char   *ep;
21667754Smsmith    size_t cl, dl;
217167802Sjkim
21867754Smsmith    if (!cp)
219167802Sjkim	cp = "";
220117521Snjl    if (!dp)
22167754Smsmith	dp = "";
22283174Smsmith    cl = strlen(cp);
22367754Smsmith    dl = strlen(dp);
22467754Smsmith    ep = xmalloc((cl + dl + 1) * sizeof(char));
22567754Smsmith    memcpy(ep, cp, cl);
22691116Smsmith    memcpy(ep + cl, dp, dl + 1);
22767754Smsmith    return (ep);
22867754Smsmith}
22967754Smsmith
23067754SmsmithChar  **
23167754Smsmithblkspl(Char **up, Char **vp)
23267754Smsmith{
23367754Smsmith    Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
23467754Smsmith
23567754Smsmith    (void) blkcpy(wp, up);
23667754Smsmith    return (blkcat(wp, vp));
23767754Smsmith}
23867754Smsmith
23967754SmsmithChar
24091116Smsmithlastchr(Char *cp)
24167754Smsmith{
24267754Smsmith
24367754Smsmith    if (!cp)
24467754Smsmith	return (0);
24567754Smsmith    if (!*cp)
24691116Smsmith	return (0);
24767754Smsmith    while (cp[1])
24891116Smsmith	cp++;
24967754Smsmith    return (*cp);
25067754Smsmith}
25167754Smsmith
25267754Smsmith/*
25391116Smsmith * This routine is called after an error to close up
25491116Smsmith * any units which may have been left open accidentally.
25567754Smsmith */
25691116Smsmithvoid
25767754Smsmithclosem(void)
25867754Smsmith{
25967754Smsmith    int f, num_files;
26067754Smsmith
26167754Smsmith#ifdef NLS_BUGS
26267754Smsmith#ifdef NLS_CATALOGS
26391116Smsmith    nlsclose();
26467754Smsmith#endif /* NLS_CATALOGS */
26567754Smsmith#endif /* NLS_BUGS */
26667754Smsmith#ifdef YPBUGS
26767754Smsmith    /* suggested by Justin Bur; thanks to Karl Kleinpaste */
26867754Smsmith    fix_yp_bugs();
26991116Smsmith#endif /* YPBUGS */
27067754Smsmith    num_files = NOFILE;
27191116Smsmith    for (f = 0; f < num_files; f++)
27291116Smsmith	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
27391116Smsmith	    f != FSHTTY
27491116Smsmith#ifdef MALLOC_TRACE
27591116Smsmith	    && f != 25
27691116Smsmith#endif /* MALLOC_TRACE */
27785756Smsmith	    )
27867754Smsmith	  {
27967754Smsmith	    xclose(f);
28067754Smsmith#ifdef NISPLUS
28167754Smsmith	    if(f < 3)
28267754Smsmith		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
28367754Smsmith#endif /* NISPLUS */
28491116Smsmith	  }
28567754Smsmith#ifdef NLS_BUGS
286114237Snjl#ifdef NLS_CATALOGS
28791116Smsmith    nlsinit();
28867754Smsmith#endif /* NLS_CATALOGS */
28967754Smsmith#endif /* NLS_BUGS */
29067754Smsmith}
29167754Smsmith
29267754Smsmith#ifndef CLOSE_ON_EXEC
29367754Smsmith/*
294123315Snjl * Close files before executing a file.
29567754Smsmith * We could be MUCH more intelligent, since (on a version 7 system)
296114237Snjl * we need only close files here during a source, the other
29767754Smsmith * shell fd's being in units 16-19 which are closed automatically!
29867754Smsmith */
29967754Smsmithvoid
30067754Smsmithclosech(void)
30167754Smsmith{
30291116Smsmith    int f, num_files;
30367754Smsmith
30467754Smsmith    if (didcch)
30567754Smsmith	return;
306167802Sjkim    didcch = 1;
30767754Smsmith    SHIN = 0;
308167802Sjkim    SHOUT = 1;
309117521Snjl    SHDIAG = 2;
31067754Smsmith    OLDSTD = 0;
31167754Smsmith    isoutatty = isatty(SHOUT);
31267754Smsmith    isdiagatty = isatty(SHDIAG);
31367754Smsmith    num_files = NOFILE;
314151937Sjkim    for (f = 3; f < num_files; f++)
31567754Smsmith	xclose(f);
31667754Smsmith}
31767754Smsmith
31867754Smsmith#endif /* CLOSE_ON_EXEC */
31967754Smsmith
32067754Smsmithvoid
32167754Smsmithdonefds(void)
32267754Smsmith{
32367754Smsmith
32467754Smsmith    xclose(0);
32567754Smsmith    xclose(1);
32667754Smsmith    xclose(2);
327117521Snjl    didfds = 0;
32867754Smsmith#ifdef NISPLUS
32967754Smsmith    {
33067754Smsmith	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
331151937Sjkim	(void)dcopy(fd, 1);
332117521Snjl	(void)dcopy(fd, 2);
333117521Snjl	(void)dmove(fd, 0);
334117521Snjl    }
33567754Smsmith#endif /*NISPLUS*/
33667754Smsmith}
33767754Smsmith
33867754Smsmith/*
339117521Snjl * Move descriptor i to j.
34067754Smsmith * If j is -1 then we just want to get i to a safe place,
34167754Smsmith * i.e. to a unit > FSAFE.  This also happens in dcopy.
34267754Smsmith */
34367754Smsmithint
344117521Snjldmove(int i, int j)
345117521Snjl{
346117521Snjl
347117521Snjl    if (i == j || i < 0)
348117521Snjl	return (i);
349117521Snjl#ifdef HAVE_DUP2
350167802Sjkim    if (j >= 0) {
351151937Sjkim	(void) xdup2(i, j);
352151937Sjkim	if (j != i)
353151937Sjkim	    xclose(i);
354151937Sjkim	return (j);
355151937Sjkim    }
35691116Smsmith#endif
35791116Smsmith    j = dcopy(i, j);
35891116Smsmith    if (j != i)
359151937Sjkim	xclose(i);
36091116Smsmith    return (j);
36167754Smsmith}
36285756Smsmith
36367754Smsmithint
36467754Smsmithdcopy(int i, int j)
36591116Smsmith{
366193267Sjkim
367151937Sjkim    if (i == j || i < 0 || (j < 0 && i > FSAFE))
36867754Smsmith	return (i);
36967754Smsmith    if (j >= 0) {
370117521Snjl#ifdef HAVE_DUP2
37167754Smsmith	(void) xdup2(i, j);
372117521Snjl	return (j);
373117521Snjl#else
374151937Sjkim	xclose(j);
375151937Sjkim#endif
376151937Sjkim    }
377117521Snjl    return (renum(i, j));
378193267Sjkim}
379193267Sjkim
380193267Sjkimstatic int
381193267Sjkimrenum(int i, int j)
382193267Sjkim{
38391116Smsmith    int k = dup(i);
38491116Smsmith
38591116Smsmith    if (k < 0)
386151937Sjkim	return (-1);
38791116Smsmith    if (j == -1 && k > FSAFE)
38867754Smsmith	return (k);
389117521Snjl    if (k != j) {
390117521Snjl	j = renum(k, j);
391151937Sjkim	xclose(k);
39267754Smsmith	return (j);
393117521Snjl    }
394117521Snjl    return (k);
395129684Snjl}
396123315Snjl
397117521Snjl/*
398151937Sjkim * Left shift a command argument list, discarding
399117521Snjl * the first c arguments.  Used in "shift" commands
400117521Snjl * as well as by commands like "repeat".
40167754Smsmith */
402117521Snjlvoid
40367754Smsmithlshift(Char **v, int c)
404151937Sjkim{
405117521Snjl    Char **u;
406117521Snjl
407151937Sjkim    for (u = v; *u && --c >= 0; u++)
408117521Snjl	xfree(*u);
40967754Smsmith    (void) blkcpy(v, u);
410117521Snjl}
41167754Smsmith
412151937Sjkimint
413117521Snjlnumber(Char *cp)
414117521Snjl{
415151937Sjkim    if (!cp)
416117521Snjl	return (0);
417117521Snjl    if (*cp == '-') {
418117521Snjl	cp++;
419117521Snjl	if (!Isdigit(*cp))
420117521Snjl	    return (0);
421117521Snjl	cp++;
422117521Snjl    }
423167802Sjkim    while (*cp && Isdigit(*cp))
424151937Sjkim	cp++;
425117521Snjl    return (*cp == 0);
426117521Snjl}
427117521Snjl
428117521SnjlChar  **
429151937Sjkimcopyblk(Char **v)
430117521Snjl{
431117521Snjl    Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
432151937Sjkim
433117521Snjl    return (blkcpy(nv, v));
434117521Snjl}
435117521Snjl
436117521Snjlchar   *
437123315Snjlstrend(const char *cp)
438151937Sjkim{
439117521Snjl    if (!cp)
440117521Snjl	return ((char *)(intptr_t)cp);
441151937Sjkim    while (*cp)
442117521Snjl	cp++;
443117521Snjl    return ((char *)(intptr_t)cp);
444126372Snjl}
445126372Snjl
446151937SjkimChar   *
447126372Snjlstrip(Char *cp)
448126372Snjl{
449151937Sjkim    Char *dp = cp;
450126372Snjl
45167754Smsmith    if (!cp)
45267754Smsmith	return (cp);
453117521Snjl    while ((*dp++ &= TRIM) != '\0')
45467754Smsmith	continue;
455117521Snjl    return (cp);
456117521Snjl}
45767754Smsmith
458117521SnjlChar   *
45967754Smsmithquote(Char *cp)
46067754Smsmith{
461117521Snjl    Char *dp = cp;
462117521Snjl
463117521Snjl    if (!cp)
464151937Sjkim	return (cp);
465117521Snjl    while (*dp != '\0')
466117521Snjl	*dp++ |= QUOTE;
46767754Smsmith    return (cp);
468117521Snjl}
46967754Smsmith
47067754Smsmithconst Char *
47167754Smsmithquote_meta(struct Strbuf *buf, const Char *s)
472117521Snjl{
473167802Sjkim    buf->len = 0;
474117521Snjl    while (*s != '\0') {
47567754Smsmith	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
476167802Sjkim	    Strbuf_append1(buf, '\\');
47767754Smsmith	Strbuf_append1(buf, *s++);
478117521Snjl    }
47967754Smsmith    Strbuf_terminate(buf);
48067754Smsmith    return buf->s;
481167802Sjkim}
482167802Sjkim
483193267Sjkimvoid
484193267Sjkimudvar(Char *name)
485193267Sjkim{
486193267Sjkim    setname(short2str(name));
487193267Sjkim    stderror(ERR_NAME | ERR_UNDVAR);
488193267Sjkim}
489193267Sjkim
490193267Sjkimint
491193267Sjkimprefix(const Char *sub, const Char *str)
492193267Sjkim{
493193267Sjkim
494193267Sjkim    for (;;) {
495193267Sjkim	if (*sub == 0)
496193267Sjkim	    return (1);
497193267Sjkim	if (*str == 0)
498193267Sjkim	    return (0);
499193267Sjkim	if ((*sub++ & TRIM) != (*str++ & TRIM))
500193267Sjkim	    return (0);
501193267Sjkim    }
502193267Sjkim}
503193267Sjkim#ifndef WINNT_NATIVE
504193267Sjkimchar *
505193267Sjkimareadlink(const char *path)
506193267Sjkim{
507193267Sjkim    char *buf;
508193267Sjkim    size_t size;
509193267Sjkim    ssize_t res;
510193267Sjkim
511193267Sjkim    size = MAXPATHLEN + 1;
512193267Sjkim    buf = xmalloc(size);
513193267Sjkim    while ((size_t)(res = readlink(path, buf, size)) == size) {
514193267Sjkim	size *= 2;
515193267Sjkim	buf = xrealloc(buf, size);
516193267Sjkim    }
517193267Sjkim    if (res == -1) {
518193267Sjkim	int err;
519193267Sjkim
520193267Sjkim	err = errno;
521193267Sjkim	xfree(buf);
522193267Sjkim	errno = err;
523193267Sjkim	return NULL;
524193267Sjkim    }
525193267Sjkim    buf[res] = '\0';
526193267Sjkim    return xrealloc(buf, res + 1);
527193267Sjkim}
528193267Sjkim#endif /*!WINNT_NATIVE*/
529193267Sjkim
530193267Sjkimvoid
531193267Sjkimxclose(int fildes)
532193267Sjkim{
533193267Sjkim    if (fildes < 0)
534193267Sjkim	return;
535193267Sjkim    while (close(fildes) == -1 && errno == EINTR)
536193267Sjkim	handle_pending_signals();
537193267Sjkim}
538193267Sjkim
539193267Sjkimvoid
540193267Sjkimxclosedir(DIR *dirp)
541193267Sjkim{
542193267Sjkim    while (closedir(dirp) == -1 && errno == EINTR)
543193267Sjkim	handle_pending_signals();
544193267Sjkim}
545193267Sjkim
546193267Sjkimint
547193267Sjkimxcreat(const char *path, mode_t mode)
548193267Sjkim{
549193267Sjkim    int res;
550193267Sjkim
551193267Sjkim    while ((res = creat(path, mode)) == -1 && errno == EINTR)
552193267Sjkim	handle_pending_signals();
553193267Sjkim    return res;
554193267Sjkim}
555193267Sjkim
556193267Sjkim#ifdef HAVE_DUP2
557193267Sjkimstatic int
558193267Sjkimxdup2(int fildes, int fildes2)
559193267Sjkim{
560193267Sjkim    int res;
561193267Sjkim
562193267Sjkim    while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
563193267Sjkim	handle_pending_signals();
564193267Sjkim    return res;
565193267Sjkim}
566193267Sjkim#endif
567193267Sjkim
568193267Sjkimstruct group *
569193267Sjkimxgetgrgid(gid_t xgid)
570193267Sjkim{
571193267Sjkim    struct group *res;
572193267Sjkim
573193267Sjkim    errno = 0;
574193267Sjkim    while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
575193267Sjkim	handle_pending_signals();
576193267Sjkim	errno = 0;
577193267Sjkim    }
578193267Sjkim    return res;
579193267Sjkim}
580193267Sjkim
581193267Sjkimstruct passwd *
582193267Sjkimxgetpwnam(const char *name)
583193267Sjkim{
584193267Sjkim    struct passwd *res;
585193267Sjkim
586193267Sjkim    errno = 0;
587193267Sjkim    while ((res = getpwnam(name)) == NULL && errno == EINTR) {
588193267Sjkim	handle_pending_signals();
589193267Sjkim	errno = 0;
590193267Sjkim    }
591193267Sjkim    return res;
592193267Sjkim}
593193267Sjkim
594193267Sjkimstruct passwd *
595193267Sjkimxgetpwuid(uid_t xuid)
596193267Sjkim{
597193267Sjkim    struct passwd *res;
598193267Sjkim
599193267Sjkim    errno = 0;
600193267Sjkim    while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
601193267Sjkim	handle_pending_signals();
602193267Sjkim	errno = 0;
603193267Sjkim    }
604193267Sjkim    return res;
605193267Sjkim}
606193267Sjkim
607193267Sjkimint
608193267Sjkimxopen(const char *path, int oflag, ...)
609193267Sjkim{
610193267Sjkim    int res;
611193267Sjkim
612193267Sjkim    if ((oflag & O_CREAT) == 0) {
613193267Sjkim	while ((res = open(path, oflag)) == -1 && errno == EINTR)
614193267Sjkim	    handle_pending_signals();
615193267Sjkim    } else {
616193267Sjkim	va_list ap;
617193267Sjkim	mode_t mode;
618193267Sjkim
619193267Sjkim	va_start(ap, oflag);
620193267Sjkim	/* "int" should actually be "mode_t after default argument
621193267Sjkim	   promotions". "int" is the best guess we have, "mode_t" used to be
622193267Sjkim	   "unsigned short", which we obviously can't use. */
623193267Sjkim	mode = va_arg(ap, int);
624193267Sjkim	va_end(ap);
625193267Sjkim	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
626193267Sjkim	    handle_pending_signals();
627193267Sjkim    }
628193267Sjkim    return res;
629193267Sjkim}
630193267Sjkim
631193267Sjkimssize_t
632193267Sjkimxread(int fildes, void *buf, size_t nbyte)
633193267Sjkim{
634193267Sjkim    ssize_t res;
635193267Sjkim
636193267Sjkim    /* This is where we will be blocked most of the time, so handle signals
637193267Sjkim       that didn't interrupt any system call. */
638193267Sjkim    do
639193267Sjkim      handle_pending_signals();
640193267Sjkim    while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
641193267Sjkim    return res;
642193267Sjkim}
643193267Sjkim
644193267Sjkim#ifdef POSIX
645int
646xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
647{
648    int res;
649
650    while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
651	   errno == EINTR)
652	handle_pending_signals();
653    return res;
654}
655#endif
656
657ssize_t
658xwrite(int fildes, const void *buf, size_t nbyte)
659{
660    ssize_t res;
661
662    /* This is where we will be blocked most of the time, so handle signals
663       that didn't interrupt any system call. */
664    do
665      handle_pending_signals();
666    while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
667    return res;
668}
669