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