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