sh.misc.c revision 145479
1145479Smp/* $Header: /src/pub/tcsh/sh.misc.c,v 3.34 2005/01/18 20:24:50 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 35145479SmpRCSID("$Id: sh.misc.c,v 3.34 2005/01/18 20:24:50 christos Exp $") 3659243Sobrien 3759243Sobrienstatic int renum __P((int, int)); 3859243Sobrienstatic Char **blkend __P((Char **)); 3959243Sobrienstatic Char **blkcat __P((Char **, Char **)); 4059243Sobrien 4159243Sobrien/* 4259243Sobrien * C Shell 4359243Sobrien */ 4459243Sobrien 4559243Sobrienint 4659243Sobrienany(s, c) 47145479Smp const char *s; 48145479Smp Char c; 4959243Sobrien{ 5059243Sobrien if (!s) 5159243Sobrien return (0); /* Check for nil pointer */ 5259243Sobrien while (*s) 53145479Smp if ((Char)*s++ == c) 5459243Sobrien return (1); 5559243Sobrien return (0); 5659243Sobrien} 5759243Sobrien 5859243Sobrienvoid 5959243Sobriensetzero(cp, i) 6059243Sobrien char *cp; 6159243Sobrien int i; 6259243Sobrien{ 6359243Sobrien if (i != 0) 6459243Sobrien do 6559243Sobrien *cp++ = 0; 6659243Sobrien while (--i); 6759243Sobrien} 6859243Sobrien 6959243Sobrienchar * 7059243Sobrienstrsave(s) 71145479Smp const char *s; 7259243Sobrien{ 73145479Smp char *n, *r; 74145479Smp const char *p; 7559243Sobrien 7659243Sobrien if (s == NULL) 77145479Smp s = ""; 78145479Smp for (p = s; *p++ != '\0';) 7959243Sobrien continue; 80145479Smp r = n = (char *) xmalloc((size_t)((((const char *) p) - s) * sizeof(char))); 81145479Smp while ((*n++ = *s++) != '\0') 8259243Sobrien continue; 83145479Smp return (r); 8459243Sobrien} 8559243Sobrien 8659243Sobrienstatic Char ** 8759243Sobrienblkend(up) 88145479Smp Char **up; 8959243Sobrien{ 9059243Sobrien 9159243Sobrien while (*up) 9259243Sobrien up++; 9359243Sobrien return (up); 9459243Sobrien} 9559243Sobrien 9659243Sobrien 9759243Sobrienvoid 9859243Sobrienblkpr(av) 99145479Smp Char **av; 10059243Sobrien{ 10159243Sobrien 10259243Sobrien for (; *av; av++) { 10359243Sobrien xprintf("%S", *av); 10459243Sobrien if (av[1]) 10559243Sobrien xprintf(" "); 10659243Sobrien } 10759243Sobrien} 10859243Sobrien 10959243Sobrienvoid 11059243Sobrienblkexpand(av, str) 111145479Smp Char **av; 11259243Sobrien Char *str; 11359243Sobrien{ 11459243Sobrien *str = '\0'; 11559243Sobrien for (; *av; av++) { 11659243Sobrien (void) Strcat(str, *av); 11759243Sobrien if (av[1]) 11859243Sobrien (void) Strcat(str, STRspace); 11959243Sobrien } 12059243Sobrien} 12159243Sobrien 12259243Sobrienint 12359243Sobrienblklen(av) 124145479Smp Char **av; 12559243Sobrien{ 126145479Smp int i = 0; 12759243Sobrien 12859243Sobrien while (*av++) 12959243Sobrien i++; 13059243Sobrien return (i); 13159243Sobrien} 13259243Sobrien 13359243SobrienChar ** 13459243Sobrienblkcpy(oav, bv) 13559243Sobrien Char **oav; 136145479Smp Char **bv; 13759243Sobrien{ 138145479Smp Char **av = oav; 13959243Sobrien 14059243Sobrien while ((*av++ = *bv++) != NULL) 14159243Sobrien continue; 14259243Sobrien return (oav); 14359243Sobrien} 14459243Sobrien 14559243Sobrienstatic Char ** 14659243Sobrienblkcat(up, vp) 14759243Sobrien Char **up, **vp; 14859243Sobrien{ 14959243Sobrien 15059243Sobrien (void) blkcpy(blkend(up), vp); 15159243Sobrien return (up); 15259243Sobrien} 15359243Sobrien 15459243Sobrienvoid 15559243Sobrienblkfree(av0) 15659243Sobrien Char **av0; 15759243Sobrien{ 158145479Smp Char **av = av0; 15959243Sobrien 16059243Sobrien if (!av0) 16159243Sobrien return; 16259243Sobrien for (; *av; av++) 16359243Sobrien xfree((ptr_t) * av); 16459243Sobrien xfree((ptr_t) av0); 16559243Sobrien} 16659243Sobrien 16759243SobrienChar ** 16859243Sobriensaveblk(v) 169145479Smp Char **v; 17059243Sobrien{ 171145479Smp Char **newv = 17259243Sobrien (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 17359243Sobrien Char **onewv = newv; 17459243Sobrien 17559243Sobrien while (*v) 17659243Sobrien *newv++ = Strsave(*v++); 17759243Sobrien return (onewv); 17859243Sobrien} 17959243Sobrien 180145479Smp#ifndef HAVE_STRSTR 18159243Sobrienchar * 18259243Sobrienstrstr(s, t) 183145479Smp const char *s, *t; 18459243Sobrien{ 18559243Sobrien do { 186145479Smp const char *ss = s; 187145479Smp const char *tt = t; 18859243Sobrien 18959243Sobrien do 19059243Sobrien if (*tt == '\0') 19159243Sobrien return ((char *) s); 19259243Sobrien while (*ss++ == *tt++); 19359243Sobrien } while (*s++ != '\0'); 19459243Sobrien return (NULL); 19559243Sobrien} 196145479Smp#endif /* !HAVE_STRSTR */ 19759243Sobrien 19859243Sobrien#ifndef SHORT_STRINGS 19959243Sobrienchar * 20059243Sobrienstrspl(cp, dp) 201145479Smp const char *cp, *dp; 20259243Sobrien{ 20359243Sobrien char *ep; 204145479Smp size_t cl, dl; 20559243Sobrien 20659243Sobrien if (!cp) 20759243Sobrien cp = ""; 20859243Sobrien if (!dp) 20959243Sobrien dp = ""; 210145479Smp cl = strlen(cp); 211145479Smp dl = strlen(dp); 212145479Smp ep = (char *) xmalloc((cl + dl + 1) * sizeof(char)); 213145479Smp memcpy(ep, cp, cl); 214145479Smp memcpy(ep + cl, dp, dl + 1); 21559243Sobrien return (ep); 21659243Sobrien} 21759243Sobrien 21859243Sobrien#endif /* !SHORT_STRINGS */ 21959243Sobrien 22059243SobrienChar ** 22159243Sobrienblkspl(up, vp) 222145479Smp Char **up, **vp; 22359243Sobrien{ 224145479Smp Char **wp = 22559243Sobrien (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 22659243Sobrien sizeof(Char **)); 22759243Sobrien 22859243Sobrien (void) blkcpy(wp, up); 22959243Sobrien return (blkcat(wp, vp)); 23059243Sobrien} 23159243Sobrien 23259243SobrienChar 23359243Sobrienlastchr(cp) 234145479Smp Char *cp; 23559243Sobrien{ 23659243Sobrien 23759243Sobrien if (!cp) 23859243Sobrien return (0); 23959243Sobrien if (!*cp) 24059243Sobrien return (0); 24159243Sobrien while (cp[1]) 24259243Sobrien cp++; 24359243Sobrien return (*cp); 24459243Sobrien} 24559243Sobrien 24659243Sobrien/* 24759243Sobrien * This routine is called after an error to close up 24859243Sobrien * any units which may have been left open accidentally. 24959243Sobrien */ 25059243Sobrienvoid 25159243Sobrienclosem() 25259243Sobrien{ 253145479Smp int f; 25459243Sobrien 255131962Smp#ifdef NLS_BUGS 256131962Smp#ifdef NLS_CATALOGS 257145479Smp nlsclose(); 258131962Smp#endif /* NLS_CATALOGS */ 259131962Smp#endif /* NLS_BUGS */ 26059243Sobrien#ifdef YPBUGS 26159243Sobrien /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 26259243Sobrien fix_yp_bugs(); 26359243Sobrien#endif /* YPBUGS */ 26459243Sobrien for (f = 0; f < NOFILE; f++) 26559243Sobrien if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 26659243Sobrien f != FSHTTY 26759243Sobrien#ifdef MALLOC_TRACE 26859243Sobrien && f != 25 26959243Sobrien#endif /* MALLOC_TRACE */ 27059243Sobrien ) 27159243Sobrien { 27259243Sobrien (void) close(f); 27359243Sobrien#ifdef NISPLUS 27459243Sobrien if(f < 3) 275131962Smp (void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 27659243Sobrien#endif /* NISPLUS */ 27759243Sobrien } 278131962Smp#ifdef NLS_BUGS 279131962Smp#ifdef NLS_CATALOGS 280131962Smp nlsinit(); 281131962Smp#endif /* NLS_CATALOGS */ 282131962Smp#endif /* NLS_BUGS */ 28359243Sobrien} 28459243Sobrien 28559243Sobrien#ifndef CLOSE_ON_EXEC 28659243Sobrien/* 28759243Sobrien * Close files before executing a file. 28859243Sobrien * We could be MUCH more intelligent, since (on a version 7 system) 28959243Sobrien * we need only close files here during a source, the other 29059243Sobrien * shell fd's being in units 16-19 which are closed automatically! 29159243Sobrien */ 29259243Sobrienvoid 29359243Sobrienclosech() 29459243Sobrien{ 295145479Smp int f; 29659243Sobrien 29759243Sobrien if (didcch) 29859243Sobrien return; 29959243Sobrien didcch = 1; 30059243Sobrien SHIN = 0; 30159243Sobrien SHOUT = 1; 30259243Sobrien SHDIAG = 2; 30359243Sobrien OLDSTD = 0; 30459243Sobrien isoutatty = isatty(SHOUT); 30559243Sobrien isdiagatty = isatty(SHDIAG); 30659243Sobrien for (f = 3; f < NOFILE; f++) 30759243Sobrien (void) close(f); 30859243Sobrien} 30959243Sobrien 31059243Sobrien#endif /* CLOSE_ON_EXEC */ 31159243Sobrien 31259243Sobrienvoid 31359243Sobriendonefds() 31459243Sobrien{ 31559243Sobrien 31659243Sobrien (void) close(0); 31759243Sobrien (void) close(1); 31859243Sobrien (void) close(2); 31959243Sobrien didfds = 0; 32059243Sobrien#ifdef NISPLUS 32159243Sobrien { 322131962Smp int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE); 323145479Smp (void)dcopy(fd, 1); 324145479Smp (void)dcopy(fd, 2); 325145479Smp (void)dmove(fd, 0); 32659243Sobrien } 32759243Sobrien#endif /*NISPLUS*/ 32859243Sobrien} 32959243Sobrien 33059243Sobrien/* 33159243Sobrien * Move descriptor i to j. 33259243Sobrien * If j is -1 then we just want to get i to a safe place, 333145479Smp * i.e. to a unit > FSAFE. This also happens in dcopy. 33459243Sobrien */ 33559243Sobrienint 33659243Sobriendmove(i, j) 337145479Smp int i, j; 33859243Sobrien{ 33959243Sobrien 34059243Sobrien if (i == j || i < 0) 34159243Sobrien return (i); 342145479Smp#ifdef HAVE_DUP2 34359243Sobrien if (j >= 0) { 34459243Sobrien (void) dup2(i, j); 34559243Sobrien if (j != i) 34659243Sobrien (void) close(i); 34759243Sobrien return (j); 34859243Sobrien } 34959243Sobrien#endif 35059243Sobrien j = dcopy(i, j); 35159243Sobrien if (j != i) 35259243Sobrien (void) close(i); 35359243Sobrien return (j); 35459243Sobrien} 35559243Sobrien 35659243Sobrienint 35759243Sobriendcopy(i, j) 358145479Smp int i, j; 35959243Sobrien{ 36059243Sobrien 361145479Smp if (i == j || i < 0 || (j < 0 && i > FSAFE)) 36259243Sobrien return (i); 36359243Sobrien if (j >= 0) { 364145479Smp#ifdef HAVE_DUP2 36559243Sobrien (void) dup2(i, j); 36659243Sobrien return (j); 36759243Sobrien#else 36859243Sobrien (void) close(j); 36959243Sobrien#endif 37059243Sobrien } 37159243Sobrien return (renum(i, j)); 37259243Sobrien} 37359243Sobrien 37459243Sobrienstatic int 37559243Sobrienrenum(i, j) 376145479Smp int i, j; 37759243Sobrien{ 378145479Smp int k = dup(i); 37959243Sobrien 38059243Sobrien if (k < 0) 38159243Sobrien return (-1); 382145479Smp if (j == -1 && k > FSAFE) 38359243Sobrien return (k); 38459243Sobrien if (k != j) { 38559243Sobrien j = renum(k, j); 38659243Sobrien (void) close(k); 38759243Sobrien return (j); 38859243Sobrien } 38959243Sobrien return (k); 39059243Sobrien} 39159243Sobrien 39259243Sobrien/* 39359243Sobrien * Left shift a command argument list, discarding 39459243Sobrien * the first c arguments. Used in "shift" commands 39559243Sobrien * as well as by commands like "repeat". 39659243Sobrien */ 39759243Sobrienvoid 39859243Sobrienlshift(v, c) 399145479Smp Char **v; 400145479Smp int c; 40159243Sobrien{ 402145479Smp Char **u; 40359243Sobrien 40459243Sobrien for (u = v; *u && --c >= 0; u++) 40559243Sobrien xfree((ptr_t) *u); 40659243Sobrien (void) blkcpy(v, u); 40759243Sobrien} 40859243Sobrien 40959243Sobrienint 41059243Sobriennumber(cp) 41159243Sobrien Char *cp; 41259243Sobrien{ 41359243Sobrien if (!cp) 41459243Sobrien return (0); 41559243Sobrien if (*cp == '-') { 41659243Sobrien cp++; 41759243Sobrien if (!Isdigit(*cp)) 41859243Sobrien return (0); 41959243Sobrien cp++; 42059243Sobrien } 42159243Sobrien while (*cp && Isdigit(*cp)) 42259243Sobrien cp++; 42359243Sobrien return (*cp == 0); 42459243Sobrien} 42559243Sobrien 42659243SobrienChar ** 42759243Sobriencopyblk(v) 428145479Smp Char **v; 42959243Sobrien{ 430145479Smp Char **nv = 43159243Sobrien (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 43259243Sobrien 43359243Sobrien return (blkcpy(nv, v)); 43459243Sobrien} 43559243Sobrien 43659243Sobrien#ifndef SHORT_STRINGS 43759243Sobrienchar * 43859243Sobrienstrend(cp) 439145479Smp char *cp; 44059243Sobrien{ 44159243Sobrien if (!cp) 44259243Sobrien return (cp); 44359243Sobrien while (*cp) 44459243Sobrien cp++; 44559243Sobrien return (cp); 44659243Sobrien} 44759243Sobrien 44859243Sobrien#endif /* SHORT_STRINGS */ 44959243Sobrien 45059243SobrienChar * 45159243Sobrienstrip(cp) 45259243Sobrien Char *cp; 45359243Sobrien{ 454145479Smp Char *dp = cp; 45559243Sobrien 45659243Sobrien if (!cp) 45759243Sobrien return (cp); 45859243Sobrien while ((*dp++ &= TRIM) != '\0') 45959243Sobrien continue; 46059243Sobrien return (cp); 46159243Sobrien} 46259243Sobrien 46359243SobrienChar * 46459243Sobrienquote(cp) 46559243Sobrien Char *cp; 46659243Sobrien{ 467145479Smp Char *dp = cp; 46859243Sobrien 46959243Sobrien if (!cp) 47059243Sobrien return (cp); 47159243Sobrien while (*dp != '\0') 47259243Sobrien *dp++ |= QUOTE; 47359243Sobrien return (cp); 47459243Sobrien} 47559243Sobrien 47659243SobrienChar * 47759243Sobrienquote_meta(d, s) 47859243Sobrien Char *d; 47959243Sobrien const Char *s; 48059243Sobrien{ 48159243Sobrien Char *r = d; 48259243Sobrien while (*s != '\0') { 48359243Sobrien if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 48459243Sobrien *d++ = '\\'; 48559243Sobrien *d++ = *s++; 48659243Sobrien } 48759243Sobrien *d = '\0'; 48859243Sobrien return r; 48959243Sobrien} 49059243Sobrien 49159243Sobrienvoid 49259243Sobrienudvar(name) 49359243Sobrien Char *name; 49459243Sobrien{ 49559243Sobrien 49659243Sobrien setname(short2str(name)); 49759243Sobrien stderror(ERR_NAME | ERR_UNDVAR); 49859243Sobrien} 49959243Sobrien 50059243Sobrienint 50159243Sobrienprefix(sub, str) 502145479Smp const Char *sub, *str; 50359243Sobrien{ 50459243Sobrien 50559243Sobrien for (;;) { 50659243Sobrien if (*sub == 0) 50759243Sobrien return (1); 50859243Sobrien if (*str == 0) 50959243Sobrien return (0); 51059243Sobrien if ((*sub++ & TRIM) != (*str++ & TRIM)) 51159243Sobrien return (0); 51259243Sobrien } 51359243Sobrien} 514