1/* $NetBSD: misc.c,v 1.23 2024/04/24 15:49:03 nia Exp $ */
2
3/*-
4 * Copyright (c) 1980, 1991, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#ifndef lint
34#if 0
35static char sccsid[] = "@(#)misc.c	8.1 (Berkeley) 5/31/93";
36#else
37__RCSID("$NetBSD: misc.c,v 1.23 2024/04/24 15:49:03 nia Exp $");
38#endif
39#endif /* not lint */
40
41#include <sys/param.h>
42
43#include <stdarg.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47#include <fcntl.h>
48
49#include "csh.h"
50#include "extern.h"
51
52static int renum(int, int);
53
54int
55any(const char *s, int c)
56{
57    if (!s)
58	return (0);		/* Check for nil pointer */
59    while (*s)
60	if (*s++ == c)
61	    return (1);
62    return (0);
63}
64
65char *
66strsave(const char *s)
67{
68    const char *n;
69    char *p, *r;
70
71    if (s == NULL)
72	s = "";
73    for (n = s; *n++;)
74	continue;
75    r = p = xreallocarray(NULL, (size_t)(n - s), sizeof(*p));
76    while ((*p++ = *s++) != '\0')
77	continue;
78    return (r);
79}
80
81Char **
82blkend(Char **up)
83{
84    while (*up)
85	up++;
86    return (up);
87}
88
89
90void
91blkpr(FILE *fp, Char **av)
92{
93    for (; *av; av++) {
94	(void)fprintf(fp, "%s", vis_str(*av));
95	if (av[1])
96	    (void)fprintf(fp, " ");
97    }
98}
99
100int
101blklen(Char **av)
102{
103    int i;
104
105    i = 0;
106    while (*av++)
107	i++;
108    return (i);
109}
110
111Char **
112blkcpy(Char **oav, Char **bv)
113{
114    Char **av;
115
116    av = oav;
117    while ((*av++ = *bv++) != NULL)
118	continue;
119    return (oav);
120}
121
122Char **
123blkcat(Char **up, Char **vp)
124{
125    (void)blkcpy(blkend(up), vp);
126    return (up);
127}
128
129void
130blkfree(Char **av0)
131{
132    Char **av;
133
134    av = av0;
135    if (!av0)
136	return;
137    for (; *av; av++)
138	free(* av);
139    free(av0);
140}
141
142Char **
143saveblk(Char **v)
144{
145    Char **newv, **onewv;
146
147    if (v == NULL)
148	return NULL;
149
150    newv = xcalloc((size_t)(blklen(v) + 1), sizeof(*newv));
151    onewv = newv;
152    while (*v)
153	*newv++ = Strsave(*v++);
154    return (onewv);
155}
156
157#ifdef NOTUSED
158char *
159strstr(char *s, char *t)
160{
161    do {
162	char *ss;
163	char *tt;
164
165	ss = s;
166	tt = t;
167
168	do
169	    if (*tt == '\0')
170		return (s);
171	while (*ss++ == *tt++);
172    } while (*s++ != '\0');
173    return (NULL);
174}
175
176#endif /* NOTUSED */
177
178#ifndef SHORT_STRINGS
179char *
180strspl(char *cp, char *dp)
181{
182    char *ep, *p, *q;
183
184    if (!cp)
185	cp = "";
186    if (!dp)
187	dp = "";
188    for (p = cp; *p++;)
189	continue;
190    for (q = dp; *q++;)
191	continue;
192    ep = xreallocarray(NULL, (size_t)(((p - cp) + (q - dp) - 1), sizeof(*ep)));
193    for (p = ep, q = cp; *p++ = *q++;)
194	continue;
195    for (p--, q = dp; *p++ = *q++;)
196	continue;
197    return (ep);
198}
199
200#endif
201
202Char **
203blkspl(Char **up, Char **vp)
204{
205    Char **wp;
206
207    wp = xcalloc((size_t)(blklen(up) + blklen(vp) + 1), sizeof(*wp));
208    (void)blkcpy(wp, up);
209    return (blkcat(wp, vp));
210}
211
212Char
213lastchr(Char *cp)
214{
215    if (!cp)
216	return (0);
217    if (!*cp)
218	return (0);
219    while (cp[1])
220	cp++;
221    return (*cp);
222}
223
224/*
225 * This routine is called after an error to close up
226 * any units which may have been left open accidentally.
227 */
228void
229closem(void)
230{
231    int f;
232    int nofile;
233
234#ifdef F_CLOSEM
235    nofile = FOLDSTD + 1;
236    if (fcntl(nofile, F_CLOSEM, 0) == -1)
237#endif
238	nofile = NOFILE;
239
240    for (f = 0; f < nofile; f++)
241	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
242	    f != FSHTTY)
243	    (void) close(f);
244}
245
246void
247donefds(void)
248{
249    (void)close(0);
250    (void)close(1);
251    (void)close(2);
252
253    didfds = 0;
254}
255
256/*
257 * Move descriptor i to j.
258 * If j is -1 then we just want to get i to a safe place,
259 * i.e. to a unit > 2.  This also happens in dcopy.
260 */
261int
262dmove(int i, int j)
263{
264    if (i == j || i < 0)
265	return (i);
266    if (j >= 0) {
267	(void)dup2(i, j);
268	if (j != i)
269	    (void)close(i);
270	return (j);
271    }
272    j = dcopy(i, j);
273    if (j != i)
274	(void)close(i);
275    return (j);
276}
277
278int
279dcopy(int i, int j)
280{
281    if (i == j || i < 0 || (j < 0 && i > 2))
282	return (i);
283    if (j >= 0) {
284	(void)dup2(i, j);
285	return (j);
286    }
287    return (renum(i, j));
288}
289
290static int
291renum(int i, int j)
292{
293    int k;
294
295    k = dup(i);
296    if (k < 0)
297	return (-1);
298    if (j == -1 && k > 2)
299	return (k);
300    if (k != j) {
301	j = renum(k, j);
302	(void)close(k);
303	return (j);
304    }
305    return (k);
306}
307
308/*
309 * Left shift a command argument list, discarding
310 * the first c arguments.  Used in "shift" commands
311 * as well as by commands like "repeat".
312 */
313void
314lshift(Char **v, size_t c)
315{
316    Char **u;
317
318    for (u = v; *u && c-- > 0; u++)
319	free(*u);
320    (void)blkcpy(v, u);
321}
322
323int
324number(Char *cp)
325{
326    if (!cp)
327	return(0);
328    if (*cp == '-') {
329	cp++;
330	if (!Isdigit(*cp))
331	    return (0);
332	cp++;
333    }
334    while (*cp && Isdigit(*cp))
335	cp++;
336    return (*cp == 0);
337}
338
339Char **
340copyblk(Char **v)
341{
342    Char **nv;
343
344    nv = xcalloc((size_t)(blklen(v) + 1), sizeof(*nv));
345
346    return (blkcpy(nv, v));
347}
348
349#ifndef SHORT_STRINGS
350char *
351strend(char *cp)
352{
353    if (!cp)
354	return (cp);
355    while (*cp)
356	cp++;
357    return (cp);
358}
359
360#endif /* SHORT_STRINGS */
361
362Char *
363strip(Char *cp)
364{
365    Char *dp;
366
367    dp = cp;
368    if (!cp)
369	return (cp);
370    while ((*dp++ &= TRIM) != '\0')
371	continue;
372    return (cp);
373}
374
375Char *
376quote(Char *cp)
377{
378    Char *dp;
379
380    dp = cp;
381    if (!cp)
382	return (cp);
383    while (*dp != '\0')
384	*dp++ |= QUOTE;
385    return (cp);
386}
387
388void
389udvar(Char *name)
390{
391    setname(vis_str(name));
392    stderror(ERR_NAME | ERR_UNDVAR);
393    /* NOTREACHED */
394}
395
396int
397prefix(Char *sub, Char *str)
398{
399    for (;;) {
400	if (*sub == 0)
401	    return (1);
402	if (*str == 0)
403	    return (0);
404	if (*sub++ != *str++)
405	    return (0);
406    }
407}
408