"Fossies" - the Fresh Open Source Software Archive

Member "tcsh-6.22.03/sh.misc.c" (18 Nov 2020, 13008 Bytes) of package /linux/misc/tcsh-6.22.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "sh.misc.c": 6.22.02_vs_6.22.03.

    1 /*
    2  * sh.misc.c: Miscelaneous functions
    3  */
    4 /*-
    5  * Copyright (c) 1980, 1991 The Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 #include "sh.h"
   33 
   34 static  int renum   (int, int);
   35 static  Char  **blkend  (Char **);
   36 static  Char  **blkcat  (Char **, Char **);
   37 static  int xdup2   (int, int);
   38 
   39 /*
   40  * C Shell
   41  */
   42 
   43 int
   44 any(const char *s, Char c)
   45 {
   46     if (!s)
   47     return (0);     /* Check for nil pointer */
   48     while (*s)
   49     if ((Char)*s++ == c)
   50         return (1);
   51     return (0);
   52 }
   53 
   54 void
   55 setzero(void *p, size_t size)
   56 {
   57     memset(p, 0, size);
   58 }
   59 
   60 #ifndef SHORT_STRINGS
   61 char *
   62 strnsave(const char *s, size_t len)
   63 {
   64     char *r;
   65 
   66     r = xmalloc(len + 1);
   67     memcpy(r, s, len);
   68     r[len] = '\0';
   69     return r;
   70 }
   71 #endif
   72 
   73 char   *
   74 strsave(const char *s)
   75 {
   76     char   *r;
   77     size_t size;
   78 
   79     if (s == NULL)
   80     s = "";
   81     size = strlen(s) + 1;
   82     r = xmalloc(size);
   83     memcpy(r, s, size);
   84     return (r);
   85 }
   86 
   87 static Char  **
   88 blkend(Char **up)
   89 {
   90 
   91     while (*up)
   92     up++;
   93     return (up);
   94 }
   95 
   96 
   97 void
   98 blkpr(Char *const *av)
   99 {
  100 
  101     for (; *av; av++) {
  102     xprintf("%S", *av);
  103     if (av[1])
  104         xprintf(" ");
  105     }
  106 }
  107 
  108 Char *
  109 blkexpand(Char *const *av)
  110 {
  111     struct Strbuf buf = Strbuf_INIT;
  112 
  113     for (; *av; av++) {
  114     Strbuf_append(&buf, *av);
  115     if (av[1])
  116         Strbuf_append1(&buf, ' ');
  117     }
  118     return Strbuf_finish(&buf);
  119 }
  120 
  121 int
  122 blklen(Char **av)
  123 {
  124     int i = 0;
  125 
  126     while (*av++)
  127     i++;
  128     return (i);
  129 }
  130 
  131 Char  **
  132 blkcpy(Char **oav, Char **bv)
  133 {
  134     Char **av = oav;
  135 
  136     while ((*av++ = *bv++) != NULL)
  137     continue;
  138     return (oav);
  139 }
  140 
  141 static Char  **
  142 blkcat(Char **up, Char **vp)
  143 {
  144 
  145     (void) blkcpy(blkend(up), vp);
  146     return (up);
  147 }
  148 
  149 void
  150 blkfree(Char **av0)
  151 {
  152     Char **av = av0;
  153 
  154     if (!av0)
  155     return;
  156     for (; *av; av++)
  157     xfree(*av);
  158     xfree(av0);
  159 }
  160 
  161 void
  162 blk_cleanup(void *ptr)
  163 {
  164     blkfree(ptr);
  165 }
  166 
  167 void
  168 blk_indirect_cleanup(void *xptr)
  169 {
  170     Char ***ptr;
  171 
  172     ptr = xptr;
  173     blkfree(*ptr);
  174     xfree(ptr);
  175 }
  176 
  177 Char  **
  178 saveblk(Char **v)
  179 {
  180     Char **newv, **onewv;
  181 
  182     if (v == NULL)
  183     return NULL;
  184 
  185     onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
  186 
  187     while (*v)
  188     *newv++ = Strsave(*v++);
  189     return (onewv);
  190 }
  191 
  192 #ifndef HAVE_STRSTR
  193 char   *
  194 strstr(const char *s, const char *t)
  195 {
  196     do {
  197     const char *ss = s;
  198     const char *tt = t;
  199 
  200     do
  201         if (*tt == '\0')
  202         return (s);
  203     while (*ss++ == *tt++);
  204     } while (*s++ != '\0');
  205     return (NULL);
  206 }
  207 #endif /* !HAVE_STRSTR */
  208 
  209 char   *
  210 strspl(const char *cp, const char *dp)
  211 {
  212     char   *ep;
  213     size_t cl, dl;
  214 
  215     if (!cp)
  216     cp = "";
  217     if (!dp)
  218     dp = "";
  219     cl = strlen(cp);
  220     dl = strlen(dp);
  221     ep = xmalloc((cl + dl + 1) * sizeof(char));
  222     memcpy(ep, cp, cl);
  223     memcpy(ep + cl, dp, dl + 1);
  224     return (ep);
  225 }
  226 
  227 Char  **
  228 blkspl(Char **up, Char **vp)
  229 {
  230     Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
  231 
  232     (void) blkcpy(wp, up);
  233     return (blkcat(wp, vp));
  234 }
  235 
  236 Char
  237 lastchr(Char *cp)
  238 {
  239 
  240     if (!cp)
  241     return (0);
  242     if (!*cp)
  243     return (0);
  244     while (cp[1])
  245     cp++;
  246     return (*cp);
  247 }
  248 
  249 /*
  250  * This routine is called after an error to close up
  251  * any units which may have been left open accidentally.
  252  */
  253 void
  254 closem(void)
  255 {
  256     int f, num_files;
  257 #ifdef S_ISSOCK
  258     struct stat st;
  259 #endif /*S_ISSOCK*/
  260 
  261 #ifdef NLS_BUGS
  262 #ifdef NLS_CATALOGS
  263     nlsclose();
  264 #endif /* NLS_CATALOGS */
  265 #endif /* NLS_BUGS */
  266 #ifdef YPBUGS
  267     /* suggested by Justin Bur; thanks to Karl Kleinpaste */
  268     fix_yp_bugs();
  269 #endif /* YPBUGS */
  270     num_files = NOFILE;
  271     for (f = 0; f < num_files; f++)
  272     if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
  273         f != FSHTTY 
  274 #ifdef MALLOC_TRACE
  275         && f != 25
  276 #endif /* MALLOC_TRACE */
  277 #ifdef S_ISSOCK
  278         /* NSS modules (e.g. Linux nss_ldap) might keep sockets open.
  279          * If we close such a socket, both the NSS module and tcsh think
  280          * they "own" the descriptor.
  281          *
  282          * Not closing sockets does not make the cleanup use of closem()
  283          * less reliable because tcsh never creates sockets.
  284          */
  285         && fstat(f, &st) == 0 && !S_ISSOCK(st.st_mode)  
  286 #endif
  287         )
  288       {
  289         xclose(f);
  290 #ifdef NISPLUS
  291         if(f < 3)
  292         (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
  293 #endif /* NISPLUS */
  294       }
  295 #ifdef NLS_BUGS
  296 #ifdef NLS_CATALOGS
  297     nlsinit();
  298 #endif /* NLS_CATALOGS */
  299 #endif /* NLS_BUGS */
  300 }
  301 
  302 #ifndef CLOSE_ON_EXEC
  303 /*
  304  * Close files before executing a file.
  305  * We could be MUCH more intelligent, since (on a version 7 system)
  306  * we need only close files here during a source, the other
  307  * shell fd's being in units 16-19 which are closed automatically!
  308  */
  309 void
  310 closech(void)
  311 {
  312     int f, num_files;
  313 
  314     if (didcch)
  315     return;
  316     didcch = 1;
  317     SHIN = 0;
  318     SHOUT = 1;
  319     SHDIAG = 2;
  320     OLDSTD = 0;
  321     isoutatty = isatty(SHOUT);
  322     isdiagatty = isatty(SHDIAG);
  323     num_files = NOFILE;
  324     for (f = 3; f < num_files; f++)
  325     xclose(f);
  326 }
  327 
  328 #endif /* CLOSE_ON_EXEC */
  329 
  330 void
  331 donefds(void)
  332 {
  333 
  334     xclose(0);
  335     xclose(1);
  336     xclose(2);
  337     didfds = 0;
  338 #ifdef NISPLUS
  339     {
  340     int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
  341     (void)dcopy(fd, 1);
  342     (void)dcopy(fd, 2);
  343     (void)dmove(fd, 0);
  344     }
  345 #endif /*NISPLUS*/    
  346 }
  347 
  348 /*
  349  * Move descriptor i to j.
  350  * If j is -1 then we just want to get i to a safe place,
  351  * i.e. to a unit > FSAFE.  This also happens in dcopy.
  352  */
  353 int
  354 dmove(int i, int j)
  355 {
  356 
  357     if (i == j || i < 0)
  358     return (i);
  359 #ifdef HAVE_DUP2
  360     if (j >= 0) {
  361     (void) xdup2(i, j);
  362     if (j != i)
  363         xclose(i);
  364     return (j);
  365     }
  366 #endif
  367     j = dcopy(i, j);
  368     if (j != i)
  369     xclose(i);
  370     return (j);
  371 }
  372 
  373 int
  374 dcopy(int i, int j)
  375 {
  376 
  377     if (i == j || i < 0 || (j < 0 && i > FSAFE))
  378     return (i);
  379     if (j >= 0) {
  380 #ifdef HAVE_DUP2
  381     (void) xdup2(i, j);
  382     return (j);
  383 #else
  384     xclose(j);
  385 #endif
  386     }
  387     return (renum(i, j));
  388 }
  389 
  390 static int
  391 renum(int i, int j)
  392 {
  393     int k = dup(i);
  394 
  395     if (k < 0)
  396     return (-1);
  397     if (j == -1 && k > FSAFE)
  398     return (k);
  399     if (k != j) {
  400     j = renum(k, j);
  401     xclose(k);
  402     return (j);
  403     }
  404     return (k);
  405 }
  406 
  407 /*
  408  * Left shift a command argument list, discarding
  409  * the first c arguments.  Used in "shift" commands
  410  * as well as by commands like "repeat".
  411  */
  412 void
  413 lshift(Char **v, int c)
  414 {
  415     Char **u;
  416 
  417     for (u = v; *u && --c >= 0; u++)
  418     xfree(*u);
  419     (void) blkcpy(v, u);
  420 }
  421 
  422 int
  423 number(Char *cp)
  424 {
  425     if (!cp)
  426     return (0);
  427     if (*cp == '-') {
  428     cp++;
  429     if (!Isdigit(*cp))
  430         return (0);
  431     cp++;
  432     }
  433     while (*cp && Isdigit(*cp))
  434     cp++;
  435     return (*cp == 0);
  436 }
  437 
  438 Char  **
  439 copyblk(Char **v)
  440 {
  441     Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
  442 
  443     return (blkcpy(nv, v));
  444 }
  445 
  446 char   *
  447 strend(const char *cp)
  448 {
  449     if (!cp)
  450     return ((char *)(intptr_t)cp);
  451     while (*cp)
  452     cp++;
  453     return ((char *)(intptr_t)cp);
  454 }
  455 
  456 Char   *
  457 strip(Char *cp)
  458 {
  459     Char *dp = cp;
  460 
  461     if (!cp)
  462     return (cp);
  463     while (*dp != '\0') {
  464 #if INVALID_BYTE != 0
  465     if ((*dp & INVALID_BYTE) != INVALID_BYTE)    /* *dp < INVALID_BYTE */
  466 #endif
  467         *dp &= TRIM;
  468     dp++;
  469     }
  470     return (cp);
  471 }
  472 
  473 Char   *
  474 quote(Char *cp)
  475 {
  476     Char *dp = cp;
  477 
  478     if (!cp)
  479     return (cp);
  480     while (*dp != '\0') {
  481 #ifdef WIDE_STRINGS
  482     if ((*dp & 0xffffff80) == 0)    /* *dp < 0x80 */
  483 #elif defined SHORT_STRINGS
  484     if ((*dp & 0xff80) == 0)    /* *dp < 0x80 */
  485 #else
  486     if ((*dp & 0x80) == 0)      /* *dp < 0x80 */
  487 #endif
  488         *dp |= QUOTE;
  489     dp++;
  490     }
  491     return (cp);
  492 }
  493 
  494 const Char *
  495 quote_meta(struct Strbuf *buf, const Char *s)
  496 {
  497     buf->len = 0;
  498     while (*s != '\0') {
  499     if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
  500         Strbuf_append1(buf, '\\');
  501     Strbuf_append1(buf, *s++);
  502     }
  503     Strbuf_terminate(buf);
  504     return buf->s;
  505 }
  506 
  507 void
  508 udvar(Char *name)
  509 {
  510     setname(short2str(name));
  511     stderror(ERR_NAME | ERR_UNDVAR);
  512 }
  513 
  514 int
  515 prefix(const Char *sub, const Char *str)
  516 {
  517 
  518     for (;;) {
  519     if (*sub == 0)
  520         return (1);
  521     if (*str == 0)
  522         return (0);
  523     if ((*sub++ & TRIM) != (*str++ & TRIM))
  524         return (0);
  525     }
  526 }
  527 #ifndef WINNT_NATIVE
  528 char *
  529 areadlink(const char *path)
  530 {
  531     char *buf;
  532     size_t size;
  533     ssize_t res;
  534 #ifdef __IBMC__
  535     /*
  536      * Prevent infinite recursion. Someone should tell me how to expand
  537      * these...
  538      */
  539     size_t i;
  540     static const char *vars[] = {
  541     "/$VERSION",
  542     "/$SYSNAME",
  543     "/$SYSSYMR",
  544     "/$SYSSYMA",
  545     };
  546     for (i = 0; i < sizeof(vars) / sizeof(vars[0]); i++) {
  547     if (strcmp(vars[i], path) == 0) {
  548         return NULL;
  549     }
  550     }
  551 #endif
  552 
  553 
  554     size = MAXPATHLEN + 1;
  555     buf = xmalloc(size);
  556     while ((size_t)(res = readlink(path, buf, size)) == size) {
  557     size *= 2;
  558     buf = xrealloc(buf, size);
  559     }
  560     if (res == -1) {
  561     int err;
  562 
  563     err = errno;
  564     xfree(buf);
  565     errno = err;
  566     return NULL;
  567     }
  568     buf[res] = '\0';
  569     return xrealloc(buf, res + 1);
  570 }
  571 #endif /*!WINNT_NATIVE*/
  572 
  573 void
  574 xclose(int fildes)
  575 {
  576     if (fildes < 0)
  577     return;
  578     while (close(fildes) == -1 && errno == EINTR)
  579     if (handle_pending_signals())
  580         break;
  581 }
  582 
  583 void
  584 xclosedir(DIR *dirp)
  585 {
  586     while (closedir(dirp) == -1 && errno == EINTR)
  587     if (handle_pending_signals())
  588         break;
  589 }
  590 
  591 int
  592 xcreat(const char *path, mode_t mode)
  593 {
  594     int res;
  595 
  596     while ((res = creat(path, mode)) == -1 && errno == EINTR)
  597     if (handle_pending_signals())
  598         break;
  599     return res;
  600 }
  601 
  602 #ifdef HAVE_DUP2
  603 static int
  604 xdup2(int fildes, int fildes2)
  605 {
  606     int res;
  607 
  608     while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
  609     if (handle_pending_signals())
  610         break;
  611     return res;
  612 }
  613 #endif
  614 
  615 struct group *
  616 xgetgrgid(gid_t xgid)
  617 {
  618     struct group *res;
  619 
  620     errno = 0;
  621     while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
  622     if (handle_pending_signals())
  623         break;
  624     errno = 0;
  625     }
  626     return res;
  627 }
  628 
  629 struct passwd *
  630 xgetpwnam(const char *name)
  631 {
  632     struct passwd *res;
  633 
  634     errno = 0;
  635     while ((res = getpwnam(name)) == NULL && errno == EINTR) {
  636     if (handle_pending_signals())
  637         break;
  638     errno = 0;
  639     }
  640     return res;
  641 }
  642 
  643 struct passwd *
  644 xgetpwuid(uid_t xuid)
  645 {
  646     struct passwd *res;
  647 
  648     errno = 0;
  649     while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
  650     if (handle_pending_signals())
  651         break;
  652     errno = 0;
  653     }
  654     return res;
  655 }
  656 
  657 int
  658 xopen(const char *path, int oflag, ...)
  659 {
  660     int res;
  661 
  662     if ((oflag & O_CREAT) == 0) {
  663     while ((res = open(path, oflag)) == -1 && errno == EINTR)
  664         if (handle_pending_signals())
  665         break;
  666     } else {
  667     va_list ap;
  668     mode_t mode;
  669 
  670     va_start(ap, oflag);
  671     /* "int" should actually be "mode_t after default argument
  672        promotions". "int" is the best guess we have, "mode_t" used to be
  673        "unsigned short", which we obviously can't use. */
  674     mode = va_arg(ap, int);
  675     va_end(ap);
  676     while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
  677         if (handle_pending_signals())
  678         break;
  679     }
  680     return res;
  681 }
  682 
  683 ssize_t
  684 xread(int fildes, void *buf, size_t nbyte)
  685 {
  686     ssize_t res = -1;
  687 
  688     /* This is where we will be blocked most of the time, so handle signals
  689        that didn't interrupt any system call. */
  690     do
  691       if (handle_pending_signals())
  692       break;
  693     while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
  694     return res;
  695 }
  696 
  697 #ifdef POSIX
  698 int
  699 xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
  700 {
  701     int res;
  702 
  703     while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
  704        errno == EINTR)
  705     if (handle_pending_signals())
  706         break;
  707     return res;
  708 }
  709 #endif
  710 
  711 ssize_t
  712 xwrite(int fildes, const void *buf, size_t nbyte)
  713 {
  714     ssize_t res = -1;
  715 
  716     /* This is where we will be blocked most of the time, so handle signals
  717        that didn't interrupt any system call. */
  718     do
  719       if (handle_pending_signals())
  720       break;
  721     while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
  722     return res;
  723 }