1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $ */
259243Sobrien/*
359243Sobrien * sh.misc.c: Miscelaneous functions
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and binary forms, with or without
1059243Sobrien * modification, are permitted provided that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source code must retain the above copyright
1359243Sobrien *    notice, this list of conditions and the following disclaimer.
1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1559243Sobrien *    notice, this list of conditions and the following disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp * 3. Neither the name of the University nor the names of its contributors
1859243Sobrien *    may be used to endorse or promote products derived from this software
1959243Sobrien *    without specific prior written permission.
2059243Sobrien *
2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459243Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159243Sobrien * SUCH DAMAGE.
3259243Sobrien */
3359243Sobrien#include "sh.h"
3459243Sobrien
35232633SmpRCSID("$tcsh: sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $")
3659243Sobrien
37167465Smpstatic	int	renum	(int, int);
38167465Smpstatic  Char  **blkend	(Char **);
39167465Smpstatic  Char  **blkcat	(Char **, Char **);
40167465Smpstatic	int	xdup2	(int, int);
4159243Sobrien
4259243Sobrien/*
4359243Sobrien * C Shell
4459243Sobrien */
4559243Sobrien
4659243Sobrienint
47167465Smpany(const char *s, Char c)
4859243Sobrien{
4959243Sobrien    if (!s)
5059243Sobrien	return (0);		/* Check for nil pointer */
5159243Sobrien    while (*s)
52145479Smp	if ((Char)*s++ == c)
5359243Sobrien	    return (1);
5459243Sobrien    return (0);
5559243Sobrien}
5659243Sobrien
5759243Sobrienvoid
58167465Smpsetzero(void *p, size_t size)
5959243Sobrien{
60167465Smp    memset(p, 0, size);
6159243Sobrien}
6259243Sobrien
63232633Smp#ifndef SHORT_STRINGS
64167465Smpchar *
65167465Smpstrnsave(const char *s, size_t len)
66167465Smp{
67167465Smp    char *r;
68167465Smp
69167465Smp    r = xmalloc(len + 1);
70167465Smp    memcpy(r, s, len);
71167465Smp    r[len] = '\0';
72167465Smp    return r;
73167465Smp}
74232633Smp#endif
75167465Smp
7659243Sobrienchar   *
77167465Smpstrsave(const char *s)
7859243Sobrien{
79167465Smp    char   *r;
80167465Smp    size_t size;
8159243Sobrien
8259243Sobrien    if (s == NULL)
83145479Smp	s = "";
84167465Smp    size = strlen(s) + 1;
85167465Smp    r = xmalloc(size);
86167465Smp    memcpy(r, s, size);
87145479Smp    return (r);
8859243Sobrien}
8959243Sobrien
9059243Sobrienstatic Char  **
91167465Smpblkend(Char **up)
9259243Sobrien{
9359243Sobrien
9459243Sobrien    while (*up)
9559243Sobrien	up++;
9659243Sobrien    return (up);
9759243Sobrien}
9859243Sobrien
9959243Sobrien
10059243Sobrienvoid
101167465Smpblkpr(Char *const *av)
10259243Sobrien{
10359243Sobrien
10459243Sobrien    for (; *av; av++) {
10559243Sobrien	xprintf("%S", *av);
10659243Sobrien	if (av[1])
10759243Sobrien	    xprintf(" ");
10859243Sobrien    }
10959243Sobrien}
11059243Sobrien
111167465SmpChar *
112167465Smpblkexpand(Char *const *av)
11359243Sobrien{
114167465Smp    struct Strbuf buf = Strbuf_INIT;
115167465Smp
11659243Sobrien    for (; *av; av++) {
117167465Smp	Strbuf_append(&buf, *av);
11859243Sobrien	if (av[1])
119167465Smp	    Strbuf_append1(&buf, ' ');
12059243Sobrien    }
121167465Smp    return Strbuf_finish(&buf);
12259243Sobrien}
12359243Sobrien
12459243Sobrienint
125167465Smpblklen(Char **av)
12659243Sobrien{
127145479Smp    int i = 0;
12859243Sobrien
12959243Sobrien    while (*av++)
13059243Sobrien	i++;
13159243Sobrien    return (i);
13259243Sobrien}
13359243Sobrien
13459243SobrienChar  **
135167465Smpblkcpy(Char **oav, Char **bv)
13659243Sobrien{
137145479Smp    Char **av = oav;
13859243Sobrien
13959243Sobrien    while ((*av++ = *bv++) != NULL)
14059243Sobrien	continue;
14159243Sobrien    return (oav);
14259243Sobrien}
14359243Sobrien
14459243Sobrienstatic Char  **
145167465Smpblkcat(Char **up, Char **vp)
14659243Sobrien{
14759243Sobrien
14859243Sobrien    (void) blkcpy(blkend(up), vp);
14959243Sobrien    return (up);
15059243Sobrien}
15159243Sobrien
15259243Sobrienvoid
153167465Smpblkfree(Char **av0)
15459243Sobrien{
155145479Smp    Char **av = av0;
15659243Sobrien
15759243Sobrien    if (!av0)
15859243Sobrien	return;
15959243Sobrien    for (; *av; av++)
160167465Smp	xfree(*av);
161167465Smp    xfree(av0);
16259243Sobrien}
16359243Sobrien
164167465Smpvoid
165167465Smpblk_cleanup(void *ptr)
166167465Smp{
167167465Smp    blkfree(ptr);
168167465Smp}
169167465Smp
170167465Smpvoid
171167465Smpblk_indirect_cleanup(void *xptr)
172167465Smp{
173167465Smp    Char ***ptr;
174167465Smp
175167465Smp    ptr = xptr;
176167465Smp    blkfree(*ptr);
177167465Smp    xfree(ptr);
178167465Smp}
179167465Smp
18059243SobrienChar  **
181167465Smpsaveblk(Char **v)
18259243Sobrien{
183167465Smp    Char **newv, **onewv;
18459243Sobrien
185167465Smp    if (v == NULL)
186167465Smp	return NULL;
187167465Smp
188167465Smp    onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
189167465Smp
19059243Sobrien    while (*v)
19159243Sobrien	*newv++ = Strsave(*v++);
19259243Sobrien    return (onewv);
19359243Sobrien}
19459243Sobrien
195145479Smp#ifndef HAVE_STRSTR
19659243Sobrienchar   *
197167465Smpstrstr(const char *s, const char *t)
19859243Sobrien{
19959243Sobrien    do {
200145479Smp	const char *ss = s;
201145479Smp	const char *tt = t;
20259243Sobrien
20359243Sobrien	do
20459243Sobrien	    if (*tt == '\0')
205167465Smp		return (s);
20659243Sobrien	while (*ss++ == *tt++);
20759243Sobrien    } while (*s++ != '\0');
20859243Sobrien    return (NULL);
20959243Sobrien}
210145479Smp#endif /* !HAVE_STRSTR */
21159243Sobrien
21259243Sobrienchar   *
213167465Smpstrspl(const char *cp, const char *dp)
21459243Sobrien{
21559243Sobrien    char   *ep;
216145479Smp    size_t cl, dl;
21759243Sobrien
21859243Sobrien    if (!cp)
21959243Sobrien	cp = "";
22059243Sobrien    if (!dp)
22159243Sobrien	dp = "";
222145479Smp    cl = strlen(cp);
223145479Smp    dl = strlen(dp);
224167465Smp    ep = xmalloc((cl + dl + 1) * sizeof(char));
225145479Smp    memcpy(ep, cp, cl);
226145479Smp    memcpy(ep + cl, dp, dl + 1);
22759243Sobrien    return (ep);
22859243Sobrien}
22959243Sobrien
23059243SobrienChar  **
231167465Smpblkspl(Char **up, Char **vp)
23259243Sobrien{
233167465Smp    Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
23459243Sobrien
23559243Sobrien    (void) blkcpy(wp, up);
23659243Sobrien    return (blkcat(wp, vp));
23759243Sobrien}
23859243Sobrien
23959243SobrienChar
240167465Smplastchr(Char *cp)
24159243Sobrien{
24259243Sobrien
24359243Sobrien    if (!cp)
24459243Sobrien	return (0);
24559243Sobrien    if (!*cp)
24659243Sobrien	return (0);
24759243Sobrien    while (cp[1])
24859243Sobrien	cp++;
24959243Sobrien    return (*cp);
25059243Sobrien}
25159243Sobrien
25259243Sobrien/*
25359243Sobrien * This routine is called after an error to close up
25459243Sobrien * any units which may have been left open accidentally.
25559243Sobrien */
25659243Sobrienvoid
257167465Smpclosem(void)
25859243Sobrien{
259167465Smp    int f, num_files;
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 */
27759243Sobrien	    )
27859243Sobrien	  {
279167465Smp	    xclose(f);
28059243Sobrien#ifdef NISPLUS
28159243Sobrien	    if(f < 3)
282167465Smp		(void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
28359243Sobrien#endif /* NISPLUS */
28459243Sobrien	  }
285131962Smp#ifdef NLS_BUGS
286131962Smp#ifdef NLS_CATALOGS
287131962Smp    nlsinit();
288131962Smp#endif /* NLS_CATALOGS */
289131962Smp#endif /* NLS_BUGS */
29059243Sobrien}
29159243Sobrien
29259243Sobrien#ifndef CLOSE_ON_EXEC
29359243Sobrien/*
29459243Sobrien * Close files before executing a file.
29559243Sobrien * We could be MUCH more intelligent, since (on a version 7 system)
29659243Sobrien * we need only close files here during a source, the other
29759243Sobrien * shell fd's being in units 16-19 which are closed automatically!
29859243Sobrien */
29959243Sobrienvoid
300167465Smpclosech(void)
30159243Sobrien{
302167465Smp    int f, num_files;
30359243Sobrien
30459243Sobrien    if (didcch)
30559243Sobrien	return;
30659243Sobrien    didcch = 1;
30759243Sobrien    SHIN = 0;
30859243Sobrien    SHOUT = 1;
30959243Sobrien    SHDIAG = 2;
31059243Sobrien    OLDSTD = 0;
31159243Sobrien    isoutatty = isatty(SHOUT);
31259243Sobrien    isdiagatty = isatty(SHDIAG);
313167465Smp    num_files = NOFILE;
314167465Smp    for (f = 3; f < num_files; f++)
315167465Smp	xclose(f);
31659243Sobrien}
31759243Sobrien
31859243Sobrien#endif /* CLOSE_ON_EXEC */
31959243Sobrien
32059243Sobrienvoid
321167465Smpdonefds(void)
32259243Sobrien{
32359243Sobrien
324167465Smp    xclose(0);
325167465Smp    xclose(1);
326167465Smp    xclose(2);
32759243Sobrien    didfds = 0;
32859243Sobrien#ifdef NISPLUS
32959243Sobrien    {
330167465Smp	int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
331145479Smp	(void)dcopy(fd, 1);
332145479Smp	(void)dcopy(fd, 2);
333145479Smp	(void)dmove(fd, 0);
33459243Sobrien    }
33559243Sobrien#endif /*NISPLUS*/
33659243Sobrien}
33759243Sobrien
33859243Sobrien/*
33959243Sobrien * Move descriptor i to j.
34059243Sobrien * If j is -1 then we just want to get i to a safe place,
341145479Smp * i.e. to a unit > FSAFE.  This also happens in dcopy.
34259243Sobrien */
34359243Sobrienint
344167465Smpdmove(int i, int j)
34559243Sobrien{
34659243Sobrien
34759243Sobrien    if (i == j || i < 0)
34859243Sobrien	return (i);
349145479Smp#ifdef HAVE_DUP2
35059243Sobrien    if (j >= 0) {
351167465Smp	(void) xdup2(i, j);
35259243Sobrien	if (j != i)
353167465Smp	    xclose(i);
35459243Sobrien	return (j);
35559243Sobrien    }
35659243Sobrien#endif
35759243Sobrien    j = dcopy(i, j);
35859243Sobrien    if (j != i)
359167465Smp	xclose(i);
36059243Sobrien    return (j);
36159243Sobrien}
36259243Sobrien
36359243Sobrienint
364167465Smpdcopy(int i, int j)
36559243Sobrien{
36659243Sobrien
367145479Smp    if (i == j || i < 0 || (j < 0 && i > FSAFE))
36859243Sobrien	return (i);
36959243Sobrien    if (j >= 0) {
370145479Smp#ifdef HAVE_DUP2
371167465Smp	(void) xdup2(i, j);
37259243Sobrien	return (j);
37359243Sobrien#else
374167465Smp	xclose(j);
37559243Sobrien#endif
37659243Sobrien    }
37759243Sobrien    return (renum(i, j));
37859243Sobrien}
37959243Sobrien
38059243Sobrienstatic int
381167465Smprenum(int i, int j)
38259243Sobrien{
383145479Smp    int k = dup(i);
38459243Sobrien
38559243Sobrien    if (k < 0)
38659243Sobrien	return (-1);
387145479Smp    if (j == -1 && k > FSAFE)
38859243Sobrien	return (k);
38959243Sobrien    if (k != j) {
39059243Sobrien	j = renum(k, j);
391167465Smp	xclose(k);
39259243Sobrien	return (j);
39359243Sobrien    }
39459243Sobrien    return (k);
39559243Sobrien}
39659243Sobrien
39759243Sobrien/*
39859243Sobrien * Left shift a command argument list, discarding
39959243Sobrien * the first c arguments.  Used in "shift" commands
40059243Sobrien * as well as by commands like "repeat".
40159243Sobrien */
40259243Sobrienvoid
403167465Smplshift(Char **v, int c)
40459243Sobrien{
405145479Smp    Char **u;
40659243Sobrien
40759243Sobrien    for (u = v; *u && --c >= 0; u++)
408167465Smp	xfree(*u);
40959243Sobrien    (void) blkcpy(v, u);
41059243Sobrien}
41159243Sobrien
41259243Sobrienint
413167465Smpnumber(Char *cp)
41459243Sobrien{
41559243Sobrien    if (!cp)
41659243Sobrien	return (0);
41759243Sobrien    if (*cp == '-') {
41859243Sobrien	cp++;
41959243Sobrien	if (!Isdigit(*cp))
42059243Sobrien	    return (0);
42159243Sobrien	cp++;
42259243Sobrien    }
42359243Sobrien    while (*cp && Isdigit(*cp))
42459243Sobrien	cp++;
42559243Sobrien    return (*cp == 0);
42659243Sobrien}
42759243Sobrien
42859243SobrienChar  **
429167465Smpcopyblk(Char **v)
43059243Sobrien{
431167465Smp    Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
43259243Sobrien
43359243Sobrien    return (blkcpy(nv, v));
43459243Sobrien}
43559243Sobrien
43659243Sobrienchar   *
437167465Smpstrend(const char *cp)
43859243Sobrien{
43959243Sobrien    if (!cp)
440167465Smp	return ((char *)(intptr_t)cp);
44159243Sobrien    while (*cp)
44259243Sobrien	cp++;
443167465Smp    return ((char *)(intptr_t)cp);
44459243Sobrien}
44559243Sobrien
44659243SobrienChar   *
447167465Smpstrip(Char *cp)
44859243Sobrien{
449145479Smp    Char *dp = cp;
45059243Sobrien
45159243Sobrien    if (!cp)
45259243Sobrien	return (cp);
45359243Sobrien    while ((*dp++ &= TRIM) != '\0')
45459243Sobrien	continue;
45559243Sobrien    return (cp);
45659243Sobrien}
45759243Sobrien
45859243SobrienChar   *
459167465Smpquote(Char *cp)
46059243Sobrien{
461145479Smp    Char *dp = cp;
46259243Sobrien
46359243Sobrien    if (!cp)
46459243Sobrien	return (cp);
46559243Sobrien    while (*dp != '\0')
46659243Sobrien	*dp++ |= QUOTE;
46759243Sobrien    return (cp);
46859243Sobrien}
46959243Sobrien
470167465Smpconst Char *
471167465Smpquote_meta(struct Strbuf *buf, const Char *s)
47259243Sobrien{
473167465Smp    buf->len = 0;
47459243Sobrien    while (*s != '\0') {
47559243Sobrien	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
476167465Smp	    Strbuf_append1(buf, '\\');
477167465Smp	Strbuf_append1(buf, *s++);
47859243Sobrien    }
479167465Smp    Strbuf_terminate(buf);
480167465Smp    return buf->s;
48159243Sobrien}
48259243Sobrien
48359243Sobrienvoid
484167465Smpudvar(Char *name)
48559243Sobrien{
48659243Sobrien    setname(short2str(name));
48759243Sobrien    stderror(ERR_NAME | ERR_UNDVAR);
48859243Sobrien}
48959243Sobrien
49059243Sobrienint
491167465Smpprefix(const Char *sub, const Char *str)
49259243Sobrien{
49359243Sobrien
49459243Sobrien    for (;;) {
49559243Sobrien	if (*sub == 0)
49659243Sobrien	    return (1);
49759243Sobrien	if (*str == 0)
49859243Sobrien	    return (0);
49959243Sobrien	if ((*sub++ & TRIM) != (*str++ & TRIM))
50059243Sobrien	    return (0);
50159243Sobrien    }
50259243Sobrien}
503167465Smp#ifndef WINNT_NATIVE
504167465Smpchar *
505167465Smpareadlink(const char *path)
506167465Smp{
507167465Smp    char *buf;
508167465Smp    size_t size;
509167465Smp    ssize_t res;
510167465Smp
511167465Smp    size = MAXPATHLEN + 1;
512167465Smp    buf = xmalloc(size);
513167465Smp    while ((size_t)(res = readlink(path, buf, size)) == size) {
514167465Smp	size *= 2;
515167465Smp	buf = xrealloc(buf, size);
516167465Smp    }
517167465Smp    if (res == -1) {
518167465Smp	int err;
519167465Smp
520167465Smp	err = errno;
521167465Smp	xfree(buf);
522167465Smp	errno = err;
523167465Smp	return NULL;
524167465Smp    }
525167465Smp    buf[res] = '\0';
526167465Smp    return xrealloc(buf, res + 1);
527167465Smp}
528167465Smp#endif /*!WINNT_NATIVE*/
529167465Smp
530167465Smpvoid
531167465Smpxclose(int fildes)
532167465Smp{
533167465Smp    if (fildes < 0)
534167465Smp	return;
535167465Smp    while (close(fildes) == -1 && errno == EINTR)
536167465Smp	handle_pending_signals();
537167465Smp}
538167465Smp
539167465Smpvoid
540167465Smpxclosedir(DIR *dirp)
541167465Smp{
542167465Smp    while (closedir(dirp) == -1 && errno == EINTR)
543167465Smp	handle_pending_signals();
544167465Smp}
545167465Smp
546167465Smpint
547167465Smpxcreat(const char *path, mode_t mode)
548167465Smp{
549167465Smp    int res;
550167465Smp
551167465Smp    while ((res = creat(path, mode)) == -1 && errno == EINTR)
552167465Smp	handle_pending_signals();
553167465Smp    return res;
554167465Smp}
555167465Smp
556167465Smp#ifdef HAVE_DUP2
557167465Smpstatic int
558167465Smpxdup2(int fildes, int fildes2)
559167465Smp{
560167465Smp    int res;
561167465Smp
562167465Smp    while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
563167465Smp	handle_pending_signals();
564167465Smp    return res;
565167465Smp}
566167465Smp#endif
567167465Smp
568167465Smpstruct group *
569167465Smpxgetgrgid(gid_t xgid)
570167465Smp{
571167465Smp    struct group *res;
572167465Smp
573167465Smp    errno = 0;
574167465Smp    while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
575167465Smp	handle_pending_signals();
576167465Smp	errno = 0;
577167465Smp    }
578167465Smp    return res;
579167465Smp}
580167465Smp
581167465Smpstruct passwd *
582167465Smpxgetpwnam(const char *name)
583167465Smp{
584167465Smp    struct passwd *res;
585167465Smp
586167465Smp    errno = 0;
587167465Smp    while ((res = getpwnam(name)) == NULL && errno == EINTR) {
588167465Smp	handle_pending_signals();
589167465Smp	errno = 0;
590167465Smp    }
591167465Smp    return res;
592167465Smp}
593167465Smp
594167465Smpstruct passwd *
595167465Smpxgetpwuid(uid_t xuid)
596167465Smp{
597167465Smp    struct passwd *res;
598167465Smp
599167465Smp    errno = 0;
600167465Smp    while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
601167465Smp	handle_pending_signals();
602167465Smp	errno = 0;
603167465Smp    }
604167465Smp    return res;
605167465Smp}
606167465Smp
607167465Smpint
608167465Smpxopen(const char *path, int oflag, ...)
609167465Smp{
610167465Smp    int res;
611167465Smp
612167465Smp    if ((oflag & O_CREAT) == 0) {
613167465Smp	while ((res = open(path, oflag)) == -1 && errno == EINTR)
614167465Smp	    handle_pending_signals();
615167465Smp    } else {
616167465Smp	va_list ap;
617167465Smp	mode_t mode;
618167465Smp
619167465Smp	va_start(ap, oflag);
620167465Smp	/* "int" should actually be "mode_t after default argument
621167465Smp	   promotions". "int" is the best guess we have, "mode_t" used to be
622167465Smp	   "unsigned short", which we obviously can't use. */
623167465Smp	mode = va_arg(ap, int);
624167465Smp	va_end(ap);
625167465Smp	while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
626167465Smp	    handle_pending_signals();
627167465Smp    }
628167465Smp    return res;
629167465Smp}
630167465Smp
631167465Smpssize_t
632167465Smpxread(int fildes, void *buf, size_t nbyte)
633167465Smp{
634167465Smp    ssize_t res;
635167465Smp
636167465Smp    /* This is where we will be blocked most of the time, so handle signals
637167465Smp       that didn't interrupt any system call. */
638167465Smp    do
639167465Smp      handle_pending_signals();
640167465Smp    while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
641167465Smp    return res;
642167465Smp}
643167465Smp
644167465Smp#ifdef POSIX
645167465Smpint
646167465Smpxtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
647167465Smp{
648167465Smp    int res;
649167465Smp
650167465Smp    while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
651167465Smp	   errno == EINTR)
652167465Smp	handle_pending_signals();
653167465Smp    return res;
654167465Smp}
655167465Smp#endif
656167465Smp
657167465Smpssize_t
658167465Smpxwrite(int fildes, const void *buf, size_t nbyte)
659167465Smp{
660167465Smp    ssize_t res;
661167465Smp
662167465Smp    /* This is where we will be blocked most of the time, so handle signals
663167465Smp       that didn't interrupt any system call. */
664167465Smp    do
665167465Smp      handle_pending_signals();
666167465Smp    while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
667167465Smp    return res;
668167465Smp}
669