xref: /illumos-gate/usr/src/cmd/csh/sh.misc.c (revision 65b0c20e)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 /*
10  * Copyright (c) 1980 Regents of the University of California.
11  * All rights reserved.  The Berkeley Software License Agreement
12  * specifies the terms and conditions for redistribution.
13  */
14 
15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
16 
17 #include "sh.h"
18 #include "sh.tconst.h"
19 #include <fcntl.h>
20 #include <unistd.h>
21 
22 /*
23  * C Shell
24  */
25 tchar	**blkcat(tchar **, tchar **);
26 tchar	**blkend(tchar **);
27 
28 int
29 any(int c, tchar *s)
30 {
31 
32 	while (s && *s)
33 		if (*s++ == c)
34 			return (1);
35 	return (0);
36 }
37 
38 int
39 onlyread(tchar *cp)
40 {
41 	extern char end[];
42 
43 	return ((char *)cp < end);
44 }
45 
46 tchar *
47 savestr(tchar *s)
48 {
49 	tchar *n;
50 	tchar *p;
51 
52 	if (s == 0)
53 		s = S_ /* "" */;
54 #ifndef m32
55 	for (p = s; *p++; )
56 		;
57 	n = p = (tchar *)xalloc((unsigned)(p - s)*sizeof (tchar));
58 	while (*p++ = *s++)
59 		;
60 	return (n);
61 #else
62 	p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar));
63 	strcpy_(p, s);
64 	return (p);
65 #endif
66 }
67 
68 static void *
69 nomem(size_t i)
70 {
71 #ifdef debug
72 	static tchar *av[2] = {0, 0};
73 #endif
74 
75 	child++;
76 #ifndef debug
77 	error("Out of memory");
78 #ifdef lint
79 	i = i;
80 #endif
81 #else
82 	showall(av);
83 	printf("i=%d: Out of memory\n", i);
84 	chdir("/usr/bill/cshcore");
85 	abort();
86 #endif
87 	return (0);		/* fool lint */
88 }
89 
90 tchar **
91 blkend(tchar **up)
92 {
93 
94 	while (*up)
95 		up++;
96 	return (up);
97 }
98 
99 void
100 blkpr(tchar **av)
101 {
102 
103 	for (; *av; av++) {
104 		printf("%t", *av);
105 		if (av[1])
106 			printf(" ");
107 	}
108 }
109 
110 int
111 blklen(tchar **av)
112 {
113 	int i = 0;
114 
115 	while (*av++)
116 		i++;
117 	return (i);
118 }
119 
120 tchar **
121 blkcpy(tchar **oav, tchar **bv)
122 {
123 	tchar **av = oav;
124 
125 	while (*av++ = *bv++)
126 		continue;
127 	return (oav);
128 }
129 
130 tchar **
131 blkcat(tchar **up, tchar **vp)
132 {
133 
134 	(void) blkcpy(blkend(up), vp);
135 	return (up);
136 }
137 
138 void
139 blkfree(tchar **av0)
140 {
141 	tchar **av = av0;
142 
143 	for (; *av; av++)
144 		xfree(*av);
145 	xfree(av0);
146 }
147 
148 tchar **
149 saveblk(tchar **v)
150 {
151 	tchar **newv =
152 		(tchar **)xcalloc((unsigned)(blklen(v) + 1),
153 				sizeof (tchar **));
154 	tchar **onewv = newv;
155 
156 	while (*v)
157 		*newv++ = savestr(*v++);
158 	return (onewv);
159 }
160 
161 tchar *
162 strspl(tchar *cp, tchar *dp)
163 {
164 	tchar *ep;
165 	tchar *p, *q;
166 
167 #ifndef m32
168 	for (p = cp; *p++; )
169 		;
170 	for (q = dp; *q++; )
171 		;
172 	ep = (tchar *) xalloc((unsigned)(((p - cp) +
173 			(q - dp) - 1))*sizeof (tchar));
174 	for (p = ep, q = cp; *p++ = *q++; )
175 		;
176 	for (p--, q = dp; *p++ = *q++; )
177 		;
178 #else
179 	int	len1 = strlen_(cp);
180 	int	len2 = strlen_(dp);
181 
182 	ep = (tchar *)xalloc((unsigned)(len1 + len2 + 1)*sizeof (tchar));
183 	strcpy_(ep, cp);
184 	strcat_(ep, dp);
185 #endif
186 	return (ep);
187 }
188 
189 tchar **
190 blkspl(tchar **up, tchar **vp)
191 {
192 	tchar **wp =
193 		(tchar **)xcalloc((unsigned)(blklen(up) + blklen(vp) + 1),
194 			sizeof (tchar **));
195 
196 	(void) blkcpy(wp, up);
197 	return (blkcat(wp, vp));
198 }
199 
200 int
201 lastchr(tchar *cp)
202 {
203 
204 	if (!*cp)
205 		return (0);
206 	while (cp[1])
207 		cp++;
208 	return (*cp);
209 }
210 
211 void
212 donefds(void)
213 {
214 	(void) close(0);
215 	(void) close(1);
216 	(void) close(2);
217 
218 	/*
219 	 * To avoid NIS+ functions to get hold of 0/1/2,
220 	 * use descriptor 0, and dup it to 1 and 2.
221 	 */
222 	open("/dev/null", 0);
223 	dup(0); dup(0);
224 	didfds = 0;
225 }
226 
227 /*
228  * Move descriptor i to j.
229  * If j is -1 then we just want to get i to a safe place,
230  * i.e. to a unit > 2.  This also happens in dcopy.
231  */
232 int
233 dmove(int i, int j)
234 {
235 	int fd;
236 
237 	if (i == j || i < 0)
238 		return (i);
239 	if (j >= 0) {
240 		fd = dup2(i, j);
241 		if (fd != -1)
242 			setfd(fd);
243 	} else
244 		j = dcopy(i, j);
245 	if (j != i) {
246 		(void) close(i);
247 		unsetfd(i);
248 	}
249 	return (j);
250 }
251 
252 int
253 dcopy(int i, int j)
254 {
255 
256 	int fd;
257 
258 	if (i == j || i < 0 || j < 0 && i > 2)
259 		return (i);
260 	if (j >= 0) {
261 		fd = dup2(i, j);
262 		if (fd != -1)
263 			setfd(fd);
264 		return (j);
265 	}
266 	(void) close(j);
267 	unsetfd(j);
268 	return (renum(i, j));
269 }
270 
271 int
272 renum(int i, int j)
273 {
274 	int k = dup(i);
275 
276 	if (k < 0)
277 		return (-1);
278 	if (j == -1 && k > 2) {
279 		setfd(k);
280 		return (k);
281 	}
282 	if (k != j) {
283 		j = renum(k, j);
284 		(void) close(k);	/* no need ofr unsetfd() */
285 		return (j);
286 	}
287 	return (k);
288 }
289 
290 #ifndef copy
291 void
292 copy(tchar *to, tchar *from, int size)
293 {
294 
295 	if (size)
296 		do
297 			*to++ = *from++;
298 		while (--size != 0);
299 }
300 #endif
301 
302 /*
303  * Left shift a command argument list, discarding
304  * the first c arguments.  Used in "shift" commands
305  * as well as by commands like "repeat".
306  */
307 void
308 lshift(tchar **v, int c)
309 {
310 	tchar **u = v;
311 
312 	while (*u && --c >= 0)
313 		xfree((char *)*u++);
314 	(void) blkcpy(v, u);
315 }
316 
317 int
318 number(tchar *cp)
319 {
320 
321 	if (*cp == '-') {
322 		cp++;
323 		if (!digit(*cp++))
324 			return (0);
325 	}
326 	while (*cp && digit(*cp))
327 		cp++;
328 	return (*cp == 0);
329 }
330 
331 tchar **
332 copyblk(tchar **v)
333 {
334 	tchar **nv =
335 		(tchar **)xcalloc((unsigned)(blklen(v) + 1),
336 				sizeof (tchar **));
337 
338 	return (blkcpy(nv, v));
339 }
340 
341 tchar *
342 strend(tchar *cp)
343 {
344 
345 	while (*cp)
346 		cp++;
347 	return (cp);
348 }
349 
350 tchar *
351 strip(tchar *cp)
352 {
353 	tchar *dp = cp;
354 
355 	while (*dp++ &= TRIM)
356 		continue;
357 	return (cp);
358 }
359 
360 void
361 udvar(tchar *name)
362 {
363 
364 	setname(name);
365 	bferr("Undefined variable");
366 }
367 
368 int
369 prefix(tchar *sub, tchar *str)
370 {
371 
372 	for (;;) {
373 		if (*sub == 0)
374 			return (1);
375 		if (*str == 0)
376 			return (0);
377 		if (*sub++ != *str++)
378 			return (0);
379 	}
380 }
381 
382 /*
383  * blk*_ routines
384  */
385 
386 char **
387 blkend_(char **up)
388 {
389 
390 	while (*up)
391 		up++;
392 	return (up);
393 }
394 
395 int
396 blklen_(char **av)
397 {
398 	int i = 0;
399 
400 	while (*av++)
401 		i++;
402 	return (i);
403 }
404 
405 char **
406 blkcpy_(char **oav, char **bv)
407 {
408 	char **av = oav;
409 
410 	while (*av++ = *bv++)
411 		continue;
412 	return (oav);
413 }
414 
415 char **
416 blkcat_(char **up, char **vp)
417 {
418 
419 	(void) blkcpy_(blkend_(up), vp);
420 	return (up);
421 }
422 
423 char **
424 blkspl_(char **up, char **vp)
425 {
426 	char **wp =
427 		(char **)xcalloc((unsigned)(blklen_(up) + blklen_(vp) + 1),
428 			sizeof (char **));
429 
430 	(void) blkcpy_(wp, up);
431 	return (blkcat_(wp, vp));
432 }
433 
434 /*
435  * If stack address was passed to free(), we have no good way to see if
436  * they are really in the stack. Therefore, we record the bottom of heap,
437  * and filter out the address not within heap's top(end) and bottom
438  * (xalloc_bottom).
439  */
440 extern char	end[];
441 static char	*xalloc_bottom;
442 
443 void *
444 xalloc(size_t size)
445 {
446 	char	*rptr, *bp;
447 
448 	if ((rptr = malloc(size)) == NULL)
449 		return (nomem(size));
450 	bp = rptr + size;
451 	if (bp > xalloc_bottom)
452 		xalloc_bottom = bp;
453 	return (rptr);
454 }
455 
456 void *
457 xrealloc(void *ptr, size_t size)
458 {
459 	char	*rptr = ptr, *bp;
460 
461 	if (ptr == NULL)
462 		return (xalloc(size));
463 	if (rptr < end) {
464 		/* data area, but not in heap area. don't touch it */
465 oob:
466 		if (size == 0)
467 			return (NULL);
468 		rptr = xalloc(size);
469 		/* copy max size */
470 		(void) memcpy(rptr, ptr, size);
471 		return (rptr);
472 	}
473 	if (rptr < xalloc_bottom) {
474 		/* address in the heap */
475 inb:
476 		if (size == 0) {
477 			free(ptr);
478 			return (NULL);
479 		}
480 		if ((rptr = realloc(ptr, size)) == NULL)
481 			return (nomem(size));
482 		bp = rptr + size;
483 		if (bp > xalloc_bottom)
484 			xalloc_bottom = bp;
485 		return (rptr);
486 	}
487 #if defined(__sparc)
488 	if (rptr > (char *)&rptr) {
489 		/* in the stack frame */
490 		goto oob;
491 	}
492 #endif
493 	/*
494 	 * can be a memory block returned indirectly from
495 	 * library functions. update bottom, and check it again.
496 	 */
497 	xalloc_bottom = sbrk(0);
498 	if (rptr <= xalloc_bottom)
499 		goto inb;
500 	else
501 		goto oob;
502 	/*NOTREACHED*/
503 }
504 
505 void
506 xfree(void *ptr)
507 {
508 	char	*rptr = ptr;
509 
510 	if (rptr < end) {
511 		return;
512 	}
513 	if (rptr < xalloc_bottom) {
514 		free(ptr);
515 		return;
516 	}
517 #if defined(__sparc)
518 	if (rptr > (char *)&rptr) {
519 		/* in the stack frame */
520 		return;
521 	}
522 #endif
523 	xalloc_bottom = sbrk(0);
524 	if (rptr <= xalloc_bottom) {
525 		free(ptr);
526 	}
527 }
528 
529 void *
530 xcalloc(size_t i, size_t j)
531 {
532 	char *cp;
533 
534 	i *= j;
535 	cp = xalloc(i);
536 	(void) memset(cp, '\0', i);
537 	return (cp);
538 }
539