145e5710bSMark Peek /* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.45 2006/10/14 17:57:21 christos Exp $ */ 2c80476e4SDavid E. O'Brien /* 3c80476e4SDavid E. O'Brien * sh.misc.c: Miscelaneous functions 4c80476e4SDavid E. O'Brien */ 5c80476e4SDavid E. O'Brien /*- 6c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California. 7c80476e4SDavid E. O'Brien * All rights reserved. 8c80476e4SDavid E. O'Brien * 9c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 10c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions 11c80476e4SDavid E. O'Brien * are met: 12c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 13c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 14c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 15c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 16c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 1729301572SMark Peek * 3. Neither the name of the University nor the names of its contributors 18c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software 19c80476e4SDavid E. O'Brien * without specific prior written permission. 20c80476e4SDavid E. O'Brien * 21c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c80476e4SDavid E. O'Brien * SUCH DAMAGE. 32c80476e4SDavid E. O'Brien */ 33c80476e4SDavid E. O'Brien #include "sh.h" 34c80476e4SDavid E. O'Brien 3545e5710bSMark Peek RCSID("$tcsh: sh.misc.c,v 3.45 2006/10/14 17:57:21 christos Exp $") 36c80476e4SDavid E. O'Brien 3745e5710bSMark Peek static int renum (int, int); 3845e5710bSMark Peek static Char **blkend (Char **); 3945e5710bSMark Peek static Char **blkcat (Char **, Char **); 4045e5710bSMark Peek static int xdup2 (int, int); 41c80476e4SDavid E. O'Brien 42c80476e4SDavid E. O'Brien /* 43c80476e4SDavid E. O'Brien * C Shell 44c80476e4SDavid E. O'Brien */ 45c80476e4SDavid E. O'Brien 46c80476e4SDavid E. O'Brien int 4745e5710bSMark Peek any(const char *s, Char c) 48c80476e4SDavid E. O'Brien { 49c80476e4SDavid E. O'Brien if (!s) 50c80476e4SDavid E. O'Brien return (0); /* Check for nil pointer */ 51c80476e4SDavid E. O'Brien while (*s) 5223338178SMark Peek if ((Char)*s++ == c) 53c80476e4SDavid E. O'Brien return (1); 54c80476e4SDavid E. O'Brien return (0); 55c80476e4SDavid E. O'Brien } 56c80476e4SDavid E. O'Brien 57c80476e4SDavid E. O'Brien void 5845e5710bSMark Peek setzero(void *p, size_t size) 59c80476e4SDavid E. O'Brien { 6045e5710bSMark Peek memset(p, 0, size); 61c80476e4SDavid E. O'Brien } 62c80476e4SDavid E. O'Brien 63c80476e4SDavid E. O'Brien char * 6445e5710bSMark Peek strnsave(const char *s, size_t len) 65c80476e4SDavid E. O'Brien { 6645e5710bSMark Peek char *r; 6745e5710bSMark Peek 6845e5710bSMark Peek r = xmalloc(len + 1); 6945e5710bSMark Peek memcpy(r, s, len); 7045e5710bSMark Peek r[len] = '\0'; 7145e5710bSMark Peek return r; 7245e5710bSMark Peek } 7345e5710bSMark Peek 7445e5710bSMark Peek char * 7545e5710bSMark Peek strsave(const char *s) 7645e5710bSMark Peek { 7745e5710bSMark Peek char *r; 7845e5710bSMark Peek size_t size; 79c80476e4SDavid E. O'Brien 80c80476e4SDavid E. O'Brien if (s == NULL) 8123338178SMark Peek s = ""; 8245e5710bSMark Peek size = strlen(s) + 1; 8345e5710bSMark Peek r = xmalloc(size); 8445e5710bSMark Peek memcpy(r, s, size); 8523338178SMark Peek return (r); 86c80476e4SDavid E. O'Brien } 87c80476e4SDavid E. O'Brien 88c80476e4SDavid E. O'Brien static Char ** 8945e5710bSMark Peek blkend(Char **up) 90c80476e4SDavid E. O'Brien { 91c80476e4SDavid E. O'Brien 92c80476e4SDavid E. O'Brien while (*up) 93c80476e4SDavid E. O'Brien up++; 94c80476e4SDavid E. O'Brien return (up); 95c80476e4SDavid E. O'Brien } 96c80476e4SDavid E. O'Brien 97c80476e4SDavid E. O'Brien 98c80476e4SDavid E. O'Brien void 9945e5710bSMark Peek blkpr(Char *const *av) 100c80476e4SDavid E. O'Brien { 101c80476e4SDavid E. O'Brien 102c80476e4SDavid E. O'Brien for (; *av; av++) { 103c80476e4SDavid E. O'Brien xprintf("%S", *av); 104c80476e4SDavid E. O'Brien if (av[1]) 105c80476e4SDavid E. O'Brien xprintf(" "); 106c80476e4SDavid E. O'Brien } 107c80476e4SDavid E. O'Brien } 108c80476e4SDavid E. O'Brien 10945e5710bSMark Peek Char * 11045e5710bSMark Peek blkexpand(Char *const *av) 111c80476e4SDavid E. O'Brien { 11245e5710bSMark Peek struct Strbuf buf = Strbuf_INIT; 11345e5710bSMark Peek 114c80476e4SDavid E. O'Brien for (; *av; av++) { 11545e5710bSMark Peek Strbuf_append(&buf, *av); 116c80476e4SDavid E. O'Brien if (av[1]) 11745e5710bSMark Peek Strbuf_append1(&buf, ' '); 118c80476e4SDavid E. O'Brien } 11945e5710bSMark Peek return Strbuf_finish(&buf); 120c80476e4SDavid E. O'Brien } 121c80476e4SDavid E. O'Brien 122c80476e4SDavid E. O'Brien int 12345e5710bSMark Peek blklen(Char **av) 124c80476e4SDavid E. O'Brien { 12523338178SMark Peek int i = 0; 126c80476e4SDavid E. O'Brien 127c80476e4SDavid E. O'Brien while (*av++) 128c80476e4SDavid E. O'Brien i++; 129c80476e4SDavid E. O'Brien return (i); 130c80476e4SDavid E. O'Brien } 131c80476e4SDavid E. O'Brien 132c80476e4SDavid E. O'Brien Char ** 13345e5710bSMark Peek blkcpy(Char **oav, Char **bv) 134c80476e4SDavid E. O'Brien { 13523338178SMark Peek Char **av = oav; 136c80476e4SDavid E. O'Brien 137c80476e4SDavid E. O'Brien while ((*av++ = *bv++) != NULL) 138c80476e4SDavid E. O'Brien continue; 139c80476e4SDavid E. O'Brien return (oav); 140c80476e4SDavid E. O'Brien } 141c80476e4SDavid E. O'Brien 142c80476e4SDavid E. O'Brien static Char ** 14345e5710bSMark Peek blkcat(Char **up, Char **vp) 144c80476e4SDavid E. O'Brien { 145c80476e4SDavid E. O'Brien 146c80476e4SDavid E. O'Brien (void) blkcpy(blkend(up), vp); 147c80476e4SDavid E. O'Brien return (up); 148c80476e4SDavid E. O'Brien } 149c80476e4SDavid E. O'Brien 150c80476e4SDavid E. O'Brien void 15145e5710bSMark Peek blkfree(Char **av0) 152c80476e4SDavid E. O'Brien { 15323338178SMark Peek Char **av = av0; 154c80476e4SDavid E. O'Brien 155c80476e4SDavid E. O'Brien if (!av0) 156c80476e4SDavid E. O'Brien return; 157c80476e4SDavid E. O'Brien for (; *av; av++) 15845e5710bSMark Peek xfree(*av); 15945e5710bSMark Peek xfree(av0); 16045e5710bSMark Peek } 16145e5710bSMark Peek 16245e5710bSMark Peek void 16345e5710bSMark Peek blk_cleanup(void *ptr) 16445e5710bSMark Peek { 16545e5710bSMark Peek blkfree(ptr); 16645e5710bSMark Peek } 16745e5710bSMark Peek 16845e5710bSMark Peek void 16945e5710bSMark Peek blk_indirect_cleanup(void *xptr) 17045e5710bSMark Peek { 17145e5710bSMark Peek Char ***ptr; 17245e5710bSMark Peek 17345e5710bSMark Peek ptr = xptr; 17445e5710bSMark Peek blkfree(*ptr); 17545e5710bSMark Peek xfree(ptr); 176c80476e4SDavid E. O'Brien } 177c80476e4SDavid E. O'Brien 178c80476e4SDavid E. O'Brien Char ** 17945e5710bSMark Peek saveblk(Char **v) 180c80476e4SDavid E. O'Brien { 18145e5710bSMark Peek Char **newv, **onewv; 18245e5710bSMark Peek 18345e5710bSMark Peek if (v == NULL) 18445e5710bSMark Peek return NULL; 18545e5710bSMark Peek 18645e5710bSMark Peek onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **)); 187c80476e4SDavid E. O'Brien 188c80476e4SDavid E. O'Brien while (*v) 189c80476e4SDavid E. O'Brien *newv++ = Strsave(*v++); 190c80476e4SDavid E. O'Brien return (onewv); 191c80476e4SDavid E. O'Brien } 192c80476e4SDavid E. O'Brien 19323338178SMark Peek #ifndef HAVE_STRSTR 194c80476e4SDavid E. O'Brien char * 19545e5710bSMark Peek strstr(const char *s, const char *t) 196c80476e4SDavid E. O'Brien { 197c80476e4SDavid E. O'Brien do { 19823338178SMark Peek const char *ss = s; 19923338178SMark Peek const char *tt = t; 200c80476e4SDavid E. O'Brien 201c80476e4SDavid E. O'Brien do 202c80476e4SDavid E. O'Brien if (*tt == '\0') 20345e5710bSMark Peek return (s); 204c80476e4SDavid E. O'Brien while (*ss++ == *tt++); 205c80476e4SDavid E. O'Brien } while (*s++ != '\0'); 206c80476e4SDavid E. O'Brien return (NULL); 207c80476e4SDavid E. O'Brien } 20823338178SMark Peek #endif /* !HAVE_STRSTR */ 209c80476e4SDavid E. O'Brien 210c80476e4SDavid E. O'Brien char * 21145e5710bSMark Peek strspl(const char *cp, const char *dp) 212c80476e4SDavid E. O'Brien { 213c80476e4SDavid E. O'Brien char *ep; 21423338178SMark Peek size_t cl, dl; 215c80476e4SDavid E. O'Brien 216c80476e4SDavid E. O'Brien if (!cp) 217c80476e4SDavid E. O'Brien cp = ""; 218c80476e4SDavid E. O'Brien if (!dp) 219c80476e4SDavid E. O'Brien dp = ""; 22023338178SMark Peek cl = strlen(cp); 22123338178SMark Peek dl = strlen(dp); 22245e5710bSMark Peek ep = xmalloc((cl + dl + 1) * sizeof(char)); 22323338178SMark Peek memcpy(ep, cp, cl); 22423338178SMark Peek memcpy(ep + cl, dp, dl + 1); 225c80476e4SDavid E. O'Brien return (ep); 226c80476e4SDavid E. O'Brien } 227c80476e4SDavid E. O'Brien 228c80476e4SDavid E. O'Brien Char ** 22945e5710bSMark Peek blkspl(Char **up, Char **vp) 230c80476e4SDavid E. O'Brien { 23145e5710bSMark Peek Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **)); 232c80476e4SDavid E. O'Brien 233c80476e4SDavid E. O'Brien (void) blkcpy(wp, up); 234c80476e4SDavid E. O'Brien return (blkcat(wp, vp)); 235c80476e4SDavid E. O'Brien } 236c80476e4SDavid E. O'Brien 237c80476e4SDavid E. O'Brien Char 23845e5710bSMark Peek lastchr(Char *cp) 239c80476e4SDavid E. O'Brien { 240c80476e4SDavid E. O'Brien 241c80476e4SDavid E. O'Brien if (!cp) 242c80476e4SDavid E. O'Brien return (0); 243c80476e4SDavid E. O'Brien if (!*cp) 244c80476e4SDavid E. O'Brien return (0); 245c80476e4SDavid E. O'Brien while (cp[1]) 246c80476e4SDavid E. O'Brien cp++; 247c80476e4SDavid E. O'Brien return (*cp); 248c80476e4SDavid E. O'Brien } 249c80476e4SDavid E. O'Brien 250c80476e4SDavid E. O'Brien /* 251c80476e4SDavid E. O'Brien * This routine is called after an error to close up 252c80476e4SDavid E. O'Brien * any units which may have been left open accidentally. 253c80476e4SDavid E. O'Brien */ 254c80476e4SDavid E. O'Brien void 25545e5710bSMark Peek closem(void) 256c80476e4SDavid E. O'Brien { 25745e5710bSMark Peek int f, num_files; 258c80476e4SDavid E. O'Brien 259b2d5d167SMark Peek #ifdef NLS_BUGS 260b2d5d167SMark Peek #ifdef NLS_CATALOGS 26123338178SMark Peek nlsclose(); 262b2d5d167SMark Peek #endif /* NLS_CATALOGS */ 263b2d5d167SMark Peek #endif /* NLS_BUGS */ 264c80476e4SDavid E. O'Brien #ifdef YPBUGS 265c80476e4SDavid E. O'Brien /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 266c80476e4SDavid E. O'Brien fix_yp_bugs(); 267c80476e4SDavid E. O'Brien #endif /* YPBUGS */ 26845e5710bSMark Peek num_files = NOFILE; 26945e5710bSMark Peek for (f = 0; f < num_files; f++) 270c80476e4SDavid E. O'Brien if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 271c80476e4SDavid E. O'Brien f != FSHTTY 272c80476e4SDavid E. O'Brien #ifdef MALLOC_TRACE 273c80476e4SDavid E. O'Brien && f != 25 274c80476e4SDavid E. O'Brien #endif /* MALLOC_TRACE */ 275c80476e4SDavid E. O'Brien ) 276c80476e4SDavid E. O'Brien { 27745e5710bSMark Peek xclose(f); 278c80476e4SDavid E. O'Brien #ifdef NISPLUS 279c80476e4SDavid E. O'Brien if(f < 3) 28045e5710bSMark Peek (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 281c80476e4SDavid E. O'Brien #endif /* NISPLUS */ 282c80476e4SDavid E. O'Brien } 283b2d5d167SMark Peek #ifdef NLS_BUGS 284b2d5d167SMark Peek #ifdef NLS_CATALOGS 285b2d5d167SMark Peek nlsinit(); 286b2d5d167SMark Peek #endif /* NLS_CATALOGS */ 287b2d5d167SMark Peek #endif /* NLS_BUGS */ 288c80476e4SDavid E. O'Brien } 289c80476e4SDavid E. O'Brien 290c80476e4SDavid E. O'Brien #ifndef CLOSE_ON_EXEC 291c80476e4SDavid E. O'Brien /* 292c80476e4SDavid E. O'Brien * Close files before executing a file. 293c80476e4SDavid E. O'Brien * We could be MUCH more intelligent, since (on a version 7 system) 294c80476e4SDavid E. O'Brien * we need only close files here during a source, the other 295c80476e4SDavid E. O'Brien * shell fd's being in units 16-19 which are closed automatically! 296c80476e4SDavid E. O'Brien */ 297c80476e4SDavid E. O'Brien void 29845e5710bSMark Peek closech(void) 299c80476e4SDavid E. O'Brien { 30045e5710bSMark Peek int f, num_files; 301c80476e4SDavid E. O'Brien 302c80476e4SDavid E. O'Brien if (didcch) 303c80476e4SDavid E. O'Brien return; 304c80476e4SDavid E. O'Brien didcch = 1; 305c80476e4SDavid E. O'Brien SHIN = 0; 306c80476e4SDavid E. O'Brien SHOUT = 1; 307c80476e4SDavid E. O'Brien SHDIAG = 2; 308c80476e4SDavid E. O'Brien OLDSTD = 0; 309c80476e4SDavid E. O'Brien isoutatty = isatty(SHOUT); 310c80476e4SDavid E. O'Brien isdiagatty = isatty(SHDIAG); 31145e5710bSMark Peek num_files = NOFILE; 31245e5710bSMark Peek for (f = 3; f < num_files; f++) 31345e5710bSMark Peek xclose(f); 314c80476e4SDavid E. O'Brien } 315c80476e4SDavid E. O'Brien 316c80476e4SDavid E. O'Brien #endif /* CLOSE_ON_EXEC */ 317c80476e4SDavid E. O'Brien 318c80476e4SDavid E. O'Brien void 31945e5710bSMark Peek donefds(void) 320c80476e4SDavid E. O'Brien { 321c80476e4SDavid E. O'Brien 32245e5710bSMark Peek xclose(0); 32345e5710bSMark Peek xclose(1); 32445e5710bSMark Peek xclose(2); 325c80476e4SDavid E. O'Brien didfds = 0; 326c80476e4SDavid E. O'Brien #ifdef NISPLUS 327c80476e4SDavid E. O'Brien { 32845e5710bSMark Peek int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 32923338178SMark Peek (void)dcopy(fd, 1); 33023338178SMark Peek (void)dcopy(fd, 2); 33123338178SMark Peek (void)dmove(fd, 0); 332c80476e4SDavid E. O'Brien } 333c80476e4SDavid E. O'Brien #endif /*NISPLUS*/ 334c80476e4SDavid E. O'Brien } 335c80476e4SDavid E. O'Brien 336c80476e4SDavid E. O'Brien /* 337c80476e4SDavid E. O'Brien * Move descriptor i to j. 338c80476e4SDavid E. O'Brien * If j is -1 then we just want to get i to a safe place, 33923338178SMark Peek * i.e. to a unit > FSAFE. This also happens in dcopy. 340c80476e4SDavid E. O'Brien */ 341c80476e4SDavid E. O'Brien int 34245e5710bSMark Peek dmove(int i, int j) 343c80476e4SDavid E. O'Brien { 344c80476e4SDavid E. O'Brien 345c80476e4SDavid E. O'Brien if (i == j || i < 0) 346c80476e4SDavid E. O'Brien return (i); 34723338178SMark Peek #ifdef HAVE_DUP2 348c80476e4SDavid E. O'Brien if (j >= 0) { 34945e5710bSMark Peek (void) xdup2(i, j); 350c80476e4SDavid E. O'Brien if (j != i) 35145e5710bSMark Peek xclose(i); 352c80476e4SDavid E. O'Brien return (j); 353c80476e4SDavid E. O'Brien } 354c80476e4SDavid E. O'Brien #endif 355c80476e4SDavid E. O'Brien j = dcopy(i, j); 356c80476e4SDavid E. O'Brien if (j != i) 35745e5710bSMark Peek xclose(i); 358c80476e4SDavid E. O'Brien return (j); 359c80476e4SDavid E. O'Brien } 360c80476e4SDavid E. O'Brien 361c80476e4SDavid E. O'Brien int 36245e5710bSMark Peek dcopy(int i, int j) 363c80476e4SDavid E. O'Brien { 364c80476e4SDavid E. O'Brien 36523338178SMark Peek if (i == j || i < 0 || (j < 0 && i > FSAFE)) 366c80476e4SDavid E. O'Brien return (i); 367c80476e4SDavid E. O'Brien if (j >= 0) { 36823338178SMark Peek #ifdef HAVE_DUP2 36945e5710bSMark Peek (void) xdup2(i, j); 370c80476e4SDavid E. O'Brien return (j); 371c80476e4SDavid E. O'Brien #else 37245e5710bSMark Peek xclose(j); 373c80476e4SDavid E. O'Brien #endif 374c80476e4SDavid E. O'Brien } 375c80476e4SDavid E. O'Brien return (renum(i, j)); 376c80476e4SDavid E. O'Brien } 377c80476e4SDavid E. O'Brien 378c80476e4SDavid E. O'Brien static int 37945e5710bSMark Peek renum(int i, int j) 380c80476e4SDavid E. O'Brien { 38123338178SMark Peek int k = dup(i); 382c80476e4SDavid E. O'Brien 383c80476e4SDavid E. O'Brien if (k < 0) 384c80476e4SDavid E. O'Brien return (-1); 38523338178SMark Peek if (j == -1 && k > FSAFE) 386c80476e4SDavid E. O'Brien return (k); 387c80476e4SDavid E. O'Brien if (k != j) { 388c80476e4SDavid E. O'Brien j = renum(k, j); 38945e5710bSMark Peek xclose(k); 390c80476e4SDavid E. O'Brien return (j); 391c80476e4SDavid E. O'Brien } 392c80476e4SDavid E. O'Brien return (k); 393c80476e4SDavid E. O'Brien } 394c80476e4SDavid E. O'Brien 395c80476e4SDavid E. O'Brien /* 396c80476e4SDavid E. O'Brien * Left shift a command argument list, discarding 397c80476e4SDavid E. O'Brien * the first c arguments. Used in "shift" commands 398c80476e4SDavid E. O'Brien * as well as by commands like "repeat". 399c80476e4SDavid E. O'Brien */ 400c80476e4SDavid E. O'Brien void 40145e5710bSMark Peek lshift(Char **v, int c) 402c80476e4SDavid E. O'Brien { 40323338178SMark Peek Char **u; 404c80476e4SDavid E. O'Brien 405c80476e4SDavid E. O'Brien for (u = v; *u && --c >= 0; u++) 40645e5710bSMark Peek xfree(*u); 407c80476e4SDavid E. O'Brien (void) blkcpy(v, u); 408c80476e4SDavid E. O'Brien } 409c80476e4SDavid E. O'Brien 410c80476e4SDavid E. O'Brien int 41145e5710bSMark Peek number(Char *cp) 412c80476e4SDavid E. O'Brien { 413c80476e4SDavid E. O'Brien if (!cp) 414c80476e4SDavid E. O'Brien return (0); 415c80476e4SDavid E. O'Brien if (*cp == '-') { 416c80476e4SDavid E. O'Brien cp++; 417c80476e4SDavid E. O'Brien if (!Isdigit(*cp)) 418c80476e4SDavid E. O'Brien return (0); 419c80476e4SDavid E. O'Brien cp++; 420c80476e4SDavid E. O'Brien } 421c80476e4SDavid E. O'Brien while (*cp && Isdigit(*cp)) 422c80476e4SDavid E. O'Brien cp++; 423c80476e4SDavid E. O'Brien return (*cp == 0); 424c80476e4SDavid E. O'Brien } 425c80476e4SDavid E. O'Brien 426c80476e4SDavid E. O'Brien Char ** 42745e5710bSMark Peek copyblk(Char **v) 428c80476e4SDavid E. O'Brien { 42945e5710bSMark Peek Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **)); 430c80476e4SDavid E. O'Brien 431c80476e4SDavid E. O'Brien return (blkcpy(nv, v)); 432c80476e4SDavid E. O'Brien } 433c80476e4SDavid E. O'Brien 434c80476e4SDavid E. O'Brien char * 43545e5710bSMark Peek strend(const char *cp) 436c80476e4SDavid E. O'Brien { 437c80476e4SDavid E. O'Brien if (!cp) 43845e5710bSMark Peek return ((char *)(intptr_t)cp); 439c80476e4SDavid E. O'Brien while (*cp) 440c80476e4SDavid E. O'Brien cp++; 44145e5710bSMark Peek return ((char *)(intptr_t)cp); 442c80476e4SDavid E. O'Brien } 443c80476e4SDavid E. O'Brien 444c80476e4SDavid E. O'Brien Char * 44545e5710bSMark Peek strip(Char *cp) 446c80476e4SDavid E. O'Brien { 44723338178SMark Peek Char *dp = cp; 448c80476e4SDavid E. O'Brien 449c80476e4SDavid E. O'Brien if (!cp) 450c80476e4SDavid E. O'Brien return (cp); 451c80476e4SDavid E. O'Brien while ((*dp++ &= TRIM) != '\0') 452c80476e4SDavid E. O'Brien continue; 453c80476e4SDavid E. O'Brien return (cp); 454c80476e4SDavid E. O'Brien } 455c80476e4SDavid E. O'Brien 456c80476e4SDavid E. O'Brien Char * 45745e5710bSMark Peek quote(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); 463c80476e4SDavid E. O'Brien while (*dp != '\0') 464c80476e4SDavid E. O'Brien *dp++ |= QUOTE; 465c80476e4SDavid E. O'Brien return (cp); 466c80476e4SDavid E. O'Brien } 467c80476e4SDavid E. O'Brien 46845e5710bSMark Peek const Char * 46945e5710bSMark Peek quote_meta(struct Strbuf *buf, const Char *s) 470c80476e4SDavid E. O'Brien { 47145e5710bSMark Peek buf->len = 0; 472c80476e4SDavid E. O'Brien while (*s != '\0') { 473c80476e4SDavid E. O'Brien if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 47445e5710bSMark Peek Strbuf_append1(buf, '\\'); 47545e5710bSMark Peek Strbuf_append1(buf, *s++); 476c80476e4SDavid E. O'Brien } 47745e5710bSMark Peek Strbuf_terminate(buf); 47845e5710bSMark Peek return buf->s; 479c80476e4SDavid E. O'Brien } 480c80476e4SDavid E. O'Brien 481c80476e4SDavid E. O'Brien void 48245e5710bSMark Peek udvar(Char *name) 483c80476e4SDavid E. O'Brien { 484c80476e4SDavid E. O'Brien setname(short2str(name)); 485c80476e4SDavid E. O'Brien stderror(ERR_NAME | ERR_UNDVAR); 486c80476e4SDavid E. O'Brien } 487c80476e4SDavid E. O'Brien 488c80476e4SDavid E. O'Brien int 48945e5710bSMark Peek prefix(const Char *sub, const Char *str) 490c80476e4SDavid E. O'Brien { 491c80476e4SDavid E. O'Brien 492c80476e4SDavid E. O'Brien for (;;) { 493c80476e4SDavid E. O'Brien if (*sub == 0) 494c80476e4SDavid E. O'Brien return (1); 495c80476e4SDavid E. O'Brien if (*str == 0) 496c80476e4SDavid E. O'Brien return (0); 497c80476e4SDavid E. O'Brien if ((*sub++ & TRIM) != (*str++ & TRIM)) 498c80476e4SDavid E. O'Brien return (0); 499c80476e4SDavid E. O'Brien } 500c80476e4SDavid E. O'Brien } 50145e5710bSMark Peek #ifndef WINNT_NATIVE 50245e5710bSMark Peek char * 50345e5710bSMark Peek areadlink(const char *path) 50445e5710bSMark Peek { 50545e5710bSMark Peek char *buf; 50645e5710bSMark Peek size_t size; 50745e5710bSMark Peek ssize_t res; 50845e5710bSMark Peek 50945e5710bSMark Peek size = MAXPATHLEN + 1; 51045e5710bSMark Peek buf = xmalloc(size); 51145e5710bSMark Peek while ((size_t)(res = readlink(path, buf, size)) == size) { 51245e5710bSMark Peek size *= 2; 51345e5710bSMark Peek buf = xrealloc(buf, size); 51445e5710bSMark Peek } 51545e5710bSMark Peek if (res == -1) { 51645e5710bSMark Peek int err; 51745e5710bSMark Peek 51845e5710bSMark Peek err = errno; 51945e5710bSMark Peek xfree(buf); 52045e5710bSMark Peek errno = err; 52145e5710bSMark Peek return NULL; 52245e5710bSMark Peek } 52345e5710bSMark Peek buf[res] = '\0'; 52445e5710bSMark Peek return xrealloc(buf, res + 1); 52545e5710bSMark Peek } 52645e5710bSMark Peek #endif /*!WINNT_NATIVE*/ 52745e5710bSMark Peek 52845e5710bSMark Peek void 52945e5710bSMark Peek xclose(int fildes) 53045e5710bSMark Peek { 53145e5710bSMark Peek if (fildes < 0) 53245e5710bSMark Peek return; 53345e5710bSMark Peek while (close(fildes) == -1 && errno == EINTR) 53445e5710bSMark Peek handle_pending_signals(); 53545e5710bSMark Peek } 53645e5710bSMark Peek 53745e5710bSMark Peek void 53845e5710bSMark Peek xclosedir(DIR *dirp) 53945e5710bSMark Peek { 54045e5710bSMark Peek while (closedir(dirp) == -1 && errno == EINTR) 54145e5710bSMark Peek handle_pending_signals(); 54245e5710bSMark Peek } 54345e5710bSMark Peek 54445e5710bSMark Peek int 54545e5710bSMark Peek xcreat(const char *path, mode_t mode) 54645e5710bSMark Peek { 54745e5710bSMark Peek int res; 54845e5710bSMark Peek 54945e5710bSMark Peek while ((res = creat(path, mode)) == -1 && errno == EINTR) 55045e5710bSMark Peek handle_pending_signals(); 55145e5710bSMark Peek return res; 55245e5710bSMark Peek } 55345e5710bSMark Peek 55445e5710bSMark Peek #ifdef HAVE_DUP2 55545e5710bSMark Peek static int 55645e5710bSMark Peek xdup2(int fildes, int fildes2) 55745e5710bSMark Peek { 55845e5710bSMark Peek int res; 55945e5710bSMark Peek 56045e5710bSMark Peek while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR) 56145e5710bSMark Peek handle_pending_signals(); 56245e5710bSMark Peek return res; 56345e5710bSMark Peek } 56445e5710bSMark Peek #endif 56545e5710bSMark Peek 56645e5710bSMark Peek struct group * 56745e5710bSMark Peek xgetgrgid(gid_t xgid) 56845e5710bSMark Peek { 56945e5710bSMark Peek struct group *res; 57045e5710bSMark Peek 57145e5710bSMark Peek errno = 0; 57245e5710bSMark Peek while ((res = getgrgid(xgid)) == NULL && errno == EINTR) { 57345e5710bSMark Peek handle_pending_signals(); 57445e5710bSMark Peek errno = 0; 57545e5710bSMark Peek } 57645e5710bSMark Peek return res; 57745e5710bSMark Peek } 57845e5710bSMark Peek 57945e5710bSMark Peek struct passwd * 58045e5710bSMark Peek xgetpwnam(const char *name) 58145e5710bSMark Peek { 58245e5710bSMark Peek struct passwd *res; 58345e5710bSMark Peek 58445e5710bSMark Peek errno = 0; 58545e5710bSMark Peek while ((res = getpwnam(name)) == NULL && errno == EINTR) { 58645e5710bSMark Peek handle_pending_signals(); 58745e5710bSMark Peek errno = 0; 58845e5710bSMark Peek } 58945e5710bSMark Peek return res; 59045e5710bSMark Peek } 59145e5710bSMark Peek 59245e5710bSMark Peek struct passwd * 59345e5710bSMark Peek xgetpwuid(uid_t xuid) 59445e5710bSMark Peek { 59545e5710bSMark Peek struct passwd *res; 59645e5710bSMark Peek 59745e5710bSMark Peek errno = 0; 59845e5710bSMark Peek while ((res = getpwuid(xuid)) == NULL && errno == EINTR) { 59945e5710bSMark Peek handle_pending_signals(); 60045e5710bSMark Peek errno = 0; 60145e5710bSMark Peek } 60245e5710bSMark Peek return res; 60345e5710bSMark Peek } 60445e5710bSMark Peek 60545e5710bSMark Peek int 60645e5710bSMark Peek xopen(const char *path, int oflag, ...) 60745e5710bSMark Peek { 60845e5710bSMark Peek int res; 60945e5710bSMark Peek 61045e5710bSMark Peek if ((oflag & O_CREAT) == 0) { 61145e5710bSMark Peek while ((res = open(path, oflag)) == -1 && errno == EINTR) 61245e5710bSMark Peek handle_pending_signals(); 61345e5710bSMark Peek } else { 61445e5710bSMark Peek va_list ap; 61545e5710bSMark Peek mode_t mode; 61645e5710bSMark Peek 61745e5710bSMark Peek va_start(ap, oflag); 61845e5710bSMark Peek /* "int" should actually be "mode_t after default argument 61945e5710bSMark Peek promotions". "int" is the best guess we have, "mode_t" used to be 62045e5710bSMark Peek "unsigned short", which we obviously can't use. */ 62145e5710bSMark Peek mode = va_arg(ap, int); 62245e5710bSMark Peek va_end(ap); 62345e5710bSMark Peek while ((res = open(path, oflag, mode)) == -1 && errno == EINTR) 62445e5710bSMark Peek handle_pending_signals(); 62545e5710bSMark Peek } 62645e5710bSMark Peek return res; 62745e5710bSMark Peek } 62845e5710bSMark Peek 62945e5710bSMark Peek ssize_t 63045e5710bSMark Peek xread(int fildes, void *buf, size_t nbyte) 63145e5710bSMark Peek { 63245e5710bSMark Peek ssize_t res; 63345e5710bSMark Peek 63445e5710bSMark Peek /* This is where we will be blocked most of the time, so handle signals 63545e5710bSMark Peek that didn't interrupt any system call. */ 63645e5710bSMark Peek do 63745e5710bSMark Peek handle_pending_signals(); 63845e5710bSMark Peek while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR); 63945e5710bSMark Peek return res; 64045e5710bSMark Peek } 64145e5710bSMark Peek 64245e5710bSMark Peek #ifdef POSIX 64345e5710bSMark Peek int 64445e5710bSMark Peek xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p) 64545e5710bSMark Peek { 64645e5710bSMark Peek int res; 64745e5710bSMark Peek 64845e5710bSMark Peek while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 && 64945e5710bSMark Peek errno == EINTR) 65045e5710bSMark Peek handle_pending_signals(); 65145e5710bSMark Peek return res; 65245e5710bSMark Peek } 65345e5710bSMark Peek #endif 65445e5710bSMark Peek 65545e5710bSMark Peek ssize_t 65645e5710bSMark Peek xwrite(int fildes, const void *buf, size_t nbyte) 65745e5710bSMark Peek { 65845e5710bSMark Peek ssize_t res; 65945e5710bSMark Peek 66045e5710bSMark Peek /* This is where we will be blocked most of the time, so handle signals 66145e5710bSMark Peek that didn't interrupt any system call. */ 66245e5710bSMark Peek do 66345e5710bSMark Peek handle_pending_signals(); 66445e5710bSMark Peek while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR); 66545e5710bSMark Peek return res; 66645e5710bSMark Peek } 667