sh.misc.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/sh.misc.c,v 3.24 2002/03/08 17:36:46 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 35100616SmpRCSID("$Id: sh.misc.c,v 3.24 2002/03/08 17:36:46 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) 4759243Sobrien register char *s; 4859243Sobrien register int c; 4959243Sobrien{ 5059243Sobrien if (!s) 5159243Sobrien return (0); /* Check for nil pointer */ 5259243Sobrien while (*s) 5359243Sobrien if (*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) 7159243Sobrien register const char *s; 7259243Sobrien{ 7359243Sobrien char *n; 7459243Sobrien register char *p; 7559243Sobrien 7659243Sobrien if (s == NULL) 7759243Sobrien s = (const char *) ""; 7859243Sobrien for (p = (char *) s; *p++ != '\0';) 7959243Sobrien continue; 8059243Sobrien n = p = (char *) xmalloc((size_t) 8159243Sobrien ((((const char *) p) - s) * sizeof(char))); 8259243Sobrien while ((*p++ = *s++) != '\0') 8359243Sobrien continue; 8459243Sobrien return (n); 8559243Sobrien} 8659243Sobrien 8759243Sobrienstatic Char ** 8859243Sobrienblkend(up) 8959243Sobrien register Char **up; 9059243Sobrien{ 9159243Sobrien 9259243Sobrien while (*up) 9359243Sobrien up++; 9459243Sobrien return (up); 9559243Sobrien} 9659243Sobrien 9759243Sobrien 9859243Sobrienvoid 9959243Sobrienblkpr(av) 10059243Sobrien register Char **av; 10159243Sobrien{ 10259243Sobrien 10359243Sobrien for (; *av; av++) { 10459243Sobrien xprintf("%S", *av); 10559243Sobrien if (av[1]) 10659243Sobrien xprintf(" "); 10759243Sobrien } 10859243Sobrien} 10959243Sobrien 11059243Sobrienvoid 11159243Sobrienblkexpand(av, str) 11259243Sobrien register Char **av; 11359243Sobrien Char *str; 11459243Sobrien{ 11559243Sobrien *str = '\0'; 11659243Sobrien for (; *av; av++) { 11759243Sobrien (void) Strcat(str, *av); 11859243Sobrien if (av[1]) 11959243Sobrien (void) Strcat(str, STRspace); 12059243Sobrien } 12159243Sobrien} 12259243Sobrien 12359243Sobrienint 12459243Sobrienblklen(av) 12559243Sobrien register Char **av; 12659243Sobrien{ 12759243Sobrien register int i = 0; 12859243Sobrien 12959243Sobrien while (*av++) 13059243Sobrien i++; 13159243Sobrien return (i); 13259243Sobrien} 13359243Sobrien 13459243SobrienChar ** 13559243Sobrienblkcpy(oav, bv) 13659243Sobrien Char **oav; 13759243Sobrien register Char **bv; 13859243Sobrien{ 13959243Sobrien register Char **av = oav; 14059243Sobrien 14159243Sobrien while ((*av++ = *bv++) != NULL) 14259243Sobrien continue; 14359243Sobrien return (oav); 14459243Sobrien} 14559243Sobrien 14659243Sobrienstatic Char ** 14759243Sobrienblkcat(up, vp) 14859243Sobrien Char **up, **vp; 14959243Sobrien{ 15059243Sobrien 15159243Sobrien (void) blkcpy(blkend(up), vp); 15259243Sobrien return (up); 15359243Sobrien} 15459243Sobrien 15559243Sobrienvoid 15659243Sobrienblkfree(av0) 15759243Sobrien Char **av0; 15859243Sobrien{ 15959243Sobrien register Char **av = av0; 16059243Sobrien 16159243Sobrien if (!av0) 16259243Sobrien return; 16359243Sobrien for (; *av; av++) 16459243Sobrien xfree((ptr_t) * av); 16559243Sobrien xfree((ptr_t) av0); 16659243Sobrien} 16759243Sobrien 16859243SobrienChar ** 16959243Sobriensaveblk(v) 17059243Sobrien register Char **v; 17159243Sobrien{ 17259243Sobrien register Char **newv = 17359243Sobrien (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 17459243Sobrien Char **onewv = newv; 17559243Sobrien 17659243Sobrien while (*v) 17759243Sobrien *newv++ = Strsave(*v++); 17859243Sobrien return (onewv); 17959243Sobrien} 18059243Sobrien 18159243Sobrien#if !defined(SHORT_STRINGS) && !defined(POSIX) 18259243Sobrienchar * 18359243Sobrienstrstr(s, t) 18459243Sobrien register const char *s, *t; 18559243Sobrien{ 18659243Sobrien do { 18759243Sobrien register const char *ss = s; 18859243Sobrien register const char *tt = t; 18959243Sobrien 19059243Sobrien do 19159243Sobrien if (*tt == '\0') 19259243Sobrien return ((char *) s); 19359243Sobrien while (*ss++ == *tt++); 19459243Sobrien } while (*s++ != '\0'); 19559243Sobrien return (NULL); 19659243Sobrien} 19759243Sobrien 19859243Sobrien#endif /* !SHORT_STRINGS && !POSIX */ 19959243Sobrien 20059243Sobrien#ifndef SHORT_STRINGS 20159243Sobrienchar * 20259243Sobrienstrspl(cp, dp) 20359243Sobrien char *cp, *dp; 20459243Sobrien{ 20559243Sobrien char *ep; 20659243Sobrien register char *p, *q; 20759243Sobrien 20859243Sobrien if (!cp) 20959243Sobrien cp = ""; 21059243Sobrien if (!dp) 21159243Sobrien dp = ""; 21259243Sobrien for (p = cp; *p++ != '\0';) 21359243Sobrien continue; 21459243Sobrien for (q = dp; *q++ != '\0';) 21559243Sobrien continue; 21659243Sobrien ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char))); 21759243Sobrien for (p = ep, q = cp; (*p++ = *q++) != '\0';) 21859243Sobrien continue; 21959243Sobrien for (p--, q = dp; (*p++ = *q++) != '\0';) 22059243Sobrien continue; 22159243Sobrien return (ep); 22259243Sobrien} 22359243Sobrien 22459243Sobrien#endif /* !SHORT_STRINGS */ 22559243Sobrien 22659243SobrienChar ** 22759243Sobrienblkspl(up, vp) 22859243Sobrien register Char **up, **vp; 22959243Sobrien{ 23059243Sobrien register Char **wp = 23159243Sobrien (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 23259243Sobrien sizeof(Char **)); 23359243Sobrien 23459243Sobrien (void) blkcpy(wp, up); 23559243Sobrien return (blkcat(wp, vp)); 23659243Sobrien} 23759243Sobrien 23859243SobrienChar 23959243Sobrienlastchr(cp) 24059243Sobrien register 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 25759243Sobrienclosem() 25859243Sobrien{ 25959243Sobrien register int f; 26059243Sobrien 26159243Sobrien#ifdef YPBUGS 26259243Sobrien /* suggested by Justin Bur; thanks to Karl Kleinpaste */ 26359243Sobrien fix_yp_bugs(); 26459243Sobrien#endif /* YPBUGS */ 26559243Sobrien for (f = 0; f < NOFILE; f++) 26659243Sobrien if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && 26759243Sobrien f != FSHTTY 26859243Sobrien#ifdef MALLOC_TRACE 26959243Sobrien && f != 25 27059243Sobrien#endif /* MALLOC_TRACE */ 27159243Sobrien ) 27259243Sobrien { 27359243Sobrien (void) close(f); 27459243Sobrien#ifdef NISPLUS 27559243Sobrien if(f < 3) 27659243Sobrien (void) open(_PATH_DEVNULL, O_RDONLY); 27759243Sobrien#endif /* NISPLUS */ 27859243Sobrien } 27959243Sobrien} 28059243Sobrien 28159243Sobrien#ifndef CLOSE_ON_EXEC 28259243Sobrien/* 28359243Sobrien * Close files before executing a file. 28459243Sobrien * We could be MUCH more intelligent, since (on a version 7 system) 28559243Sobrien * we need only close files here during a source, the other 28659243Sobrien * shell fd's being in units 16-19 which are closed automatically! 28759243Sobrien */ 28859243Sobrienvoid 28959243Sobrienclosech() 29059243Sobrien{ 29159243Sobrien register int f; 29259243Sobrien 29359243Sobrien if (didcch) 29459243Sobrien return; 29559243Sobrien didcch = 1; 29659243Sobrien SHIN = 0; 29759243Sobrien SHOUT = 1; 29859243Sobrien SHDIAG = 2; 29959243Sobrien OLDSTD = 0; 30059243Sobrien isoutatty = isatty(SHOUT); 30159243Sobrien isdiagatty = isatty(SHDIAG); 30259243Sobrien for (f = 3; f < NOFILE; f++) 30359243Sobrien (void) close(f); 30459243Sobrien} 30559243Sobrien 30659243Sobrien#endif /* CLOSE_ON_EXEC */ 30759243Sobrien 30859243Sobrienvoid 30959243Sobriendonefds() 31059243Sobrien{ 31159243Sobrien 31259243Sobrien (void) close(0); 31359243Sobrien (void) close(1); 31459243Sobrien (void) close(2); 31559243Sobrien didfds = 0; 31659243Sobrien#ifdef NISPLUS 31759243Sobrien { 31859243Sobrien int fd = open(_PATH_DEVNULL, O_RDONLY); 31959243Sobrien (void) dup2(fd, 1); 32059243Sobrien (void) dup2(fd, 2); 32159243Sobrien if (fd != 0) { 32259243Sobrien (void) dup2(fd, 0); 32359243Sobrien (void) close(fd); 32459243Sobrien } 32559243Sobrien } 32659243Sobrien#endif /*NISPLUS*/ 32759243Sobrien} 32859243Sobrien 32959243Sobrien/* 33059243Sobrien * Move descriptor i to j. 33159243Sobrien * If j is -1 then we just want to get i to a safe place, 33259243Sobrien * i.e. to a unit > 2. This also happens in dcopy. 33359243Sobrien */ 33459243Sobrienint 33559243Sobriendmove(i, j) 33659243Sobrien register int i, j; 33759243Sobrien{ 33859243Sobrien 33959243Sobrien if (i == j || i < 0) 34059243Sobrien return (i); 34159243Sobrien#ifdef HAVEDUP2 34259243Sobrien if (j >= 0) { 34359243Sobrien (void) dup2(i, j); 34459243Sobrien if (j != i) 34559243Sobrien (void) close(i); 34659243Sobrien return (j); 34759243Sobrien } 34859243Sobrien#endif 34959243Sobrien j = dcopy(i, j); 35059243Sobrien if (j != i) 35159243Sobrien (void) close(i); 35259243Sobrien return (j); 35359243Sobrien} 35459243Sobrien 35559243Sobrienint 35659243Sobriendcopy(i, j) 35759243Sobrien register int i, j; 35859243Sobrien{ 35959243Sobrien 36059243Sobrien if (i == j || i < 0 || (j < 0 && i > 2)) 36159243Sobrien return (i); 36259243Sobrien if (j >= 0) { 36359243Sobrien#ifdef HAVEDUP2 36459243Sobrien (void) dup2(i, j); 36559243Sobrien return (j); 36659243Sobrien#else 36759243Sobrien (void) close(j); 36859243Sobrien#endif 36959243Sobrien } 37059243Sobrien return (renum(i, j)); 37159243Sobrien} 37259243Sobrien 37359243Sobrienstatic int 37459243Sobrienrenum(i, j) 37559243Sobrien register int i, j; 37659243Sobrien{ 37759243Sobrien register int k = dup(i); 37859243Sobrien 37959243Sobrien if (k < 0) 38059243Sobrien return (-1); 38159243Sobrien if (j == -1 && k > 2) 38259243Sobrien return (k); 38359243Sobrien if (k != j) { 38459243Sobrien j = renum(k, j); 38559243Sobrien (void) close(k); 38659243Sobrien return (j); 38759243Sobrien } 38859243Sobrien return (k); 38959243Sobrien} 39059243Sobrien 39159243Sobrien/* 39259243Sobrien * Left shift a command argument list, discarding 39359243Sobrien * the first c arguments. Used in "shift" commands 39459243Sobrien * as well as by commands like "repeat". 39559243Sobrien */ 39659243Sobrienvoid 39759243Sobrienlshift(v, c) 39859243Sobrien register Char **v; 39959243Sobrien register int c; 40059243Sobrien{ 40159243Sobrien register Char **u; 40259243Sobrien 40359243Sobrien for (u = v; *u && --c >= 0; u++) 40459243Sobrien xfree((ptr_t) *u); 40559243Sobrien (void) blkcpy(v, u); 40659243Sobrien} 40759243Sobrien 40859243Sobrienint 40959243Sobriennumber(cp) 41059243Sobrien Char *cp; 41159243Sobrien{ 41259243Sobrien if (!cp) 41359243Sobrien return (0); 41459243Sobrien if (*cp == '-') { 41559243Sobrien cp++; 41659243Sobrien if (!Isdigit(*cp)) 41759243Sobrien return (0); 41859243Sobrien cp++; 41959243Sobrien } 42059243Sobrien while (*cp && Isdigit(*cp)) 42159243Sobrien cp++; 42259243Sobrien return (*cp == 0); 42359243Sobrien} 42459243Sobrien 42559243SobrienChar ** 42659243Sobriencopyblk(v) 42759243Sobrien register Char **v; 42859243Sobrien{ 42959243Sobrien register Char **nv = 43059243Sobrien (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 43159243Sobrien 43259243Sobrien return (blkcpy(nv, v)); 43359243Sobrien} 43459243Sobrien 43559243Sobrien#ifndef SHORT_STRINGS 43659243Sobrienchar * 43759243Sobrienstrend(cp) 43859243Sobrien register char *cp; 43959243Sobrien{ 44059243Sobrien if (!cp) 44159243Sobrien return (cp); 44259243Sobrien while (*cp) 44359243Sobrien cp++; 44459243Sobrien return (cp); 44559243Sobrien} 44659243Sobrien 44759243Sobrien#endif /* SHORT_STRINGS */ 44859243Sobrien 44959243SobrienChar * 45059243Sobrienstrip(cp) 45159243Sobrien Char *cp; 45259243Sobrien{ 45359243Sobrien register Char *dp = cp; 45459243Sobrien 45559243Sobrien if (!cp) 45659243Sobrien return (cp); 45759243Sobrien while ((*dp++ &= TRIM) != '\0') 45859243Sobrien continue; 45959243Sobrien return (cp); 46059243Sobrien} 46159243Sobrien 46259243SobrienChar * 46359243Sobrienquote(cp) 46459243Sobrien Char *cp; 46559243Sobrien{ 46659243Sobrien register Char *dp = cp; 46759243Sobrien 46859243Sobrien if (!cp) 46959243Sobrien return (cp); 47059243Sobrien while (*dp != '\0') 47159243Sobrien *dp++ |= QUOTE; 47259243Sobrien return (cp); 47359243Sobrien} 47459243Sobrien 47559243SobrienChar * 47659243Sobrienquote_meta(d, s) 47759243Sobrien Char *d; 47859243Sobrien const Char *s; 47959243Sobrien{ 48059243Sobrien Char *r = d; 48159243Sobrien while (*s != '\0') { 48259243Sobrien if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB)) 48359243Sobrien *d++ = '\\'; 48459243Sobrien *d++ = *s++; 48559243Sobrien } 48659243Sobrien *d = '\0'; 48759243Sobrien return r; 48859243Sobrien} 48959243Sobrien 49059243Sobrienvoid 49159243Sobrienudvar(name) 49259243Sobrien Char *name; 49359243Sobrien{ 49459243Sobrien 49559243Sobrien setname(short2str(name)); 49659243Sobrien stderror(ERR_NAME | ERR_UNDVAR); 49759243Sobrien} 49859243Sobrien 49959243Sobrienint 50059243Sobrienprefix(sub, str) 50159243Sobrien register Char *sub, *str; 50259243Sobrien{ 50359243Sobrien 50459243Sobrien for (;;) { 50559243Sobrien if (*sub == 0) 50659243Sobrien return (1); 50759243Sobrien if (*str == 0) 50859243Sobrien return (0); 50959243Sobrien if ((*sub++ & TRIM) != (*str++ & TRIM)) 51059243Sobrien return (0); 51159243Sobrien } 51259243Sobrien} 513