sh.misc.c revision 131962
1117845Ssam/* $Header: /src/pub/tcsh/sh.misc.c,v 3.26 2003/03/12 19:14:51 christos Exp $ */
2117845Ssam/*
3117845Ssam * sh.misc.c: Miscelaneous functions
4117845Ssam */
5117845Ssam/*-
6117845Ssam * Copyright (c) 1980, 1991 The Regents of the University of California.
7117845Ssam * All rights reserved.
8117845Ssam *
9117845Ssam * Redistribution and use in source and binary forms, with or without
10117845Ssam * modification, are permitted provided that the following conditions
11117845Ssam * are met:
12117845Ssam * 1. Redistributions of source code must retain the above copyright
13117845Ssam *    notice, this list of conditions and the following disclaimer.
14117845Ssam * 2. Redistributions in binary form must reproduce the above copyright
15117845Ssam *    notice, this list of conditions and the following disclaimer in the
16117845Ssam *    documentation and/or other materials provided with the distribution.
17117845Ssam * 3. Neither the name of the University nor the names of its contributors
18117845Ssam *    may be used to endorse or promote products derived from this software
19117845Ssam *    without specific prior written permission.
20117845Ssam *
21117845Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22117845Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23117845Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24117845Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25117845Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26117845Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27117845Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28117845Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29117845Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30117845Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31117845Ssam * SUCH DAMAGE.
32117845Ssam */
33117845Ssam#include "sh.h"
34117845Ssam
35117845SsamRCSID("$Id: sh.misc.c,v 3.26 2003/03/12 19:14:51 christos Exp $")
36117845Ssam
37117845Ssamstatic	int	renum	__P((int, int));
38117845Ssamstatic  Char  **blkend	__P((Char **));
39117845Ssamstatic  Char  **blkcat	__P((Char **, Char **));
40117845Ssam
41117845Ssam/*
42117845Ssam * C Shell
43117845Ssam */
44117845Ssam
45117845Ssamint
46117845Ssamany(s, c)
47117845Ssam    register char *s;
48117845Ssam    register int c;
49117845Ssam{
50117845Ssam    if (!s)
51117845Ssam	return (0);		/* Check for nil pointer */
52117845Ssam    while (*s)
53117845Ssam	if (*s++ == c)
54117845Ssam	    return (1);
55117845Ssam    return (0);
56117845Ssam}
57117845Ssam
58117845Ssamvoid
59117845Ssamsetzero(cp, i)
60117845Ssam    char   *cp;
61117845Ssam    int     i;
62117845Ssam{
63117845Ssam    if (i != 0)
64117845Ssam	do
65117845Ssam	    *cp++ = 0;
66117845Ssam	while (--i);
67117845Ssam}
68117845Ssam
69117845Ssamchar   *
70117845Ssamstrsave(s)
71117845Ssam    register const char *s;
72117845Ssam{
73117845Ssam    char   *n;
74117845Ssam    register char *p;
75117845Ssam
76117845Ssam    if (s == NULL)
77117845Ssam	s = (const char *) "";
78117845Ssam    for (p = (char *) s; *p++ != '\0';)
79117845Ssam	continue;
80117845Ssam    n = p = (char *) xmalloc((size_t)
81117845Ssam			     ((((const char *) p) - s) * sizeof(char)));
82117845Ssam    while ((*p++ = *s++) != '\0')
83117845Ssam	continue;
84117845Ssam    return (n);
85117845Ssam}
86117845Ssam
87117845Ssamstatic Char  **
88117845Ssamblkend(up)
89117845Ssam    register Char **up;
90117845Ssam{
91117845Ssam
92117845Ssam    while (*up)
93117845Ssam	up++;
94117845Ssam    return (up);
95117845Ssam}
96117845Ssam
97117845Ssam
98117845Ssamvoid
99117845Ssamblkpr(av)
100117845Ssam    register Char **av;
101117845Ssam{
102117845Ssam
103117845Ssam    for (; *av; av++) {
104117845Ssam	xprintf("%S", *av);
105117845Ssam	if (av[1])
106117845Ssam	    xprintf(" ");
107117845Ssam    }
108117845Ssam}
109117845Ssam
110117845Ssamvoid
111117845Ssamblkexpand(av, str)
112117845Ssam    register Char **av;
113117845Ssam    Char *str;
114117845Ssam{
115117845Ssam    *str = '\0';
116117845Ssam    for (; *av; av++) {
117117845Ssam	(void) Strcat(str, *av);
118117845Ssam	if (av[1])
119117845Ssam	    (void) Strcat(str, STRspace);
120117845Ssam    }
121117845Ssam}
122117845Ssam
123117845Ssamint
124117845Ssamblklen(av)
125117845Ssam    register Char **av;
126117845Ssam{
127117845Ssam    register int i = 0;
128117845Ssam
129117845Ssam    while (*av++)
130117845Ssam	i++;
131117845Ssam    return (i);
132117845Ssam}
133117845Ssam
134117845SsamChar  **
135117845Ssamblkcpy(oav, bv)
136117845Ssam    Char  **oav;
137117845Ssam    register Char **bv;
138117845Ssam{
139117845Ssam    register Char **av = oav;
140117845Ssam
141117845Ssam    while ((*av++ = *bv++) != NULL)
142117845Ssam	continue;
143117845Ssam    return (oav);
144117845Ssam}
145117845Ssam
146117845Ssamstatic Char  **
147117845Ssamblkcat(up, vp)
148117845Ssam    Char  **up, **vp;
149117845Ssam{
150117845Ssam
151117845Ssam    (void) blkcpy(blkend(up), vp);
152117845Ssam    return (up);
153117845Ssam}
154117845Ssam
155117845Ssamvoid
156117845Ssamblkfree(av0)
157117845Ssam    Char  **av0;
158117845Ssam{
159117845Ssam    register Char **av = av0;
160117845Ssam
161117845Ssam    if (!av0)
162117845Ssam	return;
163117845Ssam    for (; *av; av++)
164117845Ssam	xfree((ptr_t) * av);
165117845Ssam    xfree((ptr_t) av0);
166117845Ssam}
167117845Ssam
168117845SsamChar  **
169117845Ssamsaveblk(v)
170117845Ssam    register Char **v;
171117845Ssam{
172117845Ssam    register Char **newv =
173117845Ssam    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
174117845Ssam    Char  **onewv = newv;
175117845Ssam
176117845Ssam    while (*v)
177117845Ssam	*newv++ = Strsave(*v++);
178117845Ssam    return (onewv);
179117845Ssam}
180117845Ssam
181117845Ssam#if !defined(SHORT_STRINGS) && !defined(POSIX)
182117845Ssamchar   *
183117845Ssamstrstr(s, t)
184117845Ssam    register const char *s, *t;
185117845Ssam{
186117845Ssam    do {
187117845Ssam	register const char *ss = s;
188117845Ssam	register const char *tt = t;
189117845Ssam
190117845Ssam	do
191117845Ssam	    if (*tt == '\0')
192117845Ssam		return ((char *) s);
193117845Ssam	while (*ss++ == *tt++);
194117845Ssam    } while (*s++ != '\0');
195117845Ssam    return (NULL);
196117845Ssam}
197117845Ssam
198117845Ssam#endif /* !SHORT_STRINGS && !POSIX */
199117845Ssam
200117845Ssam#ifndef SHORT_STRINGS
201117845Ssamchar   *
202117845Ssamstrspl(cp, dp)
203117845Ssam    char   *cp, *dp;
204117845Ssam{
205117845Ssam    char   *ep;
206117845Ssam    register char *p, *q;
207117845Ssam
208117845Ssam    if (!cp)
209117845Ssam	cp = "";
210117845Ssam    if (!dp)
211117845Ssam	dp = "";
212117845Ssam    for (p = cp; *p++ != '\0';)
213117845Ssam	continue;
214117845Ssam    for (q = dp; *q++ != '\0';)
215117845Ssam	continue;
216117845Ssam    ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
217117845Ssam    for (p = ep, q = cp; (*p++ = *q++) != '\0';)
218117845Ssam	continue;
219117845Ssam    for (p--, q = dp; (*p++ = *q++) != '\0';)
220117845Ssam	continue;
221117845Ssam    return (ep);
222117845Ssam}
223117845Ssam
224117845Ssam#endif /* !SHORT_STRINGS */
225117845Ssam
226117845SsamChar  **
227117845Ssamblkspl(up, vp)
228117845Ssam    register Char **up, **vp;
229117845Ssam{
230117845Ssam    register Char **wp =
231117845Ssam    (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
232117845Ssam		      sizeof(Char **));
233117845Ssam
234117845Ssam    (void) blkcpy(wp, up);
235117845Ssam    return (blkcat(wp, vp));
236117845Ssam}
237117845Ssam
238117845SsamChar
239117845Ssamlastchr(cp)
240117845Ssam    register Char *cp;
241117845Ssam{
242117845Ssam
243117845Ssam    if (!cp)
244117845Ssam	return (0);
245117845Ssam    if (!*cp)
246117845Ssam	return (0);
247117845Ssam    while (cp[1])
248117845Ssam	cp++;
249117845Ssam    return (*cp);
250117845Ssam}
251117845Ssam
252117845Ssam/*
253117845Ssam * This routine is called after an error to close up
254117845Ssam * any units which may have been left open accidentally.
255117845Ssam */
256117845Ssamvoid
257117845Ssamclosem()
258117845Ssam{
259117845Ssam    register int f;
260117845Ssam
261117845Ssam#ifdef NLS_BUGS
262117845Ssam#ifdef NLS_CATALOGS
263117845Ssam    (void)catclose(catd);
264117845Ssam#endif /* NLS_CATALOGS */
265117845Ssam#endif /* NLS_BUGS */
266117845Ssam#ifdef YPBUGS
267117845Ssam    /* suggested by Justin Bur; thanks to Karl Kleinpaste */
268117845Ssam    fix_yp_bugs();
269117845Ssam#endif /* YPBUGS */
270117845Ssam    for (f = 0; f < NOFILE; f++)
271117845Ssam	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
272117845Ssam	    f != FSHTTY
273117845Ssam#ifdef MALLOC_TRACE
274117845Ssam	    && f != 25
275117845Ssam#endif /* MALLOC_TRACE */
276117845Ssam	    )
277117845Ssam	  {
278117845Ssam	    (void) close(f);
279117845Ssam#ifdef NISPLUS
280117845Ssam	    if(f < 3)
281117845Ssam		(void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
282117845Ssam#endif /* NISPLUS */
283117845Ssam	  }
284117845Ssam#ifdef NLS_BUGS
285117845Ssam#ifdef NLS_CATALOGS
286117845Ssam    nlsinit();
287117845Ssam#endif /* NLS_CATALOGS */
288117845Ssam#endif /* NLS_BUGS */
289117845Ssam}
290117845Ssam
291117845Ssam#ifndef CLOSE_ON_EXEC
292117845Ssam/*
293117845Ssam * Close files before executing a file.
294117845Ssam * We could be MUCH more intelligent, since (on a version 7 system)
295117845Ssam * we need only close files here during a source, the other
296117845Ssam * shell fd's being in units 16-19 which are closed automatically!
297117845Ssam */
298117845Ssamvoid
299117845Ssamclosech()
300117845Ssam{
301117845Ssam    register int f;
302117845Ssam
303117845Ssam    if (didcch)
304117845Ssam	return;
305117845Ssam    didcch = 1;
306117845Ssam    SHIN = 0;
307117845Ssam    SHOUT = 1;
308117845Ssam    SHDIAG = 2;
309117845Ssam    OLDSTD = 0;
310117845Ssam    isoutatty = isatty(SHOUT);
311117845Ssam    isdiagatty = isatty(SHDIAG);
312117845Ssam    for (f = 3; f < NOFILE; f++)
313117845Ssam	(void) close(f);
314117845Ssam}
315117845Ssam
316117845Ssam#endif /* CLOSE_ON_EXEC */
317117845Ssam
318117845Ssamvoid
319117845Ssamdonefds()
320117845Ssam{
321117845Ssam
322117845Ssam    (void) close(0);
323117845Ssam    (void) close(1);
324117845Ssam    (void) close(2);
325117845Ssam    didfds = 0;
326117845Ssam#ifdef NISPLUS
327117845Ssam    {
328117845Ssam	int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
329117845Ssam	(void) dup2(fd, 1);
330117845Ssam	(void) dup2(fd, 2);
331117845Ssam	if (fd != 0) {
332117845Ssam	    (void) dup2(fd, 0);
333117845Ssam	    (void) close(fd);
334117845Ssam	}
335117845Ssam    }
336117845Ssam#endif /*NISPLUS*/
337117845Ssam}
338117845Ssam
339117845Ssam/*
340117845Ssam * Move descriptor i to j.
341117845Ssam * If j is -1 then we just want to get i to a safe place,
342117845Ssam * i.e. to a unit > 2.  This also happens in dcopy.
343117845Ssam */
344117845Ssamint
345117845Ssamdmove(i, j)
346117845Ssam    register int i, j;
347117845Ssam{
348117845Ssam
349117845Ssam    if (i == j || i < 0)
350117845Ssam	return (i);
351117845Ssam#ifdef HAVEDUP2
352117845Ssam    if (j >= 0) {
353117845Ssam	(void) dup2(i, j);
354117845Ssam	if (j != i)
355117845Ssam	    (void) close(i);
356117845Ssam	return (j);
357117845Ssam    }
358117845Ssam#endif
359117845Ssam    j = dcopy(i, j);
360117845Ssam    if (j != i)
361117845Ssam	(void) close(i);
362117845Ssam    return (j);
363117845Ssam}
364117845Ssam
365117845Ssamint
366117845Ssamdcopy(i, j)
367117845Ssam    register int i, j;
368117845Ssam{
369117845Ssam
370117845Ssam    if (i == j || i < 0 || (j < 0 && i > 2))
371117845Ssam	return (i);
372117845Ssam    if (j >= 0) {
373117845Ssam#ifdef HAVEDUP2
374117845Ssam	(void) dup2(i, j);
375117845Ssam	return (j);
376117845Ssam#else
377117845Ssam	(void) close(j);
378117845Ssam#endif
379117845Ssam    }
380117845Ssam    return (renum(i, j));
381117845Ssam}
382117845Ssam
383117845Ssamstatic int
384117845Ssamrenum(i, j)
385117845Ssam    register int i, j;
386117845Ssam{
387117845Ssam    register int k = dup(i);
388117845Ssam
389117845Ssam    if (k < 0)
390117845Ssam	return (-1);
391117845Ssam    if (j == -1 && k > 2)
392117845Ssam	return (k);
393117845Ssam    if (k != j) {
394117845Ssam	j = renum(k, j);
395117845Ssam	(void) close(k);
396117845Ssam	return (j);
397117845Ssam    }
398117845Ssam    return (k);
399117845Ssam}
400117845Ssam
401117845Ssam/*
402117845Ssam * Left shift a command argument list, discarding
403117845Ssam * the first c arguments.  Used in "shift" commands
404117845Ssam * as well as by commands like "repeat".
405117845Ssam */
406117845Ssamvoid
407117845Ssamlshift(v, c)
408117845Ssam    register Char **v;
409117845Ssam    register int c;
410117845Ssam{
411117845Ssam    register Char **u;
412117845Ssam
413    for (u = v; *u && --c >= 0; u++)
414	xfree((ptr_t) *u);
415    (void) blkcpy(v, u);
416}
417
418int
419number(cp)
420    Char   *cp;
421{
422    if (!cp)
423	return (0);
424    if (*cp == '-') {
425	cp++;
426	if (!Isdigit(*cp))
427	    return (0);
428	cp++;
429    }
430    while (*cp && Isdigit(*cp))
431	cp++;
432    return (*cp == 0);
433}
434
435Char  **
436copyblk(v)
437    register Char **v;
438{
439    register Char **nv =
440    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
441
442    return (blkcpy(nv, v));
443}
444
445#ifndef SHORT_STRINGS
446char   *
447strend(cp)
448    register char *cp;
449{
450    if (!cp)
451	return (cp);
452    while (*cp)
453	cp++;
454    return (cp);
455}
456
457#endif /* SHORT_STRINGS */
458
459Char   *
460strip(cp)
461    Char   *cp;
462{
463    register Char *dp = cp;
464
465    if (!cp)
466	return (cp);
467    while ((*dp++ &= TRIM) != '\0')
468	continue;
469    return (cp);
470}
471
472Char   *
473quote(cp)
474    Char   *cp;
475{
476    register Char *dp = cp;
477
478    if (!cp)
479	return (cp);
480    while (*dp != '\0')
481	*dp++ |= QUOTE;
482    return (cp);
483}
484
485Char   *
486quote_meta(d, s)
487    Char   *d;
488    const Char   *s;
489{
490    Char *r = d;
491    while (*s != '\0') {
492	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
493		*d++ = '\\';
494	*d++ = *s++;
495    }
496    *d = '\0';
497    return r;
498}
499
500void
501udvar(name)
502    Char   *name;
503{
504
505    setname(short2str(name));
506    stderror(ERR_NAME | ERR_UNDVAR);
507}
508
509int
510prefix(sub, str)
511    register Char *sub, *str;
512{
513
514    for (;;) {
515	if (*sub == 0)
516	    return (1);
517	if (*str == 0)
518	    return (0);
519	if ((*sub++ & TRIM) != (*str++ & TRIM))
520	    return (0);
521    }
522}
523