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 */
25tchar	**blkcat(tchar **, tchar **);
26tchar	**blkend(tchar **);
27
28int
29any(int c, tchar *s)
30{
31
32	while (s && *s)
33		if (*s++ == c)
34			return (1);
35	return (0);
36}
37
38int
39onlyread(tchar *cp)
40{
41	extern char end[];
42
43	return ((char *)cp < end);
44}
45
46tchar *
47savestr(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
68static void *
69nomem(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
90tchar **
91blkend(tchar **up)
92{
93
94	while (*up)
95		up++;
96	return (up);
97}
98
99void
100blkpr(tchar **av)
101{
102
103	for (; *av; av++) {
104		printf("%t", *av);
105		if (av[1])
106			printf(" ");
107	}
108}
109
110int
111blklen(tchar **av)
112{
113	int i = 0;
114
115	while (*av++)
116		i++;
117	return (i);
118}
119
120tchar **
121blkcpy(tchar **oav, tchar **bv)
122{
123	tchar **av = oav;
124
125	while (*av++ = *bv++)
126		continue;
127	return (oav);
128}
129
130tchar **
131blkcat(tchar **up, tchar **vp)
132{
133
134	(void) blkcpy(blkend(up), vp);
135	return (up);
136}
137
138void
139blkfree(tchar **av0)
140{
141	tchar **av = av0;
142
143	for (; *av; av++)
144		xfree(*av);
145	xfree(av0);
146}
147
148tchar **
149saveblk(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
161tchar *
162strspl(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
189tchar **
190blkspl(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
200int
201lastchr(tchar *cp)
202{
203
204	if (!*cp)
205		return (0);
206	while (cp[1])
207		cp++;
208	return (*cp);
209}
210
211void
212donefds(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 */
232int
233dmove(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
252int
253dcopy(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
271int
272renum(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
291void
292copy(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 */
307void
308lshift(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
317int
318number(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
331tchar **
332copyblk(tchar **v)
333{
334	tchar **nv =
335		(tchar **)xcalloc((unsigned)(blklen(v) + 1),
336				sizeof (tchar **));
337
338	return (blkcpy(nv, v));
339}
340
341tchar *
342strend(tchar *cp)
343{
344
345	while (*cp)
346		cp++;
347	return (cp);
348}
349
350tchar *
351strip(tchar *cp)
352{
353	tchar *dp = cp;
354
355	while (*dp++ &= TRIM)
356		continue;
357	return (cp);
358}
359
360void
361udvar(tchar *name)
362{
363
364	setname(name);
365	bferr("Undefined variable");
366}
367
368int
369prefix(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
386char **
387blkend_(char **up)
388{
389
390	while (*up)
391		up++;
392	return (up);
393}
394
395int
396blklen_(char **av)
397{
398	int i = 0;
399
400	while (*av++)
401		i++;
402	return (i);
403}
404
405char **
406blkcpy_(char **oav, char **bv)
407{
408	char **av = oav;
409
410	while (*av++ = *bv++)
411		continue;
412	return (oav);
413}
414
415char **
416blkcat_(char **up, char **vp)
417{
418
419	(void) blkcpy_(blkend_(up), vp);
420	return (up);
421}
422
423char **
424blkspl_(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 */
440extern char	end[];
441static char	*xalloc_bottom;
442
443void *
444xalloc(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
456void *
457xrealloc(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 */
465oob:
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 */
475inb:
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
505void
506xfree(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
529void *
530xcalloc(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