159243Sobrien/*
259243Sobrien * sh.misc.c: Miscelaneous functions
359243Sobrien */
459243Sobrien/*-
559243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
659243Sobrien * All rights reserved.
759243Sobrien *
859243Sobrien * Redistribution and use in source and binary forms, with or without
959243Sobrien * modification, are permitted provided that the following conditions
1059243Sobrien * are met:
1159243Sobrien * 1. Redistributions of source code must retain the above copyright
1259243Sobrien *    notice, this list of conditions and the following disclaimer.
1359243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1459243Sobrien *    notice, this list of conditions and the following disclaimer in the
1559243Sobrien *    documentation and/or other materials provided with the distribution.
16100616Smp * 3. Neither the name of the University nor the names of its contributors
1759243Sobrien *    may be used to endorse or promote products derived from this software
1859243Sobrien *    without specific prior written permission.
1959243Sobrien *
2059243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2359243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3059243Sobrien * SUCH DAMAGE.
3159243Sobrien */
3259243Sobrien#include "sh.h"
3359243Sobrien
34167465Smpstatic	int	renum	(int, int);
35167465Smpstatic  Char  **blkend	(Char **);
36167465Smpstatic  Char  **blkcat	(Char **, Char **);
37167465Smpstatic	int	xdup2	(int, int);
3859243Sobrien
3959243Sobrien/*
4059243Sobrien * C Shell
4159243Sobrien */
4259243Sobrien
4359243Sobrienint
44167465Smpany(const char *s, Char c)
4559243Sobrien{
4659243Sobrien    if (!s)
4759243Sobrien	return (0);		/* Check for nil pointer */
4859243Sobrien    while (*s)
49145479Smp	if ((Char)*s++ == c)
5059243Sobrien	    return (1);
5159243Sobrien    return (0);
5259243Sobrien}
5359243Sobrien
5459243Sobrienvoid
55167465Smpsetzero(void *p, size_t size)
5659243Sobrien{
57167465Smp    memset(p, 0, size);
5859243Sobrien}
5959243Sobrien
60231990Smp#ifndef SHORT_STRINGS
61167465Smpchar *
62167465Smpstrnsave(const char *s, size_t len)
63167465Smp{
64167465Smp    char *r;
65167465Smp
66167465Smp    r = xmalloc(len + 1);
67167465Smp    memcpy(r, s, len);
68167465Smp    r[len] = '\0';
69167465Smp    return r;
70167465Smp}
71231990Smp#endif
72167465Smp
7359243Sobrienchar   *
74167465Smpstrsave(const char *s)
7559243Sobrien{
76167465Smp    char   *r;
77167465Smp    size_t size;
7859243Sobrien
7959243Sobrien    if (s == NULL)
80145479Smp	s = "";
81167465Smp    size = strlen(s) + 1;
82167465Smp    r = xmalloc(size);
83167465Smp    memcpy(r, s, size);
84145479Smp    return (r);
8559243Sobrien}
8659243Sobrien
8759243Sobrienstatic Char  **
88167465Smpblkend(Char **up)
8959243Sobrien{
9059243Sobrien
9159243Sobrien    while (*up)
9259243Sobrien	up++;
9359243Sobrien    return (up);
9459243Sobrien}
9559243Sobrien
9659243Sobrien
9759243Sobrienvoid
98167465Smpblkpr(Char *const *av)
9959243Sobrien{
10059243Sobrien
10159243Sobrien    for (; *av; av++) {
10259243Sobrien	xprintf("%S", *av);
10359243Sobrien	if (av[1])
10459243Sobrien	    xprintf(" ");
10559243Sobrien    }
10659243Sobrien}
10759243Sobrien
108167465SmpChar *
109167465Smpblkexpand(Char *const *av)
11059243Sobrien{
111167465Smp    struct Strbuf buf = Strbuf_INIT;
112167465Smp
11359243Sobrien    for (; *av; av++) {
114167465Smp	Strbuf_append(&buf, *av);
11559243Sobrien	if (av[1])
116167465Smp	    Strbuf_append1(&buf, ' ');
11759243Sobrien    }
118167465Smp    return Strbuf_finish(&buf);
11959243Sobrien}
12059243Sobrien
12159243Sobrienint
122167465Smpblklen(Char **av)
12359243Sobrien{
124145479Smp    int i = 0;
12559243Sobrien
12659243Sobrien    while (*av++)
12759243Sobrien	i++;
12859243Sobrien    return (i);
12959243Sobrien}
13059243Sobrien
13159243SobrienChar  **
132167465Smpblkcpy(Char **oav, Char **bv)
13359243Sobrien{
134145479Smp    Char **av = oav;
13559243Sobrien
13659243Sobrien    while ((*av++ = *bv++) != NULL)
13759243Sobrien	continue;
13859243Sobrien    return (oav);
13959243Sobrien}
14059243Sobrien
14159243Sobrienstatic Char  **
142167465Smpblkcat(Char **up, Char **vp)
14359243Sobrien{
14459243Sobrien
14559243Sobrien    (void) blkcpy(blkend(up), vp);
14659243Sobrien    return (up);
14759243Sobrien}
14859243Sobrien
14959243Sobrienvoid
150167465Smpblkfree(Char **av0)
15159243Sobrien{
152145479Smp    Char **av = av0;
15359243Sobrien
15459243Sobrien    if (!av0)
15559243Sobrien	return;
15659243Sobrien    for (; *av; av++)
157167465Smp	xfree(*av);
158167465Smp    xfree(av0);
15959243Sobrien}
16059243Sobrien
161167465Smpvoid
162167465Smpblk_cleanup(void *ptr)
163167465Smp{
164167465Smp    blkfree(ptr);
165167465Smp}
166167465Smp
167167465Smpvoid
168167465Smpblk_indirect_cleanup(void *xptr)
169167465Smp{
170167465Smp    Char ***ptr;
171167465Smp
172167465Smp    ptr = xptr;
173167465Smp    blkfree(*ptr);
174167465Smp    xfree(ptr);
175167465Smp}
176167465Smp
17759243SobrienChar  **
178167465Smpsaveblk(Char **v)
17959243Sobrien{
180167465Smp    Char **newv, **onewv;
18159243Sobrien
182167465Smp    if (v == NULL)
183167465Smp	return NULL;
184167465Smp
185167465Smp    onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
186167465Smp
18759243Sobrien    while (*v)
18859243Sobrien	*newv++ = Strsave(*v++);
18959243Sobrien    return (onewv);
19059243Sobrien}
19159243Sobrien
192145479Smp#ifndef HAVE_STRSTR
19359243Sobrienchar   *
194167465Smpstrstr(const char *s, const char *t)
19559243Sobrien{
19659243Sobrien    do {
197145479Smp	const char *ss = s;
198145479Smp	const char *tt = t;
19959243Sobrien
20059243Sobrien	do
20159243Sobrien	    if (*tt == '\0')
202167465Smp		return (s);
20359243Sobrien	while (*ss++ == *tt++);
20459243Sobrien    } while (*s++ != '\0');
20559243Sobrien    return (NULL);
20659243Sobrien}
207145479Smp#endif /* !HAVE_STRSTR */
20859243Sobrien
20959243Sobrienchar   *
210167465Smpstrspl(const char *cp, const char *dp)
21159243Sobrien{
21259243Sobrien    char   *ep;
213145479Smp    size_t cl, dl;
21459243Sobrien
21559243Sobrien    if (!cp)
21659243Sobrien	cp = "";
21759243Sobrien    if (!dp)
21859243Sobrien	dp = "";
219145479Smp    cl = strlen(cp);
220145479Smp    dl = strlen(dp);
221167465Smp    ep = xmalloc((cl + dl + 1) * sizeof(char));
222145479Smp    memcpy(ep, cp, cl);
223145479Smp    memcpy(ep + cl, dp, dl + 1);
22459243Sobrien    return (ep);
22559243Sobrien}
22659243Sobrien
22759243SobrienChar  **
228167465Smpblkspl(Char **up, Char **vp)
22959243Sobrien{
230167465Smp    Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
23159243Sobrien
23259243Sobrien    (void) blkcpy(wp, up);
23359243Sobrien    return (blkcat(wp, vp));
23459243Sobrien}
23559243Sobrien
23659243SobrienChar
237167465Smplastchr(Char *cp)
23859243Sobrien{
23959243Sobrien
24059243Sobrien    if (!cp)
24159243Sobrien	return (0);
24259243Sobrien    if (!*cp)
24359243Sobrien	return (0);
24459243Sobrien    while (cp[1])
24559243Sobrien	cp++;
24659243Sobrien    return (*cp);
24759243Sobrien}
24859243Sobrien
24959243Sobrien/*
25059243Sobrien * This routine is called after an error to close up
25159243Sobrien * any units which may have been left open accidentally.
25259243Sobrien */
25359243Sobrienvoid
254167465Smpclosem(void)
25559243Sobrien{
256167465Smp    int f, num_files;
257354195Sbrooks#ifdef S_ISSOCK
258354195Sbrooks    struct stat st;
259354195Sbrooks#endif /*S_ISSOCK*/
26059243Sobrien
261131962Smp#ifdef NLS_BUGS
262131962Smp#ifdef NLS_CATALOGS
263145479Smp    nlsclose();
264131962Smp#endif /* NLS_CATALOGS */
265131962Smp#endif /* NLS_BUGS */
26659243Sobrien#ifdef YPBUGS
26759243Sobrien    /* suggested by Justin Bur; thanks to Karl Kleinpaste */
26859243Sobrien    fix_yp_bugs();
26959243Sobrien#endif /* YPBUGS */
270167465Smp    num_files = NOFILE;
271167465Smp    for (f = 0; f < num_files; f++)
27259243Sobrien	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
27359243Sobrien	    f != FSHTTY
27459243Sobrien#ifdef MALLOC_TRACE
27559243Sobrien	    && f != 25
27659243Sobrien#endif /* MALLOC_TRACE */
277354195Sbrooks#ifdef S_ISSOCK
278354195Sbrooks	    /* NSS modules (e.g. Linux nss_ldap) might keep sockets open.
279354195Sbrooks	     * If we close such a socket, both the NSS module and tcsh think
280354195Sbrooks	     * they "own" the descriptor.
281354195Sbrooks	     *
282354195Sbrooks	     * Not closing sockets does not make the cleanup use of closem()
283354195Sbrooks	     * less reliable because tcsh never creates sockets.
284354195Sbrooks	     */
285354195Sbrooks	    && fstat(f, &st) == 0 && !S_ISSOCK(st.st_mode)
286354195Sbrooks#endif
28759243Sobrien	    )
28859243Sobrien	  {
289167465Smp	    xclose(f);
29059243Sobrien#ifdef NISPLUS
29159243Sobrien	    if(f < 3)
292167465Smp		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
29359243Sobrien#endif /* NISPLUS */
29459243Sobrien	  }
295131962Smp#ifdef NLS_BUGS
296131962Smp#ifdef NLS_CATALOGS
297131962Smp    nlsinit();
298131962Smp#endif /* NLS_CATALOGS */
299131962Smp#endif /* NLS_BUGS */
30059243Sobrien}
30159243Sobrien
30259243Sobrien#ifndef CLOSE_ON_EXEC
30359243Sobrien/*
30459243Sobrien * Close files before executing a file.
30559243Sobrien * We could be MUCH more intelligent, since (on a version 7 system)
30659243Sobrien * we need only close files here during a source, the other
30759243Sobrien * shell fd's being in units 16-19 which are closed automatically!
30859243Sobrien */
30959243Sobrienvoid
310167465Smpclosech(void)
31159243Sobrien{
312167465Smp    int f, num_files;
31359243Sobrien
31459243Sobrien    if (didcch)
31559243Sobrien	return;
31659243Sobrien    didcch = 1;
31759243Sobrien    SHIN = 0;
31859243Sobrien    SHOUT = 1;
31959243Sobrien    SHDIAG = 2;
32059243Sobrien    OLDSTD = 0;
32159243Sobrien    isoutatty = isatty(SHOUT);
32259243Sobrien    isdiagatty = isatty(SHDIAG);
323167465Smp    num_files = NOFILE;
324167465Smp    for (f = 3; f < num_files; f++)
325167465Smp	xclose(f);
32659243Sobrien}
32759243Sobrien
32859243Sobrien#endif /* CLOSE_ON_EXEC */
32959243Sobrien
33059243Sobrienvoid
331167465Smpdonefds(void)
33259243Sobrien{
33359243Sobrien
334167465Smp    xclose(0);
335167465Smp    xclose(1);
336167465Smp    xclose(2);
33759243Sobrien    didfds = 0;
33859243Sobrien#ifdef NISPLUS
33959243Sobrien    {
340167465Smp	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
341145479Smp	(void)dcopy(fd, 1);
342145479Smp	(void)dcopy(fd, 2);
343145479Smp	(void)dmove(fd, 0);
34459243Sobrien    }
34559243Sobrien#endif /*NISPLUS*/
34659243Sobrien}
34759243Sobrien
34859243Sobrien/*
34959243Sobrien * Move descriptor i to j.
35059243Sobrien * If j is -1 then we just want to get i to a safe place,
351145479Smp * i.e. to a unit > FSAFE.  This also happens in dcopy.
35259243Sobrien */
35359243Sobrienint
354167465Smpdmove(int i, int j)
35559243Sobrien{
35659243Sobrien
35759243Sobrien    if (i == j || i < 0)
35859243Sobrien	return (i);
359145479Smp#ifdef HAVE_DUP2
36059243Sobrien    if (j >= 0) {
361167465Smp	(void) xdup2(i, j);
36259243Sobrien	if (j != i)
363167465Smp	    xclose(i);
36459243Sobrien	return (j);
36559243Sobrien    }
36659243Sobrien#endif
36759243Sobrien    j = dcopy(i, j);
36859243Sobrien    if (j != i)
369167465Smp	xclose(i);
37059243Sobrien    return (j);
37159243Sobrien}
37259243Sobrien
37359243Sobrienint
374167465Smpdcopy(int i, int j)
37559243Sobrien{
37659243Sobrien
377145479Smp    if (i == j || i < 0 || (j < 0 && i > FSAFE))
37859243Sobrien	return (i);
37959243Sobrien    if (j >= 0) {
380145479Smp#ifdef HAVE_DUP2
381167465Smp	(void) xdup2(i, j);
38259243Sobrien	return (j);
38359243Sobrien#else
384167465Smp	xclose(j);
38559243Sobrien#endif
38659243Sobrien    }
38759243Sobrien    return (renum(i, j));
38859243Sobrien}
38959243Sobrien
39059243Sobrienstatic int
391167465Smprenum(int i, int j)
39259243Sobrien{
393145479Smp    int k = dup(i);
39459243Sobrien
39559243Sobrien    if (k < 0)
39659243Sobrien	return (-1);
397145479Smp    if (j == -1 && k > FSAFE)
39859243Sobrien	return (k);
39959243Sobrien    if (k != j) {
40059243Sobrien	j = renum(k, j);
401167465Smp	xclose(k);
40259243Sobrien	return (j);
40359243Sobrien    }
40459243Sobrien    return (k);
40559243Sobrien}
40659243Sobrien
40759243Sobrien/*
40859243Sobrien * Left shift a command argument list, discarding
40959243Sobrien * the first c arguments.  Used in "shift" commands
41059243Sobrien * as well as by commands like "repeat".
41159243Sobrien */
41259243Sobrienvoid
413167465Smplshift(Char **v, int c)
41459243Sobrien{
415145479Smp    Char **u;
41659243Sobrien
41759243Sobrien    for (u = v; *u && --c >= 0; u++)
418167465Smp	xfree(*u);
41959243Sobrien    (void) blkcpy(v, u);
42059243Sobrien}
42159243Sobrien
42259243Sobrienint
423167465Smpnumber(Char *cp)
42459243Sobrien{
42559243Sobrien    if (!cp)
42659243Sobrien	return (0);
42759243Sobrien    if (*cp == '-') {
42859243Sobrien	cp++;
42959243Sobrien	if (!Isdigit(*cp))
43059243Sobrien	    return (0);
43159243Sobrien	cp++;
43259243Sobrien    }
43359243Sobrien    while (*cp && Isdigit(*cp))
43459243Sobrien	cp++;
43559243Sobrien    return (*cp == 0);
43659243Sobrien}
43759243Sobrien
43859243SobrienChar  **
439167465Smpcopyblk(Char **v)
44059243Sobrien{
441167465Smp    Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
44259243Sobrien
44359243Sobrien    return (blkcpy(nv, v));
44459243Sobrien}
44559243Sobrien
44659243Sobrienchar   *
447167465Smpstrend(const char *cp)
44859243Sobrien{
44959243Sobrien    if (!cp)
450167465Smp	return ((char *)(intptr_t)cp);
45159243Sobrien    while (*cp)
45259243Sobrien	cp++;
453167465Smp    return ((char *)(intptr_t)cp);
45459243Sobrien}
45559243Sobrien
45659243SobrienChar   *
457167465Smpstrip(Char *cp)
45859243Sobrien{
459145479Smp    Char *dp = cp;
46059243Sobrien
46159243Sobrien    if (!cp)
46259243Sobrien	return (cp);
463316957Sdchagin    while (*dp != '\0') {
464316957Sdchagin#if INVALID_BYTE != 0
465316957Sdchagin	if ((*dp & INVALID_BYTE) != INVALID_BYTE)    /* *dp < INVALID_BYTE */
466316957Sdchagin#endif
467316957Sdchagin		*dp &= TRIM;
468316957Sdchagin	dp++;
469316957Sdchagin    }
47059243Sobrien    return (cp);
47159243Sobrien}
47259243Sobrien
47359243SobrienChar   *
474167465Smpquote(Char *cp)
47559243Sobrien{
476145479Smp    Char *dp = cp;
47759243Sobrien
47859243Sobrien    if (!cp)
47959243Sobrien	return (cp);
480316957Sdchagin    while (*dp != '\0') {
481316957Sdchagin#ifdef WIDE_STRINGS
482316957Sdchagin	if ((*dp & 0xffffff80) == 0)	/* *dp < 0x80 */
483316957Sdchagin#elif defined SHORT_STRINGS
484316957Sdchagin	if ((*dp & 0xff80) == 0)	/* *dp < 0x80 */
485316957Sdchagin#else
486316957Sdchagin	if ((*dp & 0x80) == 0)		/* *dp < 0x80 */
487316957Sdchagin#endif
488316957Sdchagin	    *dp |= QUOTE;
489316957Sdchagin	dp++;
490316957Sdchagin    }
49159243Sobrien    return (cp);
49259243Sobrien}
49359243Sobrien
494167465Smpconst Char *
495167465Smpquote_meta(struct Strbuf *buf, const Char *s)
49659243Sobrien{
497167465Smp    buf->len = 0;
49859243Sobrien    while (*s != '\0') {
49959243Sobrien	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
500167465Smp	    Strbuf_append1(buf, '\\');
501167465Smp	Strbuf_append1(buf, *s++);
50259243Sobrien    }
503167465Smp    Strbuf_terminate(buf);
504167465Smp    return buf->s;
50559243Sobrien}
50659243Sobrien
50759243Sobrienvoid
508167465Smpudvar(Char *name)
50959243Sobrien{
51059243Sobrien    setname(short2str(name));
51159243Sobrien    stderror(ERR_NAME | ERR_UNDVAR);
51259243Sobrien}
51359243Sobrien
51459243Sobrienint
515167465Smpprefix(const Char *sub, const Char *str)
51659243Sobrien{
51759243Sobrien
51859243Sobrien    for (;;) {
51959243Sobrien	if (*sub == 0)
52059243Sobrien	    return (1);
52159243Sobrien	if (*str == 0)
52259243Sobrien	    return (0);
52359243Sobrien	if ((*sub++ & TRIM) != (*str++ & TRIM))
52459243Sobrien	    return (0);
52559243Sobrien    }
52659243Sobrien}
527167465Smp#ifndef WINNT_NATIVE
528167465Smpchar *
529167465Smpareadlink(const char *path)
530167465Smp{
531167465Smp    char *buf;
532167465Smp    size_t size;
533167465Smp    ssize_t res;
534167465Smp
535167465Smp    size = MAXPATHLEN + 1;
536167465Smp    buf = xmalloc(size);
537167465Smp    while ((size_t)(res = readlink(path, buf, size)) == size) {
538167465Smp	size *= 2;
539167465Smp	buf = xrealloc(buf, size);
540167465Smp    }
541167465Smp    if (res == -1) {
542167465Smp	int err;
543167465Smp
544167465Smp	err = errno;
545167465Smp	xfree(buf);
546167465Smp	errno = err;
547167465Smp	return NULL;
548167465Smp    }
549167465Smp    buf[res] = '\0';
550167465Smp    return xrealloc(buf, res + 1);
551167465Smp}
552167465Smp#endif /*!WINNT_NATIVE*/
553167465Smp
554167465Smpvoid
555167465Smpxclose(int fildes)
556167465Smp{
557167465Smp    if (fildes < 0)
558167465Smp	return;
559167465Smp    while (close(fildes) == -1 && errno == EINTR)
560316957Sdchagin	if (handle_pending_signals())
561316957Sdchagin	    break;
562167465Smp}
563167465Smp
564167465Smpvoid
565167465Smpxclosedir(DIR *dirp)
566167465Smp{
567167465Smp    while (closedir(dirp) == -1 && errno == EINTR)
568316957Sdchagin	if (handle_pending_signals())
569316957Sdchagin	    break;
570167465Smp}
571167465Smp
572167465Smpint
573167465Smpxcreat(const char *path, mode_t mode)
574167465Smp{
575167465Smp    int res;
576167465Smp
577167465Smp    while ((res = creat(path, mode)) == -1 && errno == EINTR)
578316957Sdchagin	if (handle_pending_signals())
579316957Sdchagin	    break;
580167465Smp    return res;
581167465Smp}
582167465Smp
583167465Smp#ifdef HAVE_DUP2
584167465Smpstatic int
585167465Smpxdup2(int fildes, int fildes2)
586167465Smp{
587167465Smp    int res;
588167465Smp
589167465Smp    while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
590316957Sdchagin	if (handle_pending_signals())
591316957Sdchagin	    break;
592167465Smp    return res;
593167465Smp}
594167465Smp#endif
595167465Smp
596167465Smpstruct group *
597167465Smpxgetgrgid(gid_t xgid)
598167465Smp{
599167465Smp    struct group *res;
600167465Smp
601167465Smp    errno = 0;
602167465Smp    while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
603316957Sdchagin	if (handle_pending_signals())
604316957Sdchagin	    break;
605167465Smp	errno = 0;
606167465Smp    }
607167465Smp    return res;
608167465Smp}
609167465Smp
610167465Smpstruct passwd *
611167465Smpxgetpwnam(const char *name)
612167465Smp{
613167465Smp    struct passwd *res;
614167465Smp
615167465Smp    errno = 0;
616167465Smp    while ((res = getpwnam(name)) == NULL && errno == EINTR) {
617316957Sdchagin	if (handle_pending_signals())
618316957Sdchagin	    break;
619167465Smp	errno = 0;
620167465Smp    }
621167465Smp    return res;
622167465Smp}
623167465Smp
624167465Smpstruct passwd *
625167465Smpxgetpwuid(uid_t xuid)
626167465Smp{
627167465Smp    struct passwd *res;
628167465Smp
629167465Smp    errno = 0;
630167465Smp    while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
631316957Sdchagin	if (handle_pending_signals())
632316957Sdchagin	    break;
633167465Smp	errno = 0;
634167465Smp    }
635167465Smp    return res;
636167465Smp}
637167465Smp
638167465Smpint
639167465Smpxopen(const char *path, int oflag, ...)
640167465Smp{
641167465Smp    int res;
642167465Smp
643167465Smp    if ((oflag & O_CREAT) == 0) {
644167465Smp	while ((res = open(path, oflag)) == -1 && errno == EINTR)
645316957Sdchagin	    if (handle_pending_signals())
646316957Sdchagin		break;
647167465Smp    } else {
648167465Smp	va_list ap;
649167465Smp	mode_t mode;
650167465Smp
651167465Smp	va_start(ap, oflag);
652167465Smp	/* "int" should actually be "mode_t after default argument
653167465Smp	   promotions". "int" is the best guess we have, "mode_t" used to be
654167465Smp	   "unsigned short", which we obviously can't use. */
655167465Smp	mode = va_arg(ap, int);
656167465Smp	va_end(ap);
657167465Smp	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
658316957Sdchagin	    if (handle_pending_signals())
659316957Sdchagin		break;
660167465Smp    }
661167465Smp    return res;
662167465Smp}
663167465Smp
664167465Smpssize_t
665167465Smpxread(int fildes, void *buf, size_t nbyte)
666167465Smp{
667354195Sbrooks    ssize_t res = -1;
668167465Smp
669167465Smp    /* This is where we will be blocked most of the time, so handle signals
670167465Smp       that didn't interrupt any system call. */
671167465Smp    do
672316957Sdchagin      if (handle_pending_signals())
673316957Sdchagin	  break;
674167465Smp    while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
675167465Smp    return res;
676167465Smp}
677167465Smp
678167465Smp#ifdef POSIX
679167465Smpint
680167465Smpxtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
681167465Smp{
682167465Smp    int res;
683167465Smp
684167465Smp    while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
685167465Smp	   errno == EINTR)
686316957Sdchagin	if (handle_pending_signals())
687316957Sdchagin	    break;
688167465Smp    return res;
689167465Smp}
690167465Smp#endif
691167465Smp
692167465Smpssize_t
693167465Smpxwrite(int fildes, const void *buf, size_t nbyte)
694167465Smp{
695354195Sbrooks    ssize_t res = -1;
696167465Smp
697167465Smp    /* This is where we will be blocked most of the time, so handle signals
698167465Smp       that didn't interrupt any system call. */
699167465Smp    do
700316957Sdchagin      if (handle_pending_signals())
701316957Sdchagin	  break;
702167465Smp    while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
703167465Smp    return res;
704167465Smp}
705