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