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