sh.misc.c revision 59243
1/* $Header: /src/pub/tcsh/sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $ */
2/*
3 * sh.misc.c: Miscelaneous functions
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.misc.c,v 3.23 1997/02/23 19:03:23 christos Exp $")
40
41static	int	renum	__P((int, int));
42static  Char  **blkend	__P((Char **));
43static  Char  **blkcat	__P((Char **, Char **));
44
45/*
46 * C Shell
47 */
48
49int
50any(s, c)
51    register char *s;
52    register int c;
53{
54    if (!s)
55	return (0);		/* Check for nil pointer */
56    while (*s)
57	if (*s++ == c)
58	    return (1);
59    return (0);
60}
61
62void
63setzero(cp, i)
64    char   *cp;
65    int     i;
66{
67    if (i != 0)
68	do
69	    *cp++ = 0;
70	while (--i);
71}
72
73char   *
74strsave(s)
75    register const char *s;
76{
77    char   *n;
78    register char *p;
79
80    if (s == NULL)
81	s = (const char *) "";
82    for (p = (char *) s; *p++ != '\0';)
83	continue;
84    n = p = (char *) xmalloc((size_t)
85			     ((((const char *) p) - s) * sizeof(char)));
86    while ((*p++ = *s++) != '\0')
87	continue;
88    return (n);
89}
90
91static Char  **
92blkend(up)
93    register Char **up;
94{
95
96    while (*up)
97	up++;
98    return (up);
99}
100
101
102void
103blkpr(av)
104    register Char **av;
105{
106
107    for (; *av; av++) {
108	xprintf("%S", *av);
109	if (av[1])
110	    xprintf(" ");
111    }
112}
113
114void
115blkexpand(av, str)
116    register Char **av;
117    Char *str;
118{
119    *str = '\0';
120    for (; *av; av++) {
121	(void) Strcat(str, *av);
122	if (av[1])
123	    (void) Strcat(str, STRspace);
124    }
125}
126
127int
128blklen(av)
129    register Char **av;
130{
131    register int i = 0;
132
133    while (*av++)
134	i++;
135    return (i);
136}
137
138Char  **
139blkcpy(oav, bv)
140    Char  **oav;
141    register Char **bv;
142{
143    register Char **av = oav;
144
145    while ((*av++ = *bv++) != NULL)
146	continue;
147    return (oav);
148}
149
150static Char  **
151blkcat(up, vp)
152    Char  **up, **vp;
153{
154
155    (void) blkcpy(blkend(up), vp);
156    return (up);
157}
158
159void
160blkfree(av0)
161    Char  **av0;
162{
163    register Char **av = av0;
164
165    if (!av0)
166	return;
167    for (; *av; av++)
168	xfree((ptr_t) * av);
169    xfree((ptr_t) av0);
170}
171
172Char  **
173saveblk(v)
174    register Char **v;
175{
176    register Char **newv =
177    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
178    Char  **onewv = newv;
179
180    while (*v)
181	*newv++ = Strsave(*v++);
182    return (onewv);
183}
184
185#if !defined(SHORT_STRINGS) && !defined(POSIX)
186char   *
187strstr(s, t)
188    register const char *s, *t;
189{
190    do {
191	register const char *ss = s;
192	register const char *tt = t;
193
194	do
195	    if (*tt == '\0')
196		return ((char *) s);
197	while (*ss++ == *tt++);
198    } while (*s++ != '\0');
199    return (NULL);
200}
201
202#endif /* !SHORT_STRINGS && !POSIX */
203
204#ifndef SHORT_STRINGS
205char   *
206strspl(cp, dp)
207    char   *cp, *dp;
208{
209    char   *ep;
210    register char *p, *q;
211
212    if (!cp)
213	cp = "";
214    if (!dp)
215	dp = "";
216    for (p = cp; *p++ != '\0';)
217	continue;
218    for (q = dp; *q++ != '\0';)
219	continue;
220    ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
221    for (p = ep, q = cp; (*p++ = *q++) != '\0';)
222	continue;
223    for (p--, q = dp; (*p++ = *q++) != '\0';)
224	continue;
225    return (ep);
226}
227
228#endif /* !SHORT_STRINGS */
229
230Char  **
231blkspl(up, vp)
232    register Char **up, **vp;
233{
234    register Char **wp =
235    (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
236		      sizeof(Char **));
237
238    (void) blkcpy(wp, up);
239    return (blkcat(wp, vp));
240}
241
242Char
243lastchr(cp)
244    register Char *cp;
245{
246
247    if (!cp)
248	return (0);
249    if (!*cp)
250	return (0);
251    while (cp[1])
252	cp++;
253    return (*cp);
254}
255
256/*
257 * This routine is called after an error to close up
258 * any units which may have been left open accidentally.
259 */
260void
261closem()
262{
263    register int f;
264
265#ifdef YPBUGS
266    /* suggested by Justin Bur; thanks to Karl Kleinpaste */
267    fix_yp_bugs();
268#endif /* YPBUGS */
269    for (f = 0; f < NOFILE; f++)
270	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
271	    f != FSHTTY
272#ifdef MALLOC_TRACE
273	    && f != 25
274#endif /* MALLOC_TRACE */
275	    )
276	  {
277	    (void) close(f);
278#ifdef NISPLUS
279	    if(f < 3)
280		(void) open(_PATH_DEVNULL, O_RDONLY);
281#endif /* NISPLUS */
282	  }
283}
284
285#ifndef CLOSE_ON_EXEC
286/*
287 * Close files before executing a file.
288 * We could be MUCH more intelligent, since (on a version 7 system)
289 * we need only close files here during a source, the other
290 * shell fd's being in units 16-19 which are closed automatically!
291 */
292void
293closech()
294{
295    register int f;
296
297    if (didcch)
298	return;
299    didcch = 1;
300    SHIN = 0;
301    SHOUT = 1;
302    SHDIAG = 2;
303    OLDSTD = 0;
304    isoutatty = isatty(SHOUT);
305    isdiagatty = isatty(SHDIAG);
306    for (f = 3; f < NOFILE; f++)
307	(void) close(f);
308}
309
310#endif /* CLOSE_ON_EXEC */
311
312void
313donefds()
314{
315
316    (void) close(0);
317    (void) close(1);
318    (void) close(2);
319    didfds = 0;
320#ifdef NISPLUS
321    {
322	int fd = open(_PATH_DEVNULL, O_RDONLY);
323	(void) dup2(fd, 1);
324	(void) dup2(fd, 2);
325	if (fd != 0) {
326	    (void) dup2(fd, 0);
327	    (void) close(fd);
328	}
329    }
330#endif /*NISPLUS*/
331}
332
333/*
334 * Move descriptor i to j.
335 * If j is -1 then we just want to get i to a safe place,
336 * i.e. to a unit > 2.  This also happens in dcopy.
337 */
338int
339dmove(i, j)
340    register int i, j;
341{
342
343    if (i == j || i < 0)
344	return (i);
345#ifdef HAVEDUP2
346    if (j >= 0) {
347	(void) dup2(i, j);
348	if (j != i)
349	    (void) close(i);
350	return (j);
351    }
352#endif
353    j = dcopy(i, j);
354    if (j != i)
355	(void) close(i);
356    return (j);
357}
358
359int
360dcopy(i, j)
361    register int i, j;
362{
363
364    if (i == j || i < 0 || (j < 0 && i > 2))
365	return (i);
366    if (j >= 0) {
367#ifdef HAVEDUP2
368	(void) dup2(i, j);
369	return (j);
370#else
371	(void) close(j);
372#endif
373    }
374    return (renum(i, j));
375}
376
377static int
378renum(i, j)
379    register int i, j;
380{
381    register int k = dup(i);
382
383    if (k < 0)
384	return (-1);
385    if (j == -1 && k > 2)
386	return (k);
387    if (k != j) {
388	j = renum(k, j);
389	(void) close(k);
390	return (j);
391    }
392    return (k);
393}
394
395/*
396 * Left shift a command argument list, discarding
397 * the first c arguments.  Used in "shift" commands
398 * as well as by commands like "repeat".
399 */
400void
401lshift(v, c)
402    register Char **v;
403    register int c;
404{
405    register Char **u;
406
407    for (u = v; *u && --c >= 0; u++)
408	xfree((ptr_t) *u);
409    (void) blkcpy(v, u);
410}
411
412int
413number(cp)
414    Char   *cp;
415{
416    if (!cp)
417	return (0);
418    if (*cp == '-') {
419	cp++;
420	if (!Isdigit(*cp))
421	    return (0);
422	cp++;
423    }
424    while (*cp && Isdigit(*cp))
425	cp++;
426    return (*cp == 0);
427}
428
429Char  **
430copyblk(v)
431    register Char **v;
432{
433    register Char **nv =
434    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
435
436    return (blkcpy(nv, v));
437}
438
439#ifndef SHORT_STRINGS
440char   *
441strend(cp)
442    register char *cp;
443{
444    if (!cp)
445	return (cp);
446    while (*cp)
447	cp++;
448    return (cp);
449}
450
451#endif /* SHORT_STRINGS */
452
453Char   *
454strip(cp)
455    Char   *cp;
456{
457    register Char *dp = cp;
458
459    if (!cp)
460	return (cp);
461    while ((*dp++ &= TRIM) != '\0')
462	continue;
463    return (cp);
464}
465
466Char   *
467quote(cp)
468    Char   *cp;
469{
470    register Char *dp = cp;
471
472    if (!cp)
473	return (cp);
474    while (*dp != '\0')
475	*dp++ |= QUOTE;
476    return (cp);
477}
478
479Char   *
480quote_meta(d, s)
481    Char   *d;
482    const Char   *s;
483{
484    Char *r = d;
485    while (*s != '\0') {
486	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
487		*d++ = '\\';
488	*d++ = *s++;
489    }
490    *d = '\0';
491    return r;
492}
493
494void
495udvar(name)
496    Char   *name;
497{
498
499    setname(short2str(name));
500    stderror(ERR_NAME | ERR_UNDVAR);
501}
502
503int
504prefix(sub, str)
505    register Char *sub, *str;
506{
507
508    for (;;) {
509	if (*sub == 0)
510	    return (1);
511	if (*str == 0)
512	    return (0);
513	if ((*sub++ & TRIM) != (*str++ & TRIM))
514	    return (0);
515    }
516}
517