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