1c80476e4SDavid E. O'Brien /* 2c80476e4SDavid E. O'Brien * sh.misc.c: Miscelaneous functions 3c80476e4SDavid E. O'Brien */ 4c80476e4SDavid E. O'Brien /*- 5c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 6c80476e4SDavid E. O'Brien * All rights reserved. 7c80476e4SDavid E. O'Brien * 8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 10c80476e4SDavid E. O'Brien * are met: 11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 18c80476e4SDavid E. O'Brien * without specific prior written permission. 19c80476e4SDavid E. O'Brien * 20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30c80476e4SDavid E. O'Brien * SUCH DAMAGE. 31c80476e4SDavid E. O'Brien */ 32c80476e4SDavid E. O'Brien #include "sh.h" 33c80476e4SDavid E. O'Brien 3445e5710bSMark Peek static int renum (int, int); 3545e5710bSMark Peek static Char **blkend (Char **); 3645e5710bSMark Peek static Char **blkcat (Char **, Char **); 3745e5710bSMark Peek static int xdup2 (int, int); 38c80476e4SDavid E. O'Brien 39c80476e4SDavid E. O'Brien /* 40c80476e4SDavid E. O'Brien * C Shell 41c80476e4SDavid E. O'Brien */ 42c80476e4SDavid E. O'Brien 43c80476e4SDavid E. O'Brien int 4445e5710bSMark Peek any(const char *s, Char c) 45c80476e4SDavid E. O'Brien { 46c80476e4SDavid E. O'Brien if (!s) 47c80476e4SDavid E. O'Brien return (0); /* Check for nil pointer */ 48c80476e4SDavid E. O'Brien while (*s) 4923338178SMark Peek if ((Char)*s++ == c) 50c80476e4SDavid E. O'Brien return (1); 51c80476e4SDavid E. O'Brien return (0); 52c80476e4SDavid E. O'Brien } 53c80476e4SDavid E. O'Brien 54c80476e4SDavid E. O'Brien void 5545e5710bSMark Peek setzero(void *p, size_t size) 56c80476e4SDavid E. O'Brien { 5745e5710bSMark Peek memset(p, 0, size); 58c80476e4SDavid E. O'Brien } 59c80476e4SDavid E. O'Brien 609ccc37e3SMark Peek #ifndef SHORT_STRINGS 61c80476e4SDavid E. O'Brien char * 6245e5710bSMark Peek strnsave(const char *s, size_t len) 63c80476e4SDavid E. O'Brien { 6445e5710bSMark Peek char *r; 6545e5710bSMark Peek 6645e5710bSMark Peek r = xmalloc(len + 1); 6745e5710bSMark Peek memcpy(r, s, len); 6845e5710bSMark Peek r[len] = '\0'; 6945e5710bSMark Peek return r; 7045e5710bSMark Peek } 719ccc37e3SMark Peek #endif 7245e5710bSMark Peek 7345e5710bSMark Peek char * 7445e5710bSMark Peek strsave(const char *s) 7545e5710bSMark Peek { 7645e5710bSMark Peek char *r; 7745e5710bSMark Peek size_t size; 78c80476e4SDavid E. O'Brien 79c80476e4SDavid E. O'Brien if (s == NULL) 8023338178SMark Peek s = ""; 8145e5710bSMark Peek size = strlen(s) + 1; 8245e5710bSMark Peek r = xmalloc(size); 8345e5710bSMark Peek memcpy(r, s, size); 8423338178SMark Peek return (r); 85c80476e4SDavid E. O'Brien } 86c80476e4SDavid E. O'Brien 87c80476e4SDavid E. O'Brien static Char ** 8845e5710bSMark Peek blkend(Char **up) 89c80476e4SDavid E. O'Brien { 90c80476e4SDavid E. O'Brien 91c80476e4SDavid E. O'Brien while (*up) 92c80476e4SDavid E. O'Brien up++; 93c80476e4SDavid E. O'Brien return (up); 94c80476e4SDavid E. O'Brien } 95c80476e4SDavid E. O'Brien 96c80476e4SDavid E. O'Brien 97c80476e4SDavid E. O'Brien void 9845e5710bSMark Peek blkpr(Char *const *av) 99c80476e4SDavid E. O'Brien { 100c80476e4SDavid E. O'Brien 101c80476e4SDavid E. O'Brien for (; *av; av++) { 102c80476e4SDavid E. O'Brien xprintf("%S", *av); 103c80476e4SDavid E. O'Brien if (av[1]) 104c80476e4SDavid E. O'Brien xprintf(" "); 105c80476e4SDavid E. O'Brien } 106c80476e4SDavid E. O'Brien } 107c80476e4SDavid E. O'Brien 10845e5710bSMark Peek Char * 10945e5710bSMark Peek blkexpand(Char *const *av) 110c80476e4SDavid E. O'Brien { 11145e5710bSMark Peek struct Strbuf buf = Strbuf_INIT; 11245e5710bSMark Peek 113c80476e4SDavid E. O'Brien for (; *av; av++) { 11445e5710bSMark Peek Strbuf_append(&buf, *av); 115c80476e4SDavid E. O'Brien if (av[1]) 11645e5710bSMark Peek Strbuf_append1(&buf, ' '); 117c80476e4SDavid E. O'Brien } 11845e5710bSMark Peek return Strbuf_finish(&buf); 119c80476e4SDavid E. O'Brien } 120c80476e4SDavid E. O'Brien 121c80476e4SDavid E. O'Brien int 12245e5710bSMark Peek blklen(Char **av) 123c80476e4SDavid E. O'Brien { 12423338178SMark Peek int i = 0; 125c80476e4SDavid E. O'Brien 126c80476e4SDavid E. O'Brien while (*av++) 127c80476e4SDavid E. O'Brien i++; 128c80476e4SDavid E. O'Brien return (i); 129c80476e4SDavid E. O'Brien } 130c80476e4SDavid E. O'Brien 131c80476e4SDavid E. O'Brien Char ** 13245e5710bSMark Peek blkcpy(Char **oav, Char **bv) 133c80476e4SDavid E. O'Brien { 13423338178SMark Peek Char **av = oav; 135c80476e4SDavid E. O'Brien 136c80476e4SDavid E. O'Brien while ((*av++ = *bv++) != NULL) 137c80476e4SDavid E. O'Brien continue; 138c80476e4SDavid E. O'Brien return (oav); 139c80476e4SDavid E. O'Brien } 140c80476e4SDavid E. O'Brien 141c80476e4SDavid E. O'Brien static Char ** 14245e5710bSMark Peek blkcat(Char **up, Char **vp) 143c80476e4SDavid E. O'Brien { 144c80476e4SDavid E. O'Brien 145c80476e4SDavid E. O'Brien (void) blkcpy(blkend(up), vp); 146c80476e4SDavid E. O'Brien return (up); 147c80476e4SDavid E. O'Brien } 148c80476e4SDavid E. O'Brien 149c80476e4SDavid E. O'Brien void 15045e5710bSMark Peek blkfree(Char **av0) 151c80476e4SDavid E. O'Brien { 15223338178SMark Peek Char **av = av0; 153c80476e4SDavid E. O'Brien 154c80476e4SDavid E. O'Brien if (!av0) 155c80476e4SDavid E. O'Brien return; 156c80476e4SDavid E. O'Brien for (; *av; av++) 15745e5710bSMark Peek xfree(*av); 15845e5710bSMark Peek xfree(av0); 15945e5710bSMark Peek } 16045e5710bSMark Peek 16145e5710bSMark Peek void 16245e5710bSMark Peek blk_cleanup(void *ptr) 16345e5710bSMark Peek { 16445e5710bSMark Peek blkfree(ptr); 16545e5710bSMark Peek } 16645e5710bSMark Peek 16745e5710bSMark Peek void 16845e5710bSMark Peek blk_indirect_cleanup(void *xptr) 16945e5710bSMark Peek { 17045e5710bSMark Peek Char ***ptr; 17145e5710bSMark Peek 17245e5710bSMark Peek ptr = xptr; 17345e5710bSMark Peek blkfree(*ptr); 17445e5710bSMark Peek xfree(ptr); 175c80476e4SDavid E. O'Brien } 176c80476e4SDavid E. O'Brien 177c80476e4SDavid E. O'Brien Char ** 17845e5710bSMark Peek saveblk(Char **v) 179c80476e4SDavid E. O'Brien { 18045e5710bSMark Peek Char **newv, **onewv; 18145e5710bSMark Peek 18245e5710bSMark Peek if (v == NULL) 18345e5710bSMark Peek return NULL; 18445e5710bSMark Peek 18545e5710bSMark Peek onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **)); 186c80476e4SDavid E. O'Brien 187c80476e4SDavid E. O'Brien while (*v) 188c80476e4SDavid E. O'Brien *newv++ = Strsave(*v++); 189c80476e4SDavid E. O'Brien return (onewv); 190c80476e4SDavid E. O'Brien } 191c80476e4SDavid E. O'Brien 19223338178SMark Peek #ifndef HAVE_STRSTR 193c80476e4SDavid E. O'Brien char * 19445e5710bSMark Peek strstr(const char *s, const char *t) 195c80476e4SDavid E. O'Brien { 196c80476e4SDavid E. O'Brien do { 19723338178SMark Peek const char *ss = s; 19823338178SMark Peek const char *tt = t; 199c80476e4SDavid E. O'Brien 200c80476e4SDavid E. O'Brien do 201c80476e4SDavid E. O'Brien if (*tt == '\0') 20245e5710bSMark Peek return (s); 203c80476e4SDavid E. O'Brien while (*ss++ == *tt++); 204c80476e4SDavid E. O'Brien } while (*s++ != '\0'); 205c80476e4SDavid E. O'Brien return (NULL); 206c80476e4SDavid E. O'Brien } 20723338178SMark Peek #endif /* !HAVE_STRSTR */ 208c80476e4SDavid E. O'Brien 209c80476e4SDavid E. O'Brien char * 21045e5710bSMark Peek strspl(const char *cp, const char *dp) 211c80476e4SDavid E. O'Brien { 212c80476e4SDavid E. O'Brien char *ep; 21323338178SMark Peek size_t cl, dl; 214c80476e4SDavid E. O'Brien 215c80476e4SDavid E. O'Brien if (!cp) 216c80476e4SDavid E. O'Brien cp = ""; 217c80476e4SDavid E. O'Brien if (!dp) 218c80476e4SDavid E. O'Brien dp = ""; 21923338178SMark Peek cl = strlen(cp); 22023338178SMark Peek dl = strlen(dp); 22145e5710bSMark Peek ep = xmalloc((cl + dl + 1) * sizeof(char)); 22223338178SMark Peek memcpy(ep, cp, cl); 22323338178SMark Peek memcpy(ep + cl, dp, dl + 1); 224c80476e4SDavid E. O'Brien return (ep); 225c80476e4SDavid E. O'Brien } 226c80476e4SDavid E. O'Brien 227c80476e4SDavid E. O'Brien Char ** 22845e5710bSMark Peek blkspl(Char **up, Char **vp) 229c80476e4SDavid E. O'Brien { 23045e5710bSMark Peek Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **)); 231c80476e4SDavid E. O'Brien 232c80476e4SDavid E. O'Brien (void) blkcpy(wp, up); 233c80476e4SDavid E. O'Brien return (blkcat(wp, vp)); 234c80476e4SDavid E. O'Brien } 235c80476e4SDavid E. O'Brien 236c80476e4SDavid E. O'Brien Char 23745e5710bSMark Peek lastchr(Char *cp) 238c80476e4SDavid E. O'Brien { 239c80476e4SDavid E. O'Brien 240c80476e4SDavid E. O'Brien if (!cp) 241c80476e4SDavid E. O'Brien return (0); 242c80476e4SDavid E. O'Brien if (!*cp) 243c80476e4SDavid E. O'Brien return (0); 244c80476e4SDavid E. O'Brien while (cp[1]) 245c80476e4SDavid E. O'Brien cp++; 246c80476e4SDavid E. O'Brien return (*cp); 247c80476e4SDavid E. O'Brien } 248c80476e4SDavid E. O'Brien 249c80476e4SDavid E. O'Brien /* 250c80476e4SDavid E. O'Brien * This routine is called after an error to close up 251c80476e4SDavid E. O'Brien * any units which may have been left open accidentally. 252c80476e4SDavid E. O'Brien */ 253c80476e4SDavid E. O'Brien void 25445e5710bSMark Peek closem(void) 255c80476e4SDavid E. O'Brien { 25645e5710bSMark Peek int f, num_files; 257cc698b49SBrooks Davis #ifdef S_ISSOCK 258cc698b49SBrooks Davis struct stat st; 259cc698b49SBrooks Davis #endif /*S_ISSOCK*/ 260c80476e4SDavid E. O'Brien 261b2d5d167SMark Peek #ifdef NLS_BUGS 262b2d5d167SMark Peek #ifdef NLS_CATALOGS 26323338178SMark Peek nlsclose(); 264b2d5d167SMark Peek #endif /* NLS_CATALOGS */ 265b2d5d167SMark Peek #endif /* NLS_BUGS */ 266c80476e4SDavid E. O'Brien #ifdef YPBUGS 267c80476e4SDavid E. O'Brien /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 268c80476e4SDavid E. O'Brien fix_yp_bugs(); 269c80476e4SDavid E. O'Brien #endif /* YPBUGS */ 27045e5710bSMark Peek num_files = NOFILE; 27145e5710bSMark Peek for (f = 0; f < num_files; f++) 272c80476e4SDavid E. O'Brien if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 273c80476e4SDavid E. O'Brien f != FSHTTY 274c80476e4SDavid E. O'Brien #ifdef MALLOC_TRACE 275c80476e4SDavid E. O'Brien && f != 25 276c80476e4SDavid E. O'Brien #endif /* MALLOC_TRACE */ 277cc698b49SBrooks Davis #ifdef S_ISSOCK 278cc698b49SBrooks Davis /* NSS modules (e.g. Linux nss_ldap) might keep sockets open. 279cc698b49SBrooks Davis * If we close such a socket, both the NSS module and tcsh think 280cc698b49SBrooks Davis * they "own" the descriptor. 281cc698b49SBrooks Davis * 282cc698b49SBrooks Davis * Not closing sockets does not make the cleanup use of closem() 283cc698b49SBrooks Davis * less reliable because tcsh never creates sockets. 284cc698b49SBrooks Davis */ 285cc698b49SBrooks Davis && fstat(f, &st) == 0 && !S_ISSOCK(st.st_mode) 286cc698b49SBrooks Davis #endif 287c80476e4SDavid E. O'Brien ) 288c80476e4SDavid E. O'Brien { 28945e5710bSMark Peek xclose(f); 290c80476e4SDavid E. O'Brien #ifdef NISPLUS 291c80476e4SDavid E. O'Brien if (f < 3) 29245e5710bSMark Peek (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 293c80476e4SDavid E. O'Brien #endif /* NISPLUS */ 294c80476e4SDavid E. O'Brien } 295b2d5d167SMark Peek #ifdef NLS_BUGS 296b2d5d167SMark Peek #ifdef NLS_CATALOGS 297b2d5d167SMark Peek nlsinit(); 298b2d5d167SMark Peek #endif /* NLS_CATALOGS */ 299b2d5d167SMark Peek #endif /* NLS_BUGS */ 300c80476e4SDavid E. O'Brien } 301c80476e4SDavid E. O'Brien 302c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC 303c80476e4SDavid E. O'Brien /* 304c80476e4SDavid E. O'Brien * Close files before executing a file. 305c80476e4SDavid E. O'Brien * We could be MUCH more intelligent, since (on a version 7 system) 306c80476e4SDavid E. O'Brien * we need only close files here during a source, the other 307c80476e4SDavid E. O'Brien * shell fd's being in units 16-19 which are closed automatically! 308c80476e4SDavid E. O'Brien */ 309c80476e4SDavid E. O'Brien void 31045e5710bSMark Peek closech(void) 311c80476e4SDavid E. O'Brien { 31245e5710bSMark Peek int f, num_files; 313c80476e4SDavid E. O'Brien 314c80476e4SDavid E. O'Brien if (didcch) 315c80476e4SDavid E. O'Brien return; 316c80476e4SDavid E. O'Brien didcch = 1; 317c80476e4SDavid E. O'Brien SHIN = 0; 318c80476e4SDavid E. O'Brien SHOUT = 1; 319c80476e4SDavid E. O'Brien SHDIAG = 2; 320c80476e4SDavid E. O'Brien OLDSTD = 0; 321c80476e4SDavid E. O'Brien isoutatty = isatty(SHOUT); 322c80476e4SDavid E. O'Brien isdiagatty = isatty(SHDIAG); 32345e5710bSMark Peek num_files = NOFILE; 32445e5710bSMark Peek for (f = 3; f < num_files; f++) 32545e5710bSMark Peek xclose(f); 326c80476e4SDavid E. O'Brien } 327c80476e4SDavid E. O'Brien 328c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */ 329c80476e4SDavid E. O'Brien 330c80476e4SDavid E. O'Brien void 33145e5710bSMark Peek donefds(void) 332c80476e4SDavid E. O'Brien { 333c80476e4SDavid E. O'Brien 33445e5710bSMark Peek xclose(0); 33545e5710bSMark Peek xclose(1); 33645e5710bSMark Peek xclose(2); 337c80476e4SDavid E. O'Brien didfds = 0; 338c80476e4SDavid E. O'Brien #ifdef NISPLUS 339c80476e4SDavid E. O'Brien { 34045e5710bSMark Peek int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 34123338178SMark Peek (void)dcopy(fd, 1); 34223338178SMark Peek (void)dcopy(fd, 2); 34323338178SMark Peek (void)dmove(fd, 0); 344c80476e4SDavid E. O'Brien } 345c80476e4SDavid E. O'Brien #endif /*NISPLUS*/ 346c80476e4SDavid E. O'Brien } 347c80476e4SDavid E. O'Brien 348c80476e4SDavid E. O'Brien /* 349c80476e4SDavid E. O'Brien * Move descriptor i to j. 350c80476e4SDavid E. O'Brien * If j is -1 then we just want to get i to a safe place, 35123338178SMark Peek * i.e. to a unit > FSAFE. This also happens in dcopy. 352c80476e4SDavid E. O'Brien */ 353c80476e4SDavid E. O'Brien int 35445e5710bSMark Peek dmove(int i, int j) 355c80476e4SDavid E. O'Brien { 356c80476e4SDavid E. O'Brien 357c80476e4SDavid E. O'Brien if (i == j || i < 0) 358c80476e4SDavid E. O'Brien return (i); 35923338178SMark Peek #ifdef HAVE_DUP2 360c80476e4SDavid E. O'Brien if (j >= 0) { 36145e5710bSMark Peek (void) xdup2(i, j); 362c80476e4SDavid E. O'Brien if (j != i) 36345e5710bSMark Peek xclose(i); 364c80476e4SDavid E. O'Brien return (j); 365c80476e4SDavid E. O'Brien } 366c80476e4SDavid E. O'Brien #endif 367c80476e4SDavid E. O'Brien j = dcopy(i, j); 368c80476e4SDavid E. O'Brien if (j != i) 36945e5710bSMark Peek xclose(i); 370c80476e4SDavid E. O'Brien return (j); 371c80476e4SDavid E. O'Brien } 372c80476e4SDavid E. O'Brien 373c80476e4SDavid E. O'Brien int 37445e5710bSMark Peek dcopy(int i, int j) 375c80476e4SDavid E. O'Brien { 376c80476e4SDavid E. O'Brien 37723338178SMark Peek if (i == j || i < 0 || (j < 0 && i > FSAFE)) 378c80476e4SDavid E. O'Brien return (i); 379c80476e4SDavid E. O'Brien if (j >= 0) { 38023338178SMark Peek #ifdef HAVE_DUP2 38145e5710bSMark Peek (void) xdup2(i, j); 382c80476e4SDavid E. O'Brien return (j); 383c80476e4SDavid E. O'Brien #else 38445e5710bSMark Peek xclose(j); 385c80476e4SDavid E. O'Brien #endif 386c80476e4SDavid E. O'Brien } 387c80476e4SDavid E. O'Brien return (renum(i, j)); 388c80476e4SDavid E. O'Brien } 389c80476e4SDavid E. O'Brien 390c80476e4SDavid E. O'Brien static int 39145e5710bSMark Peek renum(int i, int j) 392c80476e4SDavid E. O'Brien { 39323338178SMark Peek int k = dup(i); 394c80476e4SDavid E. O'Brien 395c80476e4SDavid E. O'Brien if (k < 0) 396c80476e4SDavid E. O'Brien return (-1); 39723338178SMark Peek if (j == -1 && k > FSAFE) 398c80476e4SDavid E. O'Brien return (k); 399c80476e4SDavid E. O'Brien if (k != j) { 400c80476e4SDavid E. O'Brien j = renum(k, j); 40145e5710bSMark Peek xclose(k); 402c80476e4SDavid E. O'Brien return (j); 403c80476e4SDavid E. O'Brien } 404c80476e4SDavid E. O'Brien return (k); 405c80476e4SDavid E. O'Brien } 406c80476e4SDavid E. O'Brien 407c80476e4SDavid E. O'Brien /* 408c80476e4SDavid E. O'Brien * Left shift a command argument list, discarding 409c80476e4SDavid E. O'Brien * the first c arguments. Used in "shift" commands 410c80476e4SDavid E. O'Brien * as well as by commands like "repeat". 411c80476e4SDavid E. O'Brien */ 412c80476e4SDavid E. O'Brien void 41345e5710bSMark Peek lshift(Char **v, int c) 414c80476e4SDavid E. O'Brien { 41523338178SMark Peek Char **u; 416c80476e4SDavid E. O'Brien 417c80476e4SDavid E. O'Brien for (u = v; *u && --c >= 0; u++) 41845e5710bSMark Peek xfree(*u); 419c80476e4SDavid E. O'Brien (void) blkcpy(v, u); 420c80476e4SDavid E. O'Brien } 421c80476e4SDavid E. O'Brien 422c80476e4SDavid E. O'Brien int 42345e5710bSMark Peek number(Char *cp) 424c80476e4SDavid E. O'Brien { 425c80476e4SDavid E. O'Brien if (!cp) 426c80476e4SDavid E. O'Brien return (0); 427c80476e4SDavid E. O'Brien if (*cp == '-') { 428c80476e4SDavid E. O'Brien cp++; 429c80476e4SDavid E. O'Brien if (!Isdigit(*cp)) 430c80476e4SDavid E. O'Brien return (0); 431c80476e4SDavid E. O'Brien cp++; 432c80476e4SDavid E. O'Brien } 433c80476e4SDavid E. O'Brien while (*cp && Isdigit(*cp)) 434c80476e4SDavid E. O'Brien cp++; 435c80476e4SDavid E. O'Brien return (*cp == 0); 436c80476e4SDavid E. O'Brien } 437c80476e4SDavid E. O'Brien 438c80476e4SDavid E. O'Brien Char ** 43945e5710bSMark Peek copyblk(Char **v) 440c80476e4SDavid E. O'Brien { 44145e5710bSMark Peek Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **)); 442c80476e4SDavid E. O'Brien 443c80476e4SDavid E. O'Brien return (blkcpy(nv, v)); 444c80476e4SDavid E. O'Brien } 445c80476e4SDavid E. O'Brien 446c80476e4SDavid E. O'Brien char * 44745e5710bSMark Peek strend(const char *cp) 448c80476e4SDavid E. O'Brien { 449c80476e4SDavid E. O'Brien if (!cp) 45045e5710bSMark Peek return ((char *)(intptr_t)cp); 451c80476e4SDavid E. O'Brien while (*cp) 452c80476e4SDavid E. O'Brien cp++; 45345e5710bSMark Peek return ((char *)(intptr_t)cp); 454c80476e4SDavid E. O'Brien } 455c80476e4SDavid E. O'Brien 456c80476e4SDavid E. O'Brien Char * 45745e5710bSMark Peek strip(Char *cp) 458c80476e4SDavid E. O'Brien { 45923338178SMark Peek Char *dp = cp; 460c80476e4SDavid E. O'Brien 461c80476e4SDavid E. O'Brien if (!cp) 462c80476e4SDavid E. O'Brien return (cp); 46319d2e3deSDmitry Chagin while (*dp != '\0') { 46419d2e3deSDmitry Chagin #if INVALID_BYTE != 0 46519d2e3deSDmitry Chagin if ((*dp & INVALID_BYTE) != INVALID_BYTE) /* *dp < INVALID_BYTE */ 46619d2e3deSDmitry Chagin #endif 46719d2e3deSDmitry Chagin *dp &= TRIM; 46819d2e3deSDmitry Chagin dp++; 46919d2e3deSDmitry Chagin } 470c80476e4SDavid E. O'Brien return (cp); 471c80476e4SDavid E. O'Brien } 472c80476e4SDavid E. O'Brien 473c80476e4SDavid E. O'Brien Char * 47445e5710bSMark Peek quote(Char *cp) 475c80476e4SDavid E. O'Brien { 47623338178SMark Peek Char *dp = cp; 477c80476e4SDavid E. O'Brien 478c80476e4SDavid E. O'Brien if (!cp) 479c80476e4SDavid E. O'Brien return (cp); 48019d2e3deSDmitry Chagin while (*dp != '\0') { 48119d2e3deSDmitry Chagin #ifdef WIDE_STRINGS 48219d2e3deSDmitry Chagin if ((*dp & 0xffffff80) == 0) /* *dp < 0x80 */ 48319d2e3deSDmitry Chagin #elif defined SHORT_STRINGS 48419d2e3deSDmitry Chagin if ((*dp & 0xff80) == 0) /* *dp < 0x80 */ 48519d2e3deSDmitry Chagin #else 48619d2e3deSDmitry Chagin if ((*dp & 0x80) == 0) /* *dp < 0x80 */ 48719d2e3deSDmitry Chagin #endif 48819d2e3deSDmitry Chagin *dp |= QUOTE; 48919d2e3deSDmitry Chagin dp++; 49019d2e3deSDmitry Chagin } 491c80476e4SDavid E. O'Brien return (cp); 492c80476e4SDavid E. O'Brien } 493c80476e4SDavid E. O'Brien 49445e5710bSMark Peek const Char * 49545e5710bSMark Peek quote_meta(struct Strbuf *buf, const Char *s) 496c80476e4SDavid E. O'Brien { 49745e5710bSMark Peek buf->len = 0; 498c80476e4SDavid E. O'Brien while (*s != '\0') { 499c80476e4SDavid E. O'Brien if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 50045e5710bSMark Peek Strbuf_append1(buf, '\\'); 50145e5710bSMark Peek Strbuf_append1(buf, *s++); 502c80476e4SDavid E. O'Brien } 50345e5710bSMark Peek Strbuf_terminate(buf); 50445e5710bSMark Peek return buf->s; 505c80476e4SDavid E. O'Brien } 506c80476e4SDavid E. O'Brien 507c80476e4SDavid E. O'Brien void 50845e5710bSMark Peek udvar(Char *name) 509c80476e4SDavid E. O'Brien { 510c80476e4SDavid E. O'Brien setname(short2str(name)); 511c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_UNDVAR); 512c80476e4SDavid E. O'Brien } 513c80476e4SDavid E. O'Brien 514c80476e4SDavid E. O'Brien int 51545e5710bSMark Peek prefix(const Char *sub, const Char *str) 516c80476e4SDavid E. O'Brien { 517c80476e4SDavid E. O'Brien 518c80476e4SDavid E. O'Brien for (;;) { 519c80476e4SDavid E. O'Brien if (*sub == 0) 520c80476e4SDavid E. O'Brien return (1); 521c80476e4SDavid E. O'Brien if (*str == 0) 522c80476e4SDavid E. O'Brien return (0); 523c80476e4SDavid E. O'Brien if ((*sub++ & TRIM) != (*str++ & TRIM)) 524c80476e4SDavid E. O'Brien return (0); 525c80476e4SDavid E. O'Brien } 526c80476e4SDavid E. O'Brien } 52745e5710bSMark Peek #ifndef WINNT_NATIVE 52845e5710bSMark Peek char * 52945e5710bSMark Peek areadlink(const char *path) 53045e5710bSMark Peek { 53145e5710bSMark Peek char *buf; 53245e5710bSMark Peek size_t size; 53345e5710bSMark Peek ssize_t res; 534*5224c2a3SDmitry Chagin #ifdef __IBMC__ 535*5224c2a3SDmitry Chagin /* 536*5224c2a3SDmitry Chagin * Prevent infinite recursion. Someone should tell me how to expand 537*5224c2a3SDmitry Chagin * these... 538*5224c2a3SDmitry Chagin */ 539*5224c2a3SDmitry Chagin size_t i; 540*5224c2a3SDmitry Chagin static const char *vars[] = { 541*5224c2a3SDmitry Chagin "/$VERSION", 542*5224c2a3SDmitry Chagin "/$SYSNAME", 543*5224c2a3SDmitry Chagin "/$SYSSYMR", 544*5224c2a3SDmitry Chagin "/$SYSSYMA", 545*5224c2a3SDmitry Chagin }; 546*5224c2a3SDmitry Chagin for (i = 0; i < sizeof(vars) / sizeof(vars[0]); i++) { 547*5224c2a3SDmitry Chagin if (strcmp(vars[i], path) == 0) { 548*5224c2a3SDmitry Chagin return NULL; 549*5224c2a3SDmitry Chagin } 550*5224c2a3SDmitry Chagin } 551*5224c2a3SDmitry Chagin #endif 552*5224c2a3SDmitry Chagin 55345e5710bSMark Peek 55445e5710bSMark Peek size = MAXPATHLEN + 1; 55545e5710bSMark Peek buf = xmalloc(size); 55645e5710bSMark Peek while ((size_t)(res = readlink(path, buf, size)) == size) { 55745e5710bSMark Peek size *= 2; 55845e5710bSMark Peek buf = xrealloc(buf, size); 55945e5710bSMark Peek } 56045e5710bSMark Peek if (res == -1) { 56145e5710bSMark Peek int err; 56245e5710bSMark Peek 56345e5710bSMark Peek err = errno; 56445e5710bSMark Peek xfree(buf); 56545e5710bSMark Peek errno = err; 56645e5710bSMark Peek return NULL; 56745e5710bSMark Peek } 56845e5710bSMark Peek buf[res] = '\0'; 56945e5710bSMark Peek return xrealloc(buf, res + 1); 57045e5710bSMark Peek } 57145e5710bSMark Peek #endif /*!WINNT_NATIVE*/ 57245e5710bSMark Peek 57345e5710bSMark Peek void 57445e5710bSMark Peek xclose(int fildes) 57545e5710bSMark Peek { 57645e5710bSMark Peek if (fildes < 0) 57745e5710bSMark Peek return; 57845e5710bSMark Peek while (close(fildes) == -1 && errno == EINTR) 57919d2e3deSDmitry Chagin if (handle_pending_signals()) 58019d2e3deSDmitry Chagin break; 58145e5710bSMark Peek } 58245e5710bSMark Peek 58345e5710bSMark Peek void 58445e5710bSMark Peek xclosedir(DIR *dirp) 58545e5710bSMark Peek { 58645e5710bSMark Peek while (closedir(dirp) == -1 && errno == EINTR) 58719d2e3deSDmitry Chagin if (handle_pending_signals()) 58819d2e3deSDmitry Chagin break; 58945e5710bSMark Peek } 59045e5710bSMark Peek 59145e5710bSMark Peek int 59245e5710bSMark Peek xcreat(const char *path, mode_t mode) 59345e5710bSMark Peek { 59445e5710bSMark Peek int res; 59545e5710bSMark Peek 59645e5710bSMark Peek while ((res = creat(path, mode)) == -1 && errno == EINTR) 59719d2e3deSDmitry Chagin if (handle_pending_signals()) 59819d2e3deSDmitry Chagin break; 59945e5710bSMark Peek return res; 60045e5710bSMark Peek } 60145e5710bSMark Peek 60245e5710bSMark Peek #ifdef HAVE_DUP2 60345e5710bSMark Peek static int 60445e5710bSMark Peek xdup2(int fildes, int fildes2) 60545e5710bSMark Peek { 60645e5710bSMark Peek int res; 60745e5710bSMark Peek 60845e5710bSMark Peek while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR) 60919d2e3deSDmitry Chagin if (handle_pending_signals()) 61019d2e3deSDmitry Chagin break; 61145e5710bSMark Peek return res; 61245e5710bSMark Peek } 61345e5710bSMark Peek #endif 61445e5710bSMark Peek 61545e5710bSMark Peek struct group * 61645e5710bSMark Peek xgetgrgid(gid_t xgid) 61745e5710bSMark Peek { 61845e5710bSMark Peek struct group *res; 61945e5710bSMark Peek 62045e5710bSMark Peek errno = 0; 62145e5710bSMark Peek while ((res = getgrgid(xgid)) == NULL && errno == EINTR) { 62219d2e3deSDmitry Chagin if (handle_pending_signals()) 62319d2e3deSDmitry Chagin break; 62445e5710bSMark Peek errno = 0; 62545e5710bSMark Peek } 62645e5710bSMark Peek return res; 62745e5710bSMark Peek } 62845e5710bSMark Peek 62945e5710bSMark Peek struct passwd * 63045e5710bSMark Peek xgetpwnam(const char *name) 63145e5710bSMark Peek { 63245e5710bSMark Peek struct passwd *res; 63345e5710bSMark Peek 63445e5710bSMark Peek errno = 0; 63545e5710bSMark Peek while ((res = getpwnam(name)) == NULL && errno == EINTR) { 63619d2e3deSDmitry Chagin if (handle_pending_signals()) 63719d2e3deSDmitry Chagin break; 63845e5710bSMark Peek errno = 0; 63945e5710bSMark Peek } 64045e5710bSMark Peek return res; 64145e5710bSMark Peek } 64245e5710bSMark Peek 64345e5710bSMark Peek struct passwd * 64445e5710bSMark Peek xgetpwuid(uid_t xuid) 64545e5710bSMark Peek { 64645e5710bSMark Peek struct passwd *res; 64745e5710bSMark Peek 64845e5710bSMark Peek errno = 0; 64945e5710bSMark Peek while ((res = getpwuid(xuid)) == NULL && errno == EINTR) { 65019d2e3deSDmitry Chagin if (handle_pending_signals()) 65119d2e3deSDmitry Chagin break; 65245e5710bSMark Peek errno = 0; 65345e5710bSMark Peek } 65445e5710bSMark Peek return res; 65545e5710bSMark Peek } 65645e5710bSMark Peek 65745e5710bSMark Peek int 65845e5710bSMark Peek xopen(const char *path, int oflag, ...) 65945e5710bSMark Peek { 66045e5710bSMark Peek int res; 66145e5710bSMark Peek 66245e5710bSMark Peek if ((oflag & O_CREAT) == 0) { 66345e5710bSMark Peek while ((res = open(path, oflag)) == -1 && errno == EINTR) 66419d2e3deSDmitry Chagin if (handle_pending_signals()) 66519d2e3deSDmitry Chagin break; 66645e5710bSMark Peek } else { 66745e5710bSMark Peek va_list ap; 66845e5710bSMark Peek mode_t mode; 66945e5710bSMark Peek 67045e5710bSMark Peek va_start(ap, oflag); 67145e5710bSMark Peek /* "int" should actually be "mode_t after default argument 67245e5710bSMark Peek promotions". "int" is the best guess we have, "mode_t" used to be 67345e5710bSMark Peek "unsigned short", which we obviously can't use. */ 67445e5710bSMark Peek mode = va_arg(ap, int); 67545e5710bSMark Peek va_end(ap); 67645e5710bSMark Peek while ((res = open(path, oflag, mode)) == -1 && errno == EINTR) 67719d2e3deSDmitry Chagin if (handle_pending_signals()) 67819d2e3deSDmitry Chagin break; 67945e5710bSMark Peek } 68045e5710bSMark Peek return res; 68145e5710bSMark Peek } 68245e5710bSMark Peek 68345e5710bSMark Peek ssize_t 68445e5710bSMark Peek xread(int fildes, void *buf, size_t nbyte) 68545e5710bSMark Peek { 686cc698b49SBrooks Davis ssize_t res = -1; 68745e5710bSMark Peek 68845e5710bSMark Peek /* This is where we will be blocked most of the time, so handle signals 68945e5710bSMark Peek that didn't interrupt any system call. */ 69045e5710bSMark Peek do 69119d2e3deSDmitry Chagin if (handle_pending_signals()) 69219d2e3deSDmitry Chagin break; 69345e5710bSMark Peek while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR); 69445e5710bSMark Peek return res; 69545e5710bSMark Peek } 69645e5710bSMark Peek 69745e5710bSMark Peek #ifdef POSIX 69845e5710bSMark Peek int 69945e5710bSMark Peek xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p) 70045e5710bSMark Peek { 70145e5710bSMark Peek int res; 70245e5710bSMark Peek 70345e5710bSMark Peek while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 && 70445e5710bSMark Peek errno == EINTR) 70519d2e3deSDmitry Chagin if (handle_pending_signals()) 70619d2e3deSDmitry Chagin break; 70745e5710bSMark Peek return res; 70845e5710bSMark Peek } 70945e5710bSMark Peek #endif 71045e5710bSMark Peek 71145e5710bSMark Peek ssize_t 71245e5710bSMark Peek xwrite(int fildes, const void *buf, size_t nbyte) 71345e5710bSMark Peek { 714cc698b49SBrooks Davis ssize_t res = -1; 71545e5710bSMark Peek 71645e5710bSMark Peek /* This is where we will be blocked most of the time, so handle signals 71745e5710bSMark Peek that didn't interrupt any system call. */ 71845e5710bSMark Peek do 71919d2e3deSDmitry Chagin if (handle_pending_signals()) 72019d2e3deSDmitry Chagin break; 72145e5710bSMark Peek while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR); 72245e5710bSMark Peek return res; 72345e5710bSMark Peek } 724