xref: /titanic_52/usr/src/cmd/csh/sh.func.c (revision 70a587dd392ff1dbaa2875c6c33921f08ea85273)
17c478bd9Sstevel@tonic-gate /*
2*70a587ddSchin  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include "sh.h"
187c478bd9Sstevel@tonic-gate #include <locale.h>	/* For LC_ALL */
197c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
207c478bd9Sstevel@tonic-gate #include <sys/types.h>
217c478bd9Sstevel@tonic-gate #include <stdlib.h>
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate /*
247c478bd9Sstevel@tonic-gate  * N.B.: Some of the limits change from SunOS 4.x to SunOS 5.0.  In
257c478bd9Sstevel@tonic-gate  * particular, RLIMIT_RSS is gone and RLIMIT_VMEM is new.  Beware of consusing
267c478bd9Sstevel@tonic-gate  * the keywords that the command prints for these two.  The old one was
277c478bd9Sstevel@tonic-gate  * "memoryuse" and the new one is "memorysize".  Note also that a given limit
287c478bd9Sstevel@tonic-gate  * doesn't necessarily appear in the same position in the two releases.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate struct limits {
317c478bd9Sstevel@tonic-gate 	int	limconst;
327c478bd9Sstevel@tonic-gate 	tchar *limname;
337c478bd9Sstevel@tonic-gate 	int	limdiv;
347c478bd9Sstevel@tonic-gate 	tchar *limscale;
357c478bd9Sstevel@tonic-gate } limits[] = {
367c478bd9Sstevel@tonic-gate 	RLIMIT_CPU,	S_cputime,	/* "cputime" */
377c478bd9Sstevel@tonic-gate 		1,	S_seconds,	/* "seconds" */
387c478bd9Sstevel@tonic-gate 	RLIMIT_FSIZE,	S_filesize,	/* "filesize" */
397c478bd9Sstevel@tonic-gate 		1024,	S_kbytes,	/* "kbytes" */
407c478bd9Sstevel@tonic-gate 	RLIMIT_DATA,	S_datasize,	/* "datasize" */
417c478bd9Sstevel@tonic-gate 		1024,	S_kbytes,	/* "kbytes" */
427c478bd9Sstevel@tonic-gate 	RLIMIT_STACK,	S_stacksize,	/* "stacksize" */
437c478bd9Sstevel@tonic-gate 		1024,	S_kbytes,	/* "kbytes" */
447c478bd9Sstevel@tonic-gate 	RLIMIT_CORE,	S_coredumpsize, /* "coredumpsize" */
457c478bd9Sstevel@tonic-gate 		1024,	S_kbytes,	/* "kbytes" */
467c478bd9Sstevel@tonic-gate 	RLIMIT_NOFILE,	S_descriptors,	/* "descriptors" */
477c478bd9Sstevel@tonic-gate 		1,	S_,		/* "" */
487c478bd9Sstevel@tonic-gate 	RLIMIT_VMEM,	S_memorysize,	/* "memorysize" */
497c478bd9Sstevel@tonic-gate 		1024,	S_kbytes,	/* "kbytes" */
507c478bd9Sstevel@tonic-gate 	-1,		0,
517c478bd9Sstevel@tonic-gate };
527c478bd9Sstevel@tonic-gate 
536c02b4a4Smuffin 
547c478bd9Sstevel@tonic-gate static int getval(struct limits *lp, tchar **v, rlim_t *);
556c02b4a4Smuffin void islogin(void);
566c02b4a4Smuffin int dolabel(void);
577c478bd9Sstevel@tonic-gate void reexecute(struct command *kp);
586c02b4a4Smuffin void preread_(void);
596c02b4a4Smuffin void doagain(void);
606c02b4a4Smuffin void toend(void);
616c02b4a4Smuffin void wfree(void);
627c478bd9Sstevel@tonic-gate void echo(tchar sep, tchar **v);
637c478bd9Sstevel@tonic-gate void local_setenv(tchar *name, tchar *val);
647c478bd9Sstevel@tonic-gate void local_unsetenv(tchar *name);
657c478bd9Sstevel@tonic-gate void limtail(tchar *cp, tchar *str0);
667c478bd9Sstevel@tonic-gate void plim(struct limits *lp, tchar hard);
677c478bd9Sstevel@tonic-gate void search();
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	BUFSZ	1028
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * C shell
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate 
756c02b4a4Smuffin struct biltins *
767c478bd9Sstevel@tonic-gate isbfunc(struct command *t)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	tchar *cp = t->t_dcom[0];
797c478bd9Sstevel@tonic-gate 	struct biltins *bp, *bp1, *bp2;
807c478bd9Sstevel@tonic-gate 	int dofg1(), dobg1();
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	static struct biltins label = { S_, dolabel, 0, 0 };
837c478bd9Sstevel@tonic-gate 	static struct biltins foregnd = { S_Pjob, dofg1, 0, 0 };
847c478bd9Sstevel@tonic-gate 	static struct biltins backgnd = { S_PjobAND, dobg1, 0, 0 };
857c478bd9Sstevel@tonic-gate #ifdef TRACE
867c478bd9Sstevel@tonic-gate 	tprintf("TRACE- isbfunc()\n");
877c478bd9Sstevel@tonic-gate #endif
887c478bd9Sstevel@tonic-gate 	if (lastchr(cp) == ':') {
897c478bd9Sstevel@tonic-gate 		label.bname = cp;
907c478bd9Sstevel@tonic-gate 		return (&label);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 	if (*cp == '%') {
937c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FAND) {
947c478bd9Sstevel@tonic-gate 			t->t_dflg &= ~FAND;
957c478bd9Sstevel@tonic-gate 			backgnd.bname = cp;
967c478bd9Sstevel@tonic-gate 			return (&backgnd);
977c478bd9Sstevel@tonic-gate 		}
987c478bd9Sstevel@tonic-gate 		foregnd.bname = cp;
997c478bd9Sstevel@tonic-gate 		return (&foregnd);
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 	/*
1027c478bd9Sstevel@tonic-gate 	 * Binary search
1037c478bd9Sstevel@tonic-gate 	 * Bp1 is the beginning of the current search range.
1047c478bd9Sstevel@tonic-gate 	 * Bp2 is one past the end.
1057c478bd9Sstevel@tonic-gate 	 */
1067c478bd9Sstevel@tonic-gate 	for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2; ) {
1077c478bd9Sstevel@tonic-gate 		int i;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 		bp = bp1 + (bp2 - bp1 >> 1);
1107c478bd9Sstevel@tonic-gate 		if ((i = *cp - *bp->bname) == 0 &&
1117c478bd9Sstevel@tonic-gate 		    (i = strcmp_(cp, bp->bname)) == 0) {
1127c478bd9Sstevel@tonic-gate 			return (bp);
1137c478bd9Sstevel@tonic-gate 		}
1147c478bd9Sstevel@tonic-gate 		if (i < 0) {
1157c478bd9Sstevel@tonic-gate 			bp2 = bp;
1167c478bd9Sstevel@tonic-gate 		} else {
1177c478bd9Sstevel@tonic-gate 			bp1 = bp + 1;
1187c478bd9Sstevel@tonic-gate 		}
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 	return (0);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate void
1247c478bd9Sstevel@tonic-gate func(struct command *t, struct biltins *bp)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	int i;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate #ifdef TRACE
1297c478bd9Sstevel@tonic-gate 	tprintf("TRACE- func()\n");
1307c478bd9Sstevel@tonic-gate #endif
1317c478bd9Sstevel@tonic-gate 	xechoit(t->t_dcom);
1327c478bd9Sstevel@tonic-gate 	setname(bp->bname);
1337c478bd9Sstevel@tonic-gate 	i = blklen(t->t_dcom) - 1;
1347c478bd9Sstevel@tonic-gate 	if (i < bp->minargs) {
1357c478bd9Sstevel@tonic-gate 		bferr("Too few arguments");
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	if (i > bp->maxargs) {
1387c478bd9Sstevel@tonic-gate 		bferr("Too many arguments");
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 	(*bp->bfunct)(t->t_dcom, t);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate int
1446c02b4a4Smuffin dolabel(void)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate #ifdef TRACE
1477c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dolabel()\n");
1487c478bd9Sstevel@tonic-gate #endif
1496c02b4a4Smuffin 	return (0);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate void
1537c478bd9Sstevel@tonic-gate doonintr(tchar **v)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	tchar *cp;
1567c478bd9Sstevel@tonic-gate 	tchar *vv = v[1];
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate #ifdef TRACE
1597c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doonintr()\n");
1607c478bd9Sstevel@tonic-gate #endif
1617c478bd9Sstevel@tonic-gate 	if (parintr == SIG_IGN) {
1627c478bd9Sstevel@tonic-gate 		return;
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 	if (setintr && intty) {
1657c478bd9Sstevel@tonic-gate 		bferr("Can't from terminal");
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	cp = gointr, gointr = 0, xfree(cp);
1687c478bd9Sstevel@tonic-gate 	if (vv == 0) {
1697c478bd9Sstevel@tonic-gate 		if (setintr) {
1707c478bd9Sstevel@tonic-gate 			(void) sigblock(sigmask(SIGINT));
1717c478bd9Sstevel@tonic-gate 		} else {
1727c478bd9Sstevel@tonic-gate 			(void) signal(SIGINT, SIG_DFL);
1737c478bd9Sstevel@tonic-gate 		}
1747c478bd9Sstevel@tonic-gate 		gointr = 0;
1757c478bd9Sstevel@tonic-gate 	} else if (eq((vv = strip(vv)), S_MINUS)) {
1767c478bd9Sstevel@tonic-gate 		(void) signal(SIGINT, SIG_IGN);
1777c478bd9Sstevel@tonic-gate 		gointr = S_MINUS;
1787c478bd9Sstevel@tonic-gate 	} else {
1797c478bd9Sstevel@tonic-gate 		gointr = savestr(vv);
1807c478bd9Sstevel@tonic-gate 		(void) signal(SIGINT, pintr);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate void
1856c02b4a4Smuffin donohup(void)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate #ifdef TRACE
1897c478bd9Sstevel@tonic-gate 	tprintf("TRACE- donohup()\n");
1907c478bd9Sstevel@tonic-gate #endif
1917c478bd9Sstevel@tonic-gate 	if (intty) {
1927c478bd9Sstevel@tonic-gate 		bferr("Can't from terminal");
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	if (setintr == 0) {
1957c478bd9Sstevel@tonic-gate 		(void) signal(SIGHUP, SIG_IGN);
1967c478bd9Sstevel@tonic-gate #ifdef CC
1977c478bd9Sstevel@tonic-gate 		submit(getpid());
1987c478bd9Sstevel@tonic-gate #endif
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate void
2036c02b4a4Smuffin dozip(void)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate void
2096c02b4a4Smuffin prvars(void)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate #ifdef TRACE
2127c478bd9Sstevel@tonic-gate 	tprintf("TRACE- prvars()\n");
2137c478bd9Sstevel@tonic-gate #endif
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	plist(&shvhed);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate void
2197c478bd9Sstevel@tonic-gate doalias(tchar **v)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	struct varent *vp;
2227c478bd9Sstevel@tonic-gate 	tchar *p;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate #ifdef TRACE
2257c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doalias()\n");
2267c478bd9Sstevel@tonic-gate #endif
2277c478bd9Sstevel@tonic-gate 	v++;
2287c478bd9Sstevel@tonic-gate 	p = *v++;
2297c478bd9Sstevel@tonic-gate 	if (p == 0) {
2307c478bd9Sstevel@tonic-gate 		plist(&aliases);
2317c478bd9Sstevel@tonic-gate 	} else if (*v == 0) {
2327c478bd9Sstevel@tonic-gate 		vp = adrof1(strip(p), &aliases);
2337c478bd9Sstevel@tonic-gate 		if (vp) {
2347c478bd9Sstevel@tonic-gate 			blkpr(vp->vec), printf("\n");
2357c478bd9Sstevel@tonic-gate 		}
2367c478bd9Sstevel@tonic-gate 	} else {
2377c478bd9Sstevel@tonic-gate 		if (eq(p, S_alias) ||
2387c478bd9Sstevel@tonic-gate 		    eq(p, S_unalias)) {
2397c478bd9Sstevel@tonic-gate 			setname(p);
2407c478bd9Sstevel@tonic-gate 			bferr("Too dangerous to alias that");
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 		set1(strip(p), saveblk(v), &aliases);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate void
2477c478bd9Sstevel@tonic-gate unalias(tchar **v)
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate #ifdef TRACE
2517c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unalias()\n");
2527c478bd9Sstevel@tonic-gate #endif
2537c478bd9Sstevel@tonic-gate 	unset1(v, &aliases);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate void
2576c02b4a4Smuffin dologout(void)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate #ifdef TRACE
2617c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dologout()\n");
2627c478bd9Sstevel@tonic-gate #endif
2637c478bd9Sstevel@tonic-gate 	islogin();
2647c478bd9Sstevel@tonic-gate 	goodbye();
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate void
2687c478bd9Sstevel@tonic-gate dologin(tchar **v)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	char *v_;	/* work */
2727c478bd9Sstevel@tonic-gate #ifdef TRACE
2737c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dologin()\n");
2747c478bd9Sstevel@tonic-gate #endif
2757c478bd9Sstevel@tonic-gate 	islogin();
2767c478bd9Sstevel@tonic-gate 	rechist();
2777c478bd9Sstevel@tonic-gate 	(void) signal(SIGTERM, parterm);
2787c478bd9Sstevel@tonic-gate 	if (v[1] != NULL) {
2797c478bd9Sstevel@tonic-gate 		v_ = tstostr(NULL, v[1]);	/* No need to free */
2807c478bd9Sstevel@tonic-gate 	} else {
2817c478bd9Sstevel@tonic-gate 		v_ = 0;
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate 	execl("/bin/login", "login", v_, 0);
2847c478bd9Sstevel@tonic-gate 	untty();
2857c478bd9Sstevel@tonic-gate 	exit(1);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate #ifdef NEWGRP
2897c478bd9Sstevel@tonic-gate void
2907c478bd9Sstevel@tonic-gate donewgrp(tchar **v)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	char *v_;	/* work */
2947c478bd9Sstevel@tonic-gate #ifdef TRACE
2957c478bd9Sstevel@tonic-gate 	tprintf("TRACE- donewgrp()\n");
2967c478bd9Sstevel@tonic-gate #endif
2977c478bd9Sstevel@tonic-gate 	if (chkstop == 0 && setintr) {
2987c478bd9Sstevel@tonic-gate 		panystop(0);
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	(void) signal(SIGTERM, parterm);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	if (v[1] != NULL) {
3037c478bd9Sstevel@tonic-gate 		v_ = tstostr(NOSTR, v[1]);	/* No need to free */
3047c478bd9Sstevel@tonic-gate 	} else {
3057c478bd9Sstevel@tonic-gate 		v_ = 0;
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 	execl("/bin/newgrp", "newgrp", v_, 0);
3087c478bd9Sstevel@tonic-gate 	execl("/usr/bin/newgrp", "newgrp", v_, 0);
3097c478bd9Sstevel@tonic-gate 	untty();
3107c478bd9Sstevel@tonic-gate 	exit(1);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate #endif
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate void
3156c02b4a4Smuffin islogin(void)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate #ifdef TRACE
3197c478bd9Sstevel@tonic-gate 	tprintf("TRACE- islogin()\n");
3207c478bd9Sstevel@tonic-gate #endif
3217c478bd9Sstevel@tonic-gate 	if (chkstop == 0 && setintr) {
3227c478bd9Sstevel@tonic-gate 		panystop(0);
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 	if (loginsh) {
3257c478bd9Sstevel@tonic-gate 		return;
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 	error("Not login shell");
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate void
3317c478bd9Sstevel@tonic-gate doif(tchar **v, struct command *kp)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate 	int i;
3347c478bd9Sstevel@tonic-gate 	tchar **vv;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate #ifdef TRACE
3377c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doif()\n");
3387c478bd9Sstevel@tonic-gate #endif
3397c478bd9Sstevel@tonic-gate 	v++;
3407c478bd9Sstevel@tonic-gate 	i = exp(&v);
3417c478bd9Sstevel@tonic-gate 	vv = v;
3427c478bd9Sstevel@tonic-gate 	if (*vv == NOSTR) {
3437c478bd9Sstevel@tonic-gate 		bferr("Empty if");
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 	if (eq(*vv, S_then)) {
3467c478bd9Sstevel@tonic-gate 		if (*++vv) {
3477c478bd9Sstevel@tonic-gate 			bferr("Improper then");
3487c478bd9Sstevel@tonic-gate 		}
3497c478bd9Sstevel@tonic-gate 		setname(S_then);
3507c478bd9Sstevel@tonic-gate 		/*
3517c478bd9Sstevel@tonic-gate 		 * If expression was zero, then scan to else,
3527c478bd9Sstevel@tonic-gate 		 * otherwise just fall into following code.
3537c478bd9Sstevel@tonic-gate 		 */
3547c478bd9Sstevel@tonic-gate 		if (!i) {
3557c478bd9Sstevel@tonic-gate 			search(ZIF, 0);
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 		return;
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 	/*
3607c478bd9Sstevel@tonic-gate 	 * Simple command attached to this if.
3617c478bd9Sstevel@tonic-gate 	 * Left shift the node in this tree, munging it
3627c478bd9Sstevel@tonic-gate 	 * so we can reexecute it.
3637c478bd9Sstevel@tonic-gate 	 */
3647c478bd9Sstevel@tonic-gate 	if (i) {
3657c478bd9Sstevel@tonic-gate 		lshift(kp->t_dcom, vv - kp->t_dcom);
3667c478bd9Sstevel@tonic-gate 		reexecute(kp);
3677c478bd9Sstevel@tonic-gate 		donefds();
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate  * Reexecute a command, being careful not
3737c478bd9Sstevel@tonic-gate  * to redo i/o redirection, which is already set up.
3747c478bd9Sstevel@tonic-gate  */
3757c478bd9Sstevel@tonic-gate void
3767c478bd9Sstevel@tonic-gate reexecute(struct command *kp)
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate #ifdef TRACE
3807c478bd9Sstevel@tonic-gate 	tprintf("TRACE- reexecute()\n");
3817c478bd9Sstevel@tonic-gate #endif
3827c478bd9Sstevel@tonic-gate 	kp->t_dflg &= FSAVE;
3837c478bd9Sstevel@tonic-gate 	kp->t_dflg |= FREDO;
3847c478bd9Sstevel@tonic-gate 	/*
3857c478bd9Sstevel@tonic-gate 	 * If tty is still ours to arbitrate, arbitrate it;
3867c478bd9Sstevel@tonic-gate 	 * otherwise dont even set pgrp's as the jobs would
3877c478bd9Sstevel@tonic-gate 	 * then have no way to get the tty (we can't give it
3887c478bd9Sstevel@tonic-gate 	 * to them, and our parent wouldn't know their pgrp, etc.
3897c478bd9Sstevel@tonic-gate 	 */
3907c478bd9Sstevel@tonic-gate 	execute(kp, tpgrp > 0 ? tpgrp : -1);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate void
3946c02b4a4Smuffin doelse(void)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate #ifdef TRACE
3987c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doelse()\n");
3997c478bd9Sstevel@tonic-gate #endif
4007c478bd9Sstevel@tonic-gate 	search(ZELSE, 0);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate void
4047c478bd9Sstevel@tonic-gate dogoto(tchar **v)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 	struct whyle *wp;
4077c478bd9Sstevel@tonic-gate 	tchar *lp;
4087c478bd9Sstevel@tonic-gate #ifdef TRACE
4097c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dogoto()\n");
4107c478bd9Sstevel@tonic-gate #endif
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	/*
4137c478bd9Sstevel@tonic-gate 	 * While we still can, locate any unknown ends of existing loops.
4147c478bd9Sstevel@tonic-gate 	 * This obscure code is the WORST result of the fact that we
4157c478bd9Sstevel@tonic-gate 	 * don't really parse.
4167c478bd9Sstevel@tonic-gate 	 */
4177c478bd9Sstevel@tonic-gate 	for (wp = whyles; wp; wp = wp->w_next) {
4187c478bd9Sstevel@tonic-gate 		if (wp->w_end == 0) {
4197c478bd9Sstevel@tonic-gate 			search(ZBREAK, 0);
4207c478bd9Sstevel@tonic-gate 			wp->w_end = btell();
4217c478bd9Sstevel@tonic-gate 		} else {
4227c478bd9Sstevel@tonic-gate 			bseek(wp->w_end);
4237c478bd9Sstevel@tonic-gate 		}
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 	search(ZGOTO, 0, lp = globone(v[1]));
4267c478bd9Sstevel@tonic-gate 	xfree(lp);
4277c478bd9Sstevel@tonic-gate 	/*
4287c478bd9Sstevel@tonic-gate 	 * Eliminate loops which were exited.
4297c478bd9Sstevel@tonic-gate 	 */
4307c478bd9Sstevel@tonic-gate 	wfree();
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate void
4347c478bd9Sstevel@tonic-gate doswitch(tchar **v)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	tchar *cp, *lp;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate #ifdef TRACE
4397c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doswitch()\n");
4407c478bd9Sstevel@tonic-gate #endif
4417c478bd9Sstevel@tonic-gate 	v++;
4427c478bd9Sstevel@tonic-gate 	if (!*v || *(*v++) != '(') {
4437c478bd9Sstevel@tonic-gate 		goto syntax;
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 	cp = **v == ')' ? S_ : *v++;
4467c478bd9Sstevel@tonic-gate 	if (*(*v++) != ')') {
4477c478bd9Sstevel@tonic-gate 		v--;
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 	if (*v) {
4507c478bd9Sstevel@tonic-gate syntax:
4517c478bd9Sstevel@tonic-gate 		error("Syntax error");
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 	search(ZSWITCH, 0, lp = globone(cp));
4547c478bd9Sstevel@tonic-gate 	xfree(lp);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate void
4586c02b4a4Smuffin dobreak(void)
4597c478bd9Sstevel@tonic-gate {
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate #ifdef TRACE
4627c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dobreak()\n");
4637c478bd9Sstevel@tonic-gate #endif
4647c478bd9Sstevel@tonic-gate 	if (whyles) {
4657c478bd9Sstevel@tonic-gate 		toend();
4667c478bd9Sstevel@tonic-gate 	} else {
4677c478bd9Sstevel@tonic-gate 		bferr("Not in while/foreach");
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate void
4727c478bd9Sstevel@tonic-gate doexit(tchar **v)
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate #ifdef TRACE
4767c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doexit()\n");
4777c478bd9Sstevel@tonic-gate #endif
4787c478bd9Sstevel@tonic-gate 	if (chkstop == 0) {
4797c478bd9Sstevel@tonic-gate 		panystop(0);
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate 	/*
4827c478bd9Sstevel@tonic-gate 	 * Don't DEMAND parentheses here either.
4837c478bd9Sstevel@tonic-gate 	 */
4847c478bd9Sstevel@tonic-gate 	v++;
4857c478bd9Sstevel@tonic-gate 	if (*v) {
4867c478bd9Sstevel@tonic-gate 		set(S_status, putn(exp(&v)));
4877c478bd9Sstevel@tonic-gate 		if (*v) {
4887c478bd9Sstevel@tonic-gate 			bferr("Expression syntax");
4897c478bd9Sstevel@tonic-gate 		}
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 	btoeof();
4927c478bd9Sstevel@tonic-gate 	if (intty) {
4937c478bd9Sstevel@tonic-gate 		(void) close(SHIN);
4947c478bd9Sstevel@tonic-gate 		unsetfd(SHIN);
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate void
4997c478bd9Sstevel@tonic-gate doforeach(tchar **v)
5007c478bd9Sstevel@tonic-gate {
5017c478bd9Sstevel@tonic-gate 	tchar *cp;
5027c478bd9Sstevel@tonic-gate 	struct whyle *nwp;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate #ifdef TRACE
5057c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doforeach()\n");
5067c478bd9Sstevel@tonic-gate #endif
5077c478bd9Sstevel@tonic-gate 	v++;
5087c478bd9Sstevel@tonic-gate 	cp = strip(*v);
5097c478bd9Sstevel@tonic-gate 	while (*cp && alnum(*cp)) {
5107c478bd9Sstevel@tonic-gate 		cp++;
5117c478bd9Sstevel@tonic-gate 	}
512*70a587ddSchin 	if (*cp || strlen_(*v) >= MAX_VAR_LEN || !letter(**v)) {
5137c478bd9Sstevel@tonic-gate 		bferr("Invalid variable");
5147c478bd9Sstevel@tonic-gate 	}
5157c478bd9Sstevel@tonic-gate 	cp = *v++;
5167c478bd9Sstevel@tonic-gate 	if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') {
5177c478bd9Sstevel@tonic-gate 		bferr("Words not ()'ed");
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	v++;
5207c478bd9Sstevel@tonic-gate 	gflag = 0, tglob(v);
5217c478bd9Sstevel@tonic-gate 	v = glob(v);
5227c478bd9Sstevel@tonic-gate 	if (v == 0) {
5237c478bd9Sstevel@tonic-gate 		bferr("No match");
5247c478bd9Sstevel@tonic-gate 	}
52565b0c20eSnakanon 	nwp = (struct whyle *)xcalloc(1, sizeof (*nwp));
5267c478bd9Sstevel@tonic-gate 	nwp->w_fe = nwp->w_fe0 = v; gargv = 0;
5277c478bd9Sstevel@tonic-gate 	nwp->w_start = btell();
5287c478bd9Sstevel@tonic-gate 	nwp->w_fename = savestr(cp);
5297c478bd9Sstevel@tonic-gate 	nwp->w_next = whyles;
5307c478bd9Sstevel@tonic-gate 	whyles = nwp;
5317c478bd9Sstevel@tonic-gate 	/*
5327c478bd9Sstevel@tonic-gate 	 * Pre-read the loop so as to be more
5337c478bd9Sstevel@tonic-gate 	 * comprehensible to a terminal user.
5347c478bd9Sstevel@tonic-gate 	 */
5357c478bd9Sstevel@tonic-gate 	if (intty) {
5367c478bd9Sstevel@tonic-gate 		preread_();
5377c478bd9Sstevel@tonic-gate 	}
5387c478bd9Sstevel@tonic-gate 	doagain();
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate void
5427c478bd9Sstevel@tonic-gate dowhile(tchar **v)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate 	int status;
5457c478bd9Sstevel@tonic-gate 	bool again = whyles != 0 && whyles->w_start == lineloc &&
5467c478bd9Sstevel@tonic-gate 	    whyles->w_fename == 0;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate #ifdef TRACE
5497c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dowhile()\n");
5507c478bd9Sstevel@tonic-gate #endif
5517c478bd9Sstevel@tonic-gate 	v++;
5527c478bd9Sstevel@tonic-gate 	/*
5537c478bd9Sstevel@tonic-gate 	 * Implement prereading here also, taking care not to
5547c478bd9Sstevel@tonic-gate 	 * evaluate the expression before the loop has been read up
5557c478bd9Sstevel@tonic-gate 	 * from a terminal.
5567c478bd9Sstevel@tonic-gate 	 */
5577c478bd9Sstevel@tonic-gate 	if (intty && !again) {
5587c478bd9Sstevel@tonic-gate 		status = !exp0(&v, 1);
5597c478bd9Sstevel@tonic-gate 	} else {
5607c478bd9Sstevel@tonic-gate 		status = !exp(&v);
5617c478bd9Sstevel@tonic-gate 	}
5627c478bd9Sstevel@tonic-gate 	if (*v) {
5637c478bd9Sstevel@tonic-gate 		bferr("Expression syntax");
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate 	if (!again) {
56665b0c20eSnakanon 		struct whyle *nwp = (struct whyle *)xcalloc(1, sizeof (*nwp));
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		nwp->w_start = lineloc;
5697c478bd9Sstevel@tonic-gate 		nwp->w_end = 0;
5707c478bd9Sstevel@tonic-gate 		nwp->w_next = whyles;
5717c478bd9Sstevel@tonic-gate 		whyles = nwp;
5727c478bd9Sstevel@tonic-gate 		if (intty) {
5737c478bd9Sstevel@tonic-gate 			/*
5747c478bd9Sstevel@tonic-gate 			 * The tty preread
5757c478bd9Sstevel@tonic-gate 			 */
5767c478bd9Sstevel@tonic-gate 			preread_();
5777c478bd9Sstevel@tonic-gate 			doagain();
5787c478bd9Sstevel@tonic-gate 			return;
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 	if (status) {
5827c478bd9Sstevel@tonic-gate 		/* We ain't gonna loop no more, no more! */
5837c478bd9Sstevel@tonic-gate 		toend();
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate void
5886c02b4a4Smuffin preread_(void)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate #ifdef TRACE
5917c478bd9Sstevel@tonic-gate 	tprintf("TRACE- preread()\n");
5927c478bd9Sstevel@tonic-gate #endif
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	whyles->w_end = -1;
5957c478bd9Sstevel@tonic-gate 	if (setintr) {
5967c478bd9Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 	search(ZBREAK, 0);
5997c478bd9Sstevel@tonic-gate 	if (setintr) {
6007c478bd9Sstevel@tonic-gate 		(void) sigblock(sigmask(SIGINT));
6017c478bd9Sstevel@tonic-gate 	}
6027c478bd9Sstevel@tonic-gate 	whyles->w_end = btell();
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate void
6066c02b4a4Smuffin doend(void)
6077c478bd9Sstevel@tonic-gate {
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate #ifdef TRACE
6107c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doend()\n");
6117c478bd9Sstevel@tonic-gate #endif
6127c478bd9Sstevel@tonic-gate 	if (!whyles) {
6137c478bd9Sstevel@tonic-gate 		bferr("Not in while/foreach");
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 	whyles->w_end = btell();
6167c478bd9Sstevel@tonic-gate 	doagain();
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate void
6206c02b4a4Smuffin docontin(void)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate #ifdef TRACE
6237c478bd9Sstevel@tonic-gate 	tprintf("TRACE- docontin()\n");
6247c478bd9Sstevel@tonic-gate #endif
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	if (!whyles) {
6277c478bd9Sstevel@tonic-gate 		bferr("Not in while/foreach");
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 	doagain();
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate void
6336c02b4a4Smuffin doagain(void)
6347c478bd9Sstevel@tonic-gate {
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate #ifdef TRACE
6377c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doagain()\n");
6387c478bd9Sstevel@tonic-gate #endif
6397c478bd9Sstevel@tonic-gate 	/* Repeating a while is simple */
6407c478bd9Sstevel@tonic-gate 	if (whyles->w_fename == 0) {
6417c478bd9Sstevel@tonic-gate 		bseek(whyles->w_start);
6427c478bd9Sstevel@tonic-gate 		return;
6437c478bd9Sstevel@tonic-gate 	}
6447c478bd9Sstevel@tonic-gate 	/*
6457c478bd9Sstevel@tonic-gate 	 * The foreach variable list actually has a spurious word
6467c478bd9Sstevel@tonic-gate 	 * ")" at the end of the w_fe list.  Thus we are at the
6477c478bd9Sstevel@tonic-gate 	 * of the list if one word beyond this is 0.
6487c478bd9Sstevel@tonic-gate 	 */
6497c478bd9Sstevel@tonic-gate 	if (!whyles->w_fe[1]) {
6507c478bd9Sstevel@tonic-gate 		dobreak();
6517c478bd9Sstevel@tonic-gate 		return;
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate 	set(whyles->w_fename, savestr(*whyles->w_fe++));
6547c478bd9Sstevel@tonic-gate 	bseek(whyles->w_start);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate void
6587c478bd9Sstevel@tonic-gate dorepeat(tchar **v, struct command *kp)
6597c478bd9Sstevel@tonic-gate {
6607c478bd9Sstevel@tonic-gate 	int i, omask;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate #ifdef TRACE
6637c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dorepeat()\n");
6647c478bd9Sstevel@tonic-gate #endif
6657c478bd9Sstevel@tonic-gate 	i = getn(v[1]);
6667c478bd9Sstevel@tonic-gate 	if (setintr) {
6677c478bd9Sstevel@tonic-gate 		omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 	lshift(v, 2);
6707c478bd9Sstevel@tonic-gate 	while (i > 0) {
6717c478bd9Sstevel@tonic-gate 		if (setintr) {
6727c478bd9Sstevel@tonic-gate 			(void) sigsetmask(omask);
6737c478bd9Sstevel@tonic-gate 		}
6747c478bd9Sstevel@tonic-gate 		reexecute(kp);
6757c478bd9Sstevel@tonic-gate 		--i;
6767c478bd9Sstevel@tonic-gate 	}
6777c478bd9Sstevel@tonic-gate 	donefds();
6787c478bd9Sstevel@tonic-gate 	if (setintr) {
6797c478bd9Sstevel@tonic-gate 		(void) sigsetmask(omask);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate }
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate void
6846c02b4a4Smuffin doswbrk(void)
6857c478bd9Sstevel@tonic-gate {
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate #ifdef TRACE
6887c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doswbrk()\n");
6897c478bd9Sstevel@tonic-gate #endif
6907c478bd9Sstevel@tonic-gate 	search(ZBRKSW, 0);
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate int
6947c478bd9Sstevel@tonic-gate srchx(tchar *cp)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate 	struct srch *sp, *sp1, *sp2;
6977c478bd9Sstevel@tonic-gate 	int i;
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate #ifdef TRACE
7007c478bd9Sstevel@tonic-gate 	tprintf("TRACE- srchx()\n");
7017c478bd9Sstevel@tonic-gate #endif
7027c478bd9Sstevel@tonic-gate 	/*
7037c478bd9Sstevel@tonic-gate 	 * Binary search
7047c478bd9Sstevel@tonic-gate 	 * Sp1 is the beginning of the current search range.
7057c478bd9Sstevel@tonic-gate 	 * Sp2 is one past the end.
7067c478bd9Sstevel@tonic-gate 	 */
7077c478bd9Sstevel@tonic-gate 	for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2; ) {
7087c478bd9Sstevel@tonic-gate 		sp = sp1 + (sp2 - sp1 >> 1);
7097c478bd9Sstevel@tonic-gate 		if ((i = *cp - *sp->s_name) == 0 &&
7107c478bd9Sstevel@tonic-gate 		    (i = strcmp_(cp, sp->s_name)) == 0) {
7117c478bd9Sstevel@tonic-gate 			return (sp->s_value);
7127c478bd9Sstevel@tonic-gate 		}
7137c478bd9Sstevel@tonic-gate 		if (i < 0) {
7147c478bd9Sstevel@tonic-gate 			sp2 = sp;
7157c478bd9Sstevel@tonic-gate 		} else {
7167c478bd9Sstevel@tonic-gate 			sp1 = sp + 1;
7177c478bd9Sstevel@tonic-gate 		}
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 	return (-1);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate tchar Stype;
7237c478bd9Sstevel@tonic-gate tchar *Sgoal;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate /*VARARGS2*/
7267c478bd9Sstevel@tonic-gate void
7277c478bd9Sstevel@tonic-gate search(type, level, goal)
7287c478bd9Sstevel@tonic-gate 	int type; int level; tchar *goal;
7297c478bd9Sstevel@tonic-gate {
7307c478bd9Sstevel@tonic-gate 	tchar wordbuf[BUFSIZ];
7317c478bd9Sstevel@tonic-gate 	tchar *aword = wordbuf;
7327c478bd9Sstevel@tonic-gate 	tchar *cp;
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate #ifdef TRACE
7357c478bd9Sstevel@tonic-gate 	tprintf("TRACE- search()\n");
7367c478bd9Sstevel@tonic-gate #endif
7377c478bd9Sstevel@tonic-gate 	Stype = type; Sgoal = goal;
7387c478bd9Sstevel@tonic-gate 	if (type == ZGOTO) {
7397c478bd9Sstevel@tonic-gate 		bseek((off_t)0);
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 	do {
7427c478bd9Sstevel@tonic-gate 		if (intty && fseekp == feobp) {
7437c478bd9Sstevel@tonic-gate 			printf("? "), flush();
7447c478bd9Sstevel@tonic-gate 		}
7457c478bd9Sstevel@tonic-gate 		aword[0] = 0;
7467c478bd9Sstevel@tonic-gate 		(void) getword(aword);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 		switch (srchx(aword)) {
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		case ZELSE:
7517c478bd9Sstevel@tonic-gate 			if (level == 0 && type == ZIF) {
7527c478bd9Sstevel@tonic-gate 				return;
7537c478bd9Sstevel@tonic-gate 			}
7547c478bd9Sstevel@tonic-gate 			break;
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		case ZIF:
7577c478bd9Sstevel@tonic-gate 			while (getword(aword)) {
7587c478bd9Sstevel@tonic-gate 				continue;
7597c478bd9Sstevel@tonic-gate 			}
7607c478bd9Sstevel@tonic-gate 			if ((type == ZIF || type == ZELSE) &&
7617c478bd9Sstevel@tonic-gate 			    eq(aword, S_then)) {
7627c478bd9Sstevel@tonic-gate 				level++;
7637c478bd9Sstevel@tonic-gate 			}
7647c478bd9Sstevel@tonic-gate 			break;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 		case ZENDIF:
7677c478bd9Sstevel@tonic-gate 			if (type == ZIF || type == ZELSE) {
7687c478bd9Sstevel@tonic-gate 				level--;
7697c478bd9Sstevel@tonic-gate 			}
7707c478bd9Sstevel@tonic-gate 			break;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 		case ZFOREACH:
7737c478bd9Sstevel@tonic-gate 		case ZWHILE:
7747c478bd9Sstevel@tonic-gate 			if (type == ZBREAK) {
7757c478bd9Sstevel@tonic-gate 				level++;
7767c478bd9Sstevel@tonic-gate 			}
7777c478bd9Sstevel@tonic-gate 			break;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 		case ZEND:
7807c478bd9Sstevel@tonic-gate 			if (type == ZBREAK) {
7817c478bd9Sstevel@tonic-gate 				level--;
7827c478bd9Sstevel@tonic-gate 			}
7837c478bd9Sstevel@tonic-gate 			break;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 		case ZSWITCH:
7867c478bd9Sstevel@tonic-gate 			if (type == ZSWITCH || type == ZBRKSW) {
7877c478bd9Sstevel@tonic-gate 				level++;
7887c478bd9Sstevel@tonic-gate 			}
7897c478bd9Sstevel@tonic-gate 			break;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 		case ZENDSW:
7927c478bd9Sstevel@tonic-gate 			if (type == ZSWITCH || type == ZBRKSW) {
7937c478bd9Sstevel@tonic-gate 				level--;
7947c478bd9Sstevel@tonic-gate 			}
7957c478bd9Sstevel@tonic-gate 			break;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 		case ZLABEL:
7987c478bd9Sstevel@tonic-gate 			if (type == ZGOTO && getword(aword) &&
7997c478bd9Sstevel@tonic-gate 			    eq(aword, goal)) {
8007c478bd9Sstevel@tonic-gate 				level = -1;
8017c478bd9Sstevel@tonic-gate 			}
8027c478bd9Sstevel@tonic-gate 			break;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 		default:
8057c478bd9Sstevel@tonic-gate 			if (type != ZGOTO && (type != ZSWITCH || level != 0)) {
8067c478bd9Sstevel@tonic-gate 				break;
8077c478bd9Sstevel@tonic-gate 			}
8087c478bd9Sstevel@tonic-gate 			if (lastchr(aword) != ':') {
8097c478bd9Sstevel@tonic-gate 				break;
8107c478bd9Sstevel@tonic-gate 			}
8117c478bd9Sstevel@tonic-gate 			aword[strlen_(aword) - 1] = 0;
8127c478bd9Sstevel@tonic-gate 			if (type == ZGOTO && eq(aword, goal) ||
8137c478bd9Sstevel@tonic-gate 			    type == ZSWITCH && eq(aword, S_default)) {
8147c478bd9Sstevel@tonic-gate 				level = -1;
8157c478bd9Sstevel@tonic-gate 			}
8167c478bd9Sstevel@tonic-gate 			break;
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 		case ZCASE:
8197c478bd9Sstevel@tonic-gate 			if (type != ZSWITCH || level != 0) {
8207c478bd9Sstevel@tonic-gate 				break;
8217c478bd9Sstevel@tonic-gate 			}
8227c478bd9Sstevel@tonic-gate 			(void) getword(aword);
8237c478bd9Sstevel@tonic-gate 			if (lastchr(aword) == ':') {
8247c478bd9Sstevel@tonic-gate 				aword[strlen_(aword) - 1] = 0;
8257c478bd9Sstevel@tonic-gate 			}
8267c478bd9Sstevel@tonic-gate 			cp = strip(Dfix1(aword));
8277c478bd9Sstevel@tonic-gate 			if (Gmatch(goal, cp)) {
8287c478bd9Sstevel@tonic-gate 				level = -1;
8297c478bd9Sstevel@tonic-gate 			}
8307c478bd9Sstevel@tonic-gate 			xfree(cp);
8317c478bd9Sstevel@tonic-gate 			break;
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 		case ZDEFAULT:
8347c478bd9Sstevel@tonic-gate 			if (type == ZSWITCH && level == 0) {
8357c478bd9Sstevel@tonic-gate 				level = -1;
8367c478bd9Sstevel@tonic-gate 			}
8377c478bd9Sstevel@tonic-gate 			break;
8387c478bd9Sstevel@tonic-gate 		}
8397c478bd9Sstevel@tonic-gate 		(void) getword(NOSTR);
8407c478bd9Sstevel@tonic-gate 	} while (level >= 0);
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate int
8447c478bd9Sstevel@tonic-gate getword(tchar *wp)
8457c478bd9Sstevel@tonic-gate {
8467c478bd9Sstevel@tonic-gate 	int found = 0;
8477c478bd9Sstevel@tonic-gate 	int c, d;
8487c478bd9Sstevel@tonic-gate #ifdef TRACE
8497c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getword()\n");
8507c478bd9Sstevel@tonic-gate #endif
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	c = readc(1);
8537c478bd9Sstevel@tonic-gate 	d = 0;
8547c478bd9Sstevel@tonic-gate 	do {
8557c478bd9Sstevel@tonic-gate 		while (issp(c)) {
8567c478bd9Sstevel@tonic-gate 			c = readc(1);
8577c478bd9Sstevel@tonic-gate 		}
8587c478bd9Sstevel@tonic-gate 		if (c == '#') {
8597c478bd9Sstevel@tonic-gate 			do {
8607c478bd9Sstevel@tonic-gate 				c = readc(1);
8617c478bd9Sstevel@tonic-gate 			} while (c >= 0 && c != '\n');
8627c478bd9Sstevel@tonic-gate 		}
8637c478bd9Sstevel@tonic-gate 		if (c < 0) {
8647c478bd9Sstevel@tonic-gate 			goto past;
8657c478bd9Sstevel@tonic-gate 		}
8667c478bd9Sstevel@tonic-gate 		if (c == '\n') {
8677c478bd9Sstevel@tonic-gate 			if (wp) {
8687c478bd9Sstevel@tonic-gate 				break;
8697c478bd9Sstevel@tonic-gate 			}
8707c478bd9Sstevel@tonic-gate 			return (0);
8717c478bd9Sstevel@tonic-gate 		}
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate 		/* ( and ) form separate words */
8747c478bd9Sstevel@tonic-gate 		if (c == '(' || c == ')') {
8757c478bd9Sstevel@tonic-gate 			return (1);
8767c478bd9Sstevel@tonic-gate 		}
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 		unreadc(c);
8797c478bd9Sstevel@tonic-gate 		found = 1;
8807c478bd9Sstevel@tonic-gate 		do {
8817c478bd9Sstevel@tonic-gate 			c = readc(1);
8827c478bd9Sstevel@tonic-gate 			if (c == '\\' && (c = readc(1)) == '\n') {
8837c478bd9Sstevel@tonic-gate 				c = ' ';
8847c478bd9Sstevel@tonic-gate 			}
8857c478bd9Sstevel@tonic-gate 			if (c == '\'' || c == '"') {
8867c478bd9Sstevel@tonic-gate 				if (d == 0) {
8877c478bd9Sstevel@tonic-gate 					d = c;
8887c478bd9Sstevel@tonic-gate 				} else if (d == c) {
8897c478bd9Sstevel@tonic-gate 					d = 0;
8907c478bd9Sstevel@tonic-gate 				}
8917c478bd9Sstevel@tonic-gate 			}
8927c478bd9Sstevel@tonic-gate 			if (c < 0) {
8937c478bd9Sstevel@tonic-gate 				goto past;
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 			if (wp) {
8967c478bd9Sstevel@tonic-gate 				*wp++ = c;
8977c478bd9Sstevel@tonic-gate 			}
8987c478bd9Sstevel@tonic-gate 		} while ((d || !issp(c) && c != '(' && c != ')') && c != '\n');
8997c478bd9Sstevel@tonic-gate 	} while (wp == 0);
9007c478bd9Sstevel@tonic-gate 	unreadc(c);
9017c478bd9Sstevel@tonic-gate 	if (found) {
9027c478bd9Sstevel@tonic-gate 		*--wp = 0;
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 	return (found);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate past:
9077c478bd9Sstevel@tonic-gate 	switch (Stype) {
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 	case ZIF:
9107c478bd9Sstevel@tonic-gate 		bferr("then/endif not found");
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	case ZELSE:
9137c478bd9Sstevel@tonic-gate 		bferr("endif not found");
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 	case ZBRKSW:
9167c478bd9Sstevel@tonic-gate 	case ZSWITCH:
9177c478bd9Sstevel@tonic-gate 		bferr("endsw not found");
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 	case ZBREAK:
9207c478bd9Sstevel@tonic-gate 		bferr("end not found");
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	case ZGOTO:
9237c478bd9Sstevel@tonic-gate 		setname(Sgoal);
9247c478bd9Sstevel@tonic-gate 		bferr("label not found");
9257c478bd9Sstevel@tonic-gate 	}
9267c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
9276c02b4a4Smuffin 
9286c02b4a4Smuffin 	return (0);
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate void
9326c02b4a4Smuffin toend(void)
9337c478bd9Sstevel@tonic-gate {
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate #ifdef TRACE
9367c478bd9Sstevel@tonic-gate 	tprintf("TRACE- toend()\n");
9377c478bd9Sstevel@tonic-gate #endif
9387c478bd9Sstevel@tonic-gate 	if (whyles->w_end == 0) {
9397c478bd9Sstevel@tonic-gate 		search(ZBREAK, 0);
9407c478bd9Sstevel@tonic-gate 		whyles->w_end = btell() - 1;
9417c478bd9Sstevel@tonic-gate 	} else {
9427c478bd9Sstevel@tonic-gate 		bseek(whyles->w_end);
9437c478bd9Sstevel@tonic-gate 	}
9447c478bd9Sstevel@tonic-gate 	wfree();
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate void
9486c02b4a4Smuffin wfree(void)
9497c478bd9Sstevel@tonic-gate {
9507c478bd9Sstevel@tonic-gate 	long o = btell();
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate #ifdef TRACE
9537c478bd9Sstevel@tonic-gate 	tprintf("TRACE- wfree()\n");
9547c478bd9Sstevel@tonic-gate #endif
9557c478bd9Sstevel@tonic-gate 	while (whyles) {
9567c478bd9Sstevel@tonic-gate 		struct whyle *wp = whyles;
9577c478bd9Sstevel@tonic-gate 		struct whyle *nwp = wp->w_next;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 		if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) {
9607c478bd9Sstevel@tonic-gate 			break;
9617c478bd9Sstevel@tonic-gate 		}
9627c478bd9Sstevel@tonic-gate 		if (wp->w_fe0) {
9637c478bd9Sstevel@tonic-gate 			blkfree(wp->w_fe0);
9647c478bd9Sstevel@tonic-gate 		}
9657c478bd9Sstevel@tonic-gate 		if (wp->w_fename) {
9667c478bd9Sstevel@tonic-gate 			xfree(wp->w_fename);
9677c478bd9Sstevel@tonic-gate 		}
9687c478bd9Sstevel@tonic-gate 		xfree((char *)wp);
9697c478bd9Sstevel@tonic-gate 		whyles = nwp;
9707c478bd9Sstevel@tonic-gate 	}
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate void
9747c478bd9Sstevel@tonic-gate doecho(tchar **v)
9757c478bd9Sstevel@tonic-gate {
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate #ifdef TRACE
9787c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doecho()\n");
9797c478bd9Sstevel@tonic-gate #endif
9807c478bd9Sstevel@tonic-gate 	echo(' ', v);
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate void
9847c478bd9Sstevel@tonic-gate doglob(tchar **v)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate #ifdef TRACE
9887c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doglob()\n");
9897c478bd9Sstevel@tonic-gate #endif
9907c478bd9Sstevel@tonic-gate 	echo(0, v);
9917c478bd9Sstevel@tonic-gate 	flush();
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate void
9957c478bd9Sstevel@tonic-gate echo(tchar sep, tchar **v)
9967c478bd9Sstevel@tonic-gate {
9977c478bd9Sstevel@tonic-gate 	tchar *cp;
9987c478bd9Sstevel@tonic-gate 	int nonl = 0;
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate #ifdef TRACE
10017c478bd9Sstevel@tonic-gate 	tprintf("TRACE- echo()\n");
10027c478bd9Sstevel@tonic-gate #endif
10037c478bd9Sstevel@tonic-gate 	if (setintr) {
10047c478bd9Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~sigmask(SIGINT));
10057c478bd9Sstevel@tonic-gate 	}
10067c478bd9Sstevel@tonic-gate 	v++;
10077c478bd9Sstevel@tonic-gate 	if (*v == 0) {
10087c478bd9Sstevel@tonic-gate 		/*
10097c478bd9Sstevel@tonic-gate 		 * echo command needs to have newline when there are no
10107c478bd9Sstevel@tonic-gate 		 * flags or arguments.  glob should have no newline.  If
10117c478bd9Sstevel@tonic-gate 		 * the separator is a blank, we are doing an echo.  If the
10127c478bd9Sstevel@tonic-gate 		 * separator is zero, we are globbing.
10137c478bd9Sstevel@tonic-gate 		 */
10147c478bd9Sstevel@tonic-gate 		if (sep == (tchar)' ')
10157c478bd9Sstevel@tonic-gate 			Putchar('\n');
10167c478bd9Sstevel@tonic-gate 		return;
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate 	gflag = 0, tglob(v);
10197c478bd9Sstevel@tonic-gate 	if (gflag) {
10207c478bd9Sstevel@tonic-gate 		v = glob(v);
10217c478bd9Sstevel@tonic-gate 		if (v == 0) {
10227c478bd9Sstevel@tonic-gate 			bferr("No match");
10237c478bd9Sstevel@tonic-gate 		}
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 	/* check for -n arg, NOTE: it might be quoted */
10267c478bd9Sstevel@tonic-gate 	if (sep == ' ' && *v && strlen_(*v) == 2 &&
10277c478bd9Sstevel@tonic-gate 	    ((**v&TRIM) == '-' && (*(*v + 1) & TRIM) == 'n' &&
10287c478bd9Sstevel@tonic-gate 	    (*(*v+2)&TRIM) == 0)) {
10297c478bd9Sstevel@tonic-gate 		nonl++, v++;
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 	while (cp = *v++) {
10327c478bd9Sstevel@tonic-gate 		int c;
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 		while (c = *cp++) {
10357c478bd9Sstevel@tonic-gate 			Putchar(c | QUOTE);
10367c478bd9Sstevel@tonic-gate 		}
10377c478bd9Sstevel@tonic-gate 		if (*v) {
10387c478bd9Sstevel@tonic-gate 			Putchar(sep | QUOTE);
10397c478bd9Sstevel@tonic-gate 		}
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 	if (sep && nonl == 0) {
10427c478bd9Sstevel@tonic-gate 		Putchar('\n');
10437c478bd9Sstevel@tonic-gate 	} else {
10447c478bd9Sstevel@tonic-gate 		flush();
10457c478bd9Sstevel@tonic-gate 	}
10467c478bd9Sstevel@tonic-gate 	if (setintr) {
10477c478bd9Sstevel@tonic-gate 		(void) sigblock(sigmask(SIGINT));
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 	if (gargv) {
10507c478bd9Sstevel@tonic-gate 		blkfree(gargv), gargv = 0;
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate }
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate extern char **environ;
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate /*
10577c478bd9Sstevel@tonic-gate  * Check if the environment variable vp affects this csh's behavior
10587c478bd9Sstevel@tonic-gate  * and therefore we should call setlocale() or not.
10597c478bd9Sstevel@tonic-gate  * This function has two side effects when it returns 1:
10607c478bd9Sstevel@tonic-gate  *	variable islocalevar_catnum is set to the LC_xxx value.
10617c478bd9Sstevel@tonic-gate  *	variable islocalevar_catname is set to the string "LC_xxx"
10627c478bd9Sstevel@tonic-gate  */
10637c478bd9Sstevel@tonic-gate static int	islocalevar_catnum;
10647c478bd9Sstevel@tonic-gate static char	*islocalevar_catname;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate static
10677c478bd9Sstevel@tonic-gate bool
10687c478bd9Sstevel@tonic-gate islocalevar(tchar *vp)
10697c478bd9Sstevel@tonic-gate {
10707c478bd9Sstevel@tonic-gate 	static struct lcinfo {
10717c478bd9Sstevel@tonic-gate 		tchar *	evname; /* The name of the env. var. */
10727c478bd9Sstevel@tonic-gate 	} categories_we_care[] = {
10737c478bd9Sstevel@tonic-gate 	    S_LANG, S_LC_ALL, S_LC_CTYPE, S_LC_MESSAGES,
10747c478bd9Sstevel@tonic-gate 	    NOSTR		/* assumption: LC_xxx >= 0 */
10757c478bd9Sstevel@tonic-gate 	};
10767c478bd9Sstevel@tonic-gate 	struct lcinfo *p = categories_we_care;
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	do {
10797c478bd9Sstevel@tonic-gate 		if (strcmp_(vp, p->evname) == 0) {
10807c478bd9Sstevel@tonic-gate 			return (1);
10817c478bd9Sstevel@tonic-gate 		}
10827c478bd9Sstevel@tonic-gate 	} while (((++p)->evname) != NOSTR);
10837c478bd9Sstevel@tonic-gate 	return (0);
10847c478bd9Sstevel@tonic-gate }
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate void
10877c478bd9Sstevel@tonic-gate dosetenv(tchar **v)
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate 	tchar *vp, *lp;
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate #ifdef TRACE
10927c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dosetenv()\n");
10937c478bd9Sstevel@tonic-gate #endif
10947c478bd9Sstevel@tonic-gate 	v++;
10957c478bd9Sstevel@tonic-gate 	if ((vp = *v++) == 0) {
10967c478bd9Sstevel@tonic-gate 		char **ep;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 		if (setintr) {
10997c478bd9Sstevel@tonic-gate 			(void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
11007c478bd9Sstevel@tonic-gate 		}
11017c478bd9Sstevel@tonic-gate 		for (ep = environ; *ep; ep++) {
11027c478bd9Sstevel@tonic-gate 			printf("%s\n", *ep);
11037c478bd9Sstevel@tonic-gate 		}
11047c478bd9Sstevel@tonic-gate 		return;
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	if ((lp = *v++) == 0) {
11087c478bd9Sstevel@tonic-gate 		lp = S_;	/* "" */
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 	local_setenv(vp, lp = globone(lp));
11117c478bd9Sstevel@tonic-gate 	if (eq(vp, S_PATH)) {
11127c478bd9Sstevel@tonic-gate 		importpath(lp);
11137c478bd9Sstevel@tonic-gate 		dohash(xhash);
11147c478bd9Sstevel@tonic-gate 	} else if (islocalevar(vp)) {
11157c478bd9Sstevel@tonic-gate 		if (!setlocale(LC_ALL, "")) {
11167c478bd9Sstevel@tonic-gate 			error("Locale could not be set properly");
11177c478bd9Sstevel@tonic-gate 		}
11187c478bd9Sstevel@tonic-gate 	}
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	xfree(lp);
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate void
11247c478bd9Sstevel@tonic-gate dounsetenv(tchar **v)
11257c478bd9Sstevel@tonic-gate {
11267c478bd9Sstevel@tonic-gate #ifdef TRACE
11277c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dounsetenv()\n");
11287c478bd9Sstevel@tonic-gate #endif
11297c478bd9Sstevel@tonic-gate 	v++;
11307c478bd9Sstevel@tonic-gate 	do {
11317c478bd9Sstevel@tonic-gate 		local_unsetenv(*v);
11327c478bd9Sstevel@tonic-gate 		if (islocalevar(*v++)) {
11337c478bd9Sstevel@tonic-gate 			setlocale(LC_ALL, "");	/* Hope no error! */
11347c478bd9Sstevel@tonic-gate 		}
11357c478bd9Sstevel@tonic-gate 	} while (*v);
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate void
11397c478bd9Sstevel@tonic-gate local_setenv(tchar *name, tchar *val)
11407c478bd9Sstevel@tonic-gate {
11417c478bd9Sstevel@tonic-gate 	char **ep = environ;
11427c478bd9Sstevel@tonic-gate 	tchar *cp;
11437c478bd9Sstevel@tonic-gate 	char *dp;
11447c478bd9Sstevel@tonic-gate 	tchar *ep_;	/* temporary */
11457c478bd9Sstevel@tonic-gate 	char *blk[2], **oep = ep;
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate #ifdef TRACE
11487c478bd9Sstevel@tonic-gate 	/* tprintf("TRACE- local_setenv(%t, %t)\n", name, val); */
11497c478bd9Sstevel@tonic-gate 	/* printf("IN local_setenv args = (%t)\n", val); */
11507c478bd9Sstevel@tonic-gate #endif
11517c478bd9Sstevel@tonic-gate 	for (; *ep; ep++) {
11527c478bd9Sstevel@tonic-gate #ifdef MBCHAR
11537c478bd9Sstevel@tonic-gate 		for (cp = name, dp = *ep; *cp && *dp; cp++) {
11547c478bd9Sstevel@tonic-gate 			/*
11557c478bd9Sstevel@tonic-gate 			 * This loop compares two chars in different
11567c478bd9Sstevel@tonic-gate 			 * representations, EUC (as char *) and wchar_t
11577c478bd9Sstevel@tonic-gate 			 * (in tchar), and ends when they are different.
11587c478bd9Sstevel@tonic-gate 			 */
11597c478bd9Sstevel@tonic-gate 			wchar_t	dwc;
11607c478bd9Sstevel@tonic-gate 			int	n;
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 			n = mbtowc(&dwc, dp, MB_CUR_MAX);
11637c478bd9Sstevel@tonic-gate 			if (n <= 0) {
11647c478bd9Sstevel@tonic-gate 				break; /* Illegal multibyte. */
11657c478bd9Sstevel@tonic-gate 			}
11667c478bd9Sstevel@tonic-gate 			dp += n; /* Advance to next multibyte char. */
11677c478bd9Sstevel@tonic-gate 			if (dwc == (wchar_t)(*cp & TRIM)) {
11687c478bd9Sstevel@tonic-gate 				continue;
11697c478bd9Sstevel@tonic-gate 			} else  {
11707c478bd9Sstevel@tonic-gate 				break;
11717c478bd9Sstevel@tonic-gate 			}
11727c478bd9Sstevel@tonic-gate 		}
11737c478bd9Sstevel@tonic-gate #else /* !MBCHAR */
11747c478bd9Sstevel@tonic-gate 		for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) {
11757c478bd9Sstevel@tonic-gate 			continue;
11767c478bd9Sstevel@tonic-gate 		}
11777c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */
11787c478bd9Sstevel@tonic-gate 		if (*cp != 0 || *dp != '=') {
11797c478bd9Sstevel@tonic-gate 			continue;
11807c478bd9Sstevel@tonic-gate 		}
11817c478bd9Sstevel@tonic-gate 		cp = strspl(S_EQ, val);
11827c478bd9Sstevel@tonic-gate 		xfree(*ep);
11837c478bd9Sstevel@tonic-gate 		ep_ = strspl(name, cp);		/* ep_ is xalloc'ed */
11847c478bd9Sstevel@tonic-gate 		xfree(cp);
11857c478bd9Sstevel@tonic-gate 		/*
11867c478bd9Sstevel@tonic-gate 		 * Trimming is not needed here.
11877c478bd9Sstevel@tonic-gate 		 * trim();
11887c478bd9Sstevel@tonic-gate 		 */
11897c478bd9Sstevel@tonic-gate 		*ep = tstostr(NULL, ep_);
11907c478bd9Sstevel@tonic-gate 		xfree(ep_);			/* because temp.  use */
11917c478bd9Sstevel@tonic-gate 		return;
11927c478bd9Sstevel@tonic-gate 	}
11937c478bd9Sstevel@tonic-gate 	ep_ = strspl(name, S_EQ);		/* ep_ is xalloc'ed */
11947c478bd9Sstevel@tonic-gate 	blk[0] = tstostr(NULL, ep_);
11957c478bd9Sstevel@tonic-gate 	blk[1] = 0;
11967c478bd9Sstevel@tonic-gate 	xfree(ep_);
11976c02b4a4Smuffin 	environ = (char **)blkspl_((char **)environ, blk);
11987c478bd9Sstevel@tonic-gate 	xfree((void *)oep);
11997c478bd9Sstevel@tonic-gate 	local_setenv(name, val);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate void
12037c478bd9Sstevel@tonic-gate local_unsetenv(tchar *name)
12047c478bd9Sstevel@tonic-gate {
12057c478bd9Sstevel@tonic-gate 	char **ep = environ;
12067c478bd9Sstevel@tonic-gate 	tchar *cp;
12077c478bd9Sstevel@tonic-gate 	char *dp;
12087c478bd9Sstevel@tonic-gate 	char **oep = ep;
12097c478bd9Sstevel@tonic-gate 	char *cp_;	/* tmp use */
12106c02b4a4Smuffin 	static int cnt = 0;	/* delete counter */
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate #ifdef TRACE
12137c478bd9Sstevel@tonic-gate 	tprintf("TRACE- local_unsetenv()\n");
12147c478bd9Sstevel@tonic-gate #endif
12157c478bd9Sstevel@tonic-gate 	for (; *ep; ep++) {
12167c478bd9Sstevel@tonic-gate #ifdef MBCHAR
12177c478bd9Sstevel@tonic-gate 		for (cp = name, dp = *ep; *cp && *dp; cp++) {
12187c478bd9Sstevel@tonic-gate 			/*
12197c478bd9Sstevel@tonic-gate 			 * This loop compares two chars in different
12207c478bd9Sstevel@tonic-gate 			 * representations, EUC (as char *) and wchar_t
12217c478bd9Sstevel@tonic-gate 			 * (in tchar), and ends when they are different.
12227c478bd9Sstevel@tonic-gate 			 */
12237c478bd9Sstevel@tonic-gate 			wchar_t	dwc;
12247c478bd9Sstevel@tonic-gate 			int	n;
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 			n = mbtowc(&dwc, dp, MB_CUR_MAX);
12277c478bd9Sstevel@tonic-gate 			if (n <= 0) {
12287c478bd9Sstevel@tonic-gate 				break; /* Illegal multibyte. */
12297c478bd9Sstevel@tonic-gate 			}
12307c478bd9Sstevel@tonic-gate 			dp += n; /* Advance to next multibyte char. */
12317c478bd9Sstevel@tonic-gate 			if (dwc == (wchar_t)(*cp & TRIM)) {
12327c478bd9Sstevel@tonic-gate 				continue;
12337c478bd9Sstevel@tonic-gate 			} else {
12347c478bd9Sstevel@tonic-gate 				break;
12357c478bd9Sstevel@tonic-gate 			}
12367c478bd9Sstevel@tonic-gate 		}
12377c478bd9Sstevel@tonic-gate #else /* !MBCHAR */
12387c478bd9Sstevel@tonic-gate 		for (cp = name, dp = *ep; *cp && (char)*cp == *dp; cp++, dp++) {
12397c478bd9Sstevel@tonic-gate 			continue;
12407c478bd9Sstevel@tonic-gate 		}
12417c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */
12427c478bd9Sstevel@tonic-gate 		if (*cp != 0 || *dp != '=') {
12437c478bd9Sstevel@tonic-gate 			continue;
12447c478bd9Sstevel@tonic-gate 		}
12457c478bd9Sstevel@tonic-gate 		cp_ = *ep;
12467c478bd9Sstevel@tonic-gate 		*ep = 0;
12476c02b4a4Smuffin 		environ = (char **)blkspl_((char **)environ, ep+1);
12487c478bd9Sstevel@tonic-gate 		*ep = cp_;
12497c478bd9Sstevel@tonic-gate 		xfree(cp_);
12507c478bd9Sstevel@tonic-gate 		xfree((void *)oep);
12517c478bd9Sstevel@tonic-gate 		return;
12527c478bd9Sstevel@tonic-gate 	}
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate void
12567c478bd9Sstevel@tonic-gate doumask(tchar **v)
12577c478bd9Sstevel@tonic-gate {
12587c478bd9Sstevel@tonic-gate 	tchar *cp = v[1];
12597c478bd9Sstevel@tonic-gate 	int i;
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate #ifdef TRACE
12627c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dounmask()\n");
12637c478bd9Sstevel@tonic-gate #endif
12647c478bd9Sstevel@tonic-gate 	if (cp == 0) {
12657c478bd9Sstevel@tonic-gate 		i = umask(0);
12667c478bd9Sstevel@tonic-gate 		(void) umask(i);
12677c478bd9Sstevel@tonic-gate 		printf("%o\n", i);
12687c478bd9Sstevel@tonic-gate 		return;
12697c478bd9Sstevel@tonic-gate 	}
12707c478bd9Sstevel@tonic-gate 	i = 0;
12717c478bd9Sstevel@tonic-gate 	while (digit(*cp) && *cp != '8' && *cp != '9') {
12727c478bd9Sstevel@tonic-gate 		i = i * 8 + *cp++ - '0';
12737c478bd9Sstevel@tonic-gate 	}
12747c478bd9Sstevel@tonic-gate 	if (*cp || i < 0 || i > 0777) {
12757c478bd9Sstevel@tonic-gate 		bferr("Improper mask");
12767c478bd9Sstevel@tonic-gate 	}
12777c478bd9Sstevel@tonic-gate 	(void) umask(i);
12787c478bd9Sstevel@tonic-gate }
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate struct limits *
12827c478bd9Sstevel@tonic-gate findlim(tchar *cp)
12837c478bd9Sstevel@tonic-gate {
12847c478bd9Sstevel@tonic-gate 	struct limits *lp, *res;
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate #ifdef TRACE
12877c478bd9Sstevel@tonic-gate 	tprintf("TRACE- findlim()\n");
12887c478bd9Sstevel@tonic-gate #endif
12897c478bd9Sstevel@tonic-gate 	res = 0;
12907c478bd9Sstevel@tonic-gate 	for (lp = limits; lp->limconst >= 0; lp++) {
12917c478bd9Sstevel@tonic-gate 		if (prefix(cp, lp->limname)) {
12927c478bd9Sstevel@tonic-gate 			if (res) {
12937c478bd9Sstevel@tonic-gate 				bferr("Ambiguous");
12947c478bd9Sstevel@tonic-gate 			}
12957c478bd9Sstevel@tonic-gate 			res = lp;
12967c478bd9Sstevel@tonic-gate 		}
12977c478bd9Sstevel@tonic-gate 	}
12987c478bd9Sstevel@tonic-gate 	if (res) {
12997c478bd9Sstevel@tonic-gate 		return (res);
13007c478bd9Sstevel@tonic-gate 	}
13017c478bd9Sstevel@tonic-gate 	bferr("No such limit");
13027c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
13037c478bd9Sstevel@tonic-gate }
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate void
13067c478bd9Sstevel@tonic-gate dolimit(tchar **v)
13077c478bd9Sstevel@tonic-gate {
13087c478bd9Sstevel@tonic-gate 	struct limits *lp;
13097c478bd9Sstevel@tonic-gate 	rlim_t limit;
13107c478bd9Sstevel@tonic-gate 	tchar hard = 0;
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate #ifdef TRACE
13137c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dolimit()\n");
13147c478bd9Sstevel@tonic-gate #endif
13157c478bd9Sstevel@tonic-gate 	v++;
13167c478bd9Sstevel@tonic-gate 	if (*v && eq(*v, S_h)) {
13177c478bd9Sstevel@tonic-gate 		hard = 1;
13187c478bd9Sstevel@tonic-gate 		v++;
13197c478bd9Sstevel@tonic-gate 	}
13207c478bd9Sstevel@tonic-gate 	if (*v == 0) {
13217c478bd9Sstevel@tonic-gate 		for (lp = limits; lp->limconst >= 0; lp++) {
13227c478bd9Sstevel@tonic-gate 			plim(lp, hard);
13237c478bd9Sstevel@tonic-gate 		}
13247c478bd9Sstevel@tonic-gate 		return;
13257c478bd9Sstevel@tonic-gate 	}
13267c478bd9Sstevel@tonic-gate 	lp = findlim(v[0]);
13277c478bd9Sstevel@tonic-gate 	if (v[1] == 0) {
13287c478bd9Sstevel@tonic-gate 		plim(lp,  hard);
13297c478bd9Sstevel@tonic-gate 		return;
13307c478bd9Sstevel@tonic-gate 	}
13317c478bd9Sstevel@tonic-gate 	switch (getval(lp, v+1, &limit)) {
13327c478bd9Sstevel@tonic-gate 	case 0:
13337c478bd9Sstevel@tonic-gate 		error("Value specified for limit is too large");
13347c478bd9Sstevel@tonic-gate 		return;
13357c478bd9Sstevel@tonic-gate 	case (-1):
13367c478bd9Sstevel@tonic-gate 		error("Numeric conversion failed");
13377c478bd9Sstevel@tonic-gate 		return;
13387c478bd9Sstevel@tonic-gate 	default:
13397c478bd9Sstevel@tonic-gate 		if (setlim(lp, hard, limit) < 0) {
13407c478bd9Sstevel@tonic-gate 			error(NOSTR);
13417c478bd9Sstevel@tonic-gate 		}
13427c478bd9Sstevel@tonic-gate 	}
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate static int
13467c478bd9Sstevel@tonic-gate getval(struct limits *lp, tchar **v, rlim_t *retval)
13477c478bd9Sstevel@tonic-gate {
13487c478bd9Sstevel@tonic-gate 	rlim_t value, tmp, tmp2;
13497c478bd9Sstevel@tonic-gate 	tchar *cp = *v++;
13507c478bd9Sstevel@tonic-gate 	char chbuf[BUFSIZ * MB_LEN_MAX];
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate #ifdef TRACE
13537c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getval()\n");
13547c478bd9Sstevel@tonic-gate #endif
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	tstostr(chbuf, cp);
13577c478bd9Sstevel@tonic-gate 	errno = 0;
13587c478bd9Sstevel@tonic-gate 	value = strtoull(chbuf, NULL, 0);
13597c478bd9Sstevel@tonic-gate /*
13607c478bd9Sstevel@tonic-gate  * we must accept zero, but the conversion can fail and give us
13617c478bd9Sstevel@tonic-gate  * zero as well...try to deal with it as gracefully as possible
13627c478bd9Sstevel@tonic-gate  * by checking for EINVAL
13637c478bd9Sstevel@tonic-gate  */
13647c478bd9Sstevel@tonic-gate 	if (value == 0 && errno == EINVAL)
13657c478bd9Sstevel@tonic-gate 		return (-1);
13667c478bd9Sstevel@tonic-gate 
13677c478bd9Sstevel@tonic-gate 	while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') {
13687c478bd9Sstevel@tonic-gate 		cp++;
13697c478bd9Sstevel@tonic-gate 	}
13707c478bd9Sstevel@tonic-gate 	if (*cp == 0) {
13717c478bd9Sstevel@tonic-gate 		if (*v == 0) {
13727c478bd9Sstevel@tonic-gate 			tmp = value * (rlim_t)lp->limdiv;
13737c478bd9Sstevel@tonic-gate 			/* Check for overflow */
13747c478bd9Sstevel@tonic-gate 			if (tmp >= value) {
13757c478bd9Sstevel@tonic-gate 				*retval = tmp;
13767c478bd9Sstevel@tonic-gate 				return (1);
13777c478bd9Sstevel@tonic-gate 			} else {
13787c478bd9Sstevel@tonic-gate 				return (0);
13797c478bd9Sstevel@tonic-gate 			}
13807c478bd9Sstevel@tonic-gate 		}
13817c478bd9Sstevel@tonic-gate 		cp = *v;
13827c478bd9Sstevel@tonic-gate 	}
13837c478bd9Sstevel@tonic-gate 	switch (*cp) {
13847c478bd9Sstevel@tonic-gate 
13857c478bd9Sstevel@tonic-gate 	case ':':
13867c478bd9Sstevel@tonic-gate 		if (lp->limconst != RLIMIT_CPU) {
13877c478bd9Sstevel@tonic-gate 			goto badscal;
13887c478bd9Sstevel@tonic-gate 		}
13897c478bd9Sstevel@tonic-gate 		tstostr(chbuf, cp + 1);
13907c478bd9Sstevel@tonic-gate 		tmp = strtoull(chbuf, NULL, 0);
13917c478bd9Sstevel@tonic-gate 		tmp2 = value * 60 + tmp;
13927c478bd9Sstevel@tonic-gate 		if (tmp2 >= value) {
13937c478bd9Sstevel@tonic-gate 			*retval = tmp2;
13947c478bd9Sstevel@tonic-gate 			return (1);
13957c478bd9Sstevel@tonic-gate 		} else {
13967c478bd9Sstevel@tonic-gate 			return (0);
13977c478bd9Sstevel@tonic-gate 		}
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 	case 'h':
14007c478bd9Sstevel@tonic-gate 		if (lp->limconst != RLIMIT_CPU) {
14017c478bd9Sstevel@tonic-gate 			goto badscal;
14027c478bd9Sstevel@tonic-gate 		}
14037c478bd9Sstevel@tonic-gate 		limtail(cp, S_hours);
14047c478bd9Sstevel@tonic-gate 		tmp = value * 3600;
14057c478bd9Sstevel@tonic-gate 		if (tmp < value) {
14067c478bd9Sstevel@tonic-gate 			return (0);
14077c478bd9Sstevel@tonic-gate 		}
14087c478bd9Sstevel@tonic-gate 		value = tmp;
14097c478bd9Sstevel@tonic-gate 		break;
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	case 'm':
14127c478bd9Sstevel@tonic-gate 		if (lp->limconst == RLIMIT_CPU) {
14137c478bd9Sstevel@tonic-gate 			limtail(cp, S_minutes);
14147c478bd9Sstevel@tonic-gate 			tmp = value * 60;
14157c478bd9Sstevel@tonic-gate 			if (tmp < value) {
14167c478bd9Sstevel@tonic-gate 				return (0);
14177c478bd9Sstevel@tonic-gate 			}
14187c478bd9Sstevel@tonic-gate 			value = tmp;
14197c478bd9Sstevel@tonic-gate 			break;
14207c478bd9Sstevel@tonic-gate 		}
14217c478bd9Sstevel@tonic-gate 	case 'M':
14227c478bd9Sstevel@tonic-gate 		if (lp->limconst == RLIMIT_CPU) {
14237c478bd9Sstevel@tonic-gate 			goto badscal;
14247c478bd9Sstevel@tonic-gate 		}
14257c478bd9Sstevel@tonic-gate 		*cp = 'm';
14267c478bd9Sstevel@tonic-gate 		limtail(cp, S_megabytes);
14277c478bd9Sstevel@tonic-gate 		tmp = value * 1024 * 1024;
14287c478bd9Sstevel@tonic-gate 		if (tmp < value) {
14297c478bd9Sstevel@tonic-gate 			return (0);
14307c478bd9Sstevel@tonic-gate 		}
14317c478bd9Sstevel@tonic-gate 		value = tmp;
14327c478bd9Sstevel@tonic-gate 		break;
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	case 's':
14357c478bd9Sstevel@tonic-gate 		if (lp->limconst != RLIMIT_CPU) {
14367c478bd9Sstevel@tonic-gate 			goto badscal;
14377c478bd9Sstevel@tonic-gate 		}
14387c478bd9Sstevel@tonic-gate 		limtail(cp, S_seconds);
14397c478bd9Sstevel@tonic-gate 		break;
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 	case 'k':
14427c478bd9Sstevel@tonic-gate 		if (lp->limconst == RLIMIT_CPU) {
14437c478bd9Sstevel@tonic-gate 			goto badscal;
14447c478bd9Sstevel@tonic-gate 		}
14457c478bd9Sstevel@tonic-gate 		limtail(cp, S_kbytes);
14467c478bd9Sstevel@tonic-gate 		tmp = value * 1024;
14477c478bd9Sstevel@tonic-gate 		if (tmp < value) {
14487c478bd9Sstevel@tonic-gate 			return (0);
14497c478bd9Sstevel@tonic-gate 		}
14507c478bd9Sstevel@tonic-gate 		value = tmp;
14517c478bd9Sstevel@tonic-gate 		break;
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 	case 'u':
14547c478bd9Sstevel@tonic-gate 		limtail(cp, S_unlimited);
14557c478bd9Sstevel@tonic-gate 		*retval = RLIM_INFINITY;
14567c478bd9Sstevel@tonic-gate 		return (1);
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 	default:
14597c478bd9Sstevel@tonic-gate badscal:
14607c478bd9Sstevel@tonic-gate 		bferr("Improper or unknown scale factor");
14617c478bd9Sstevel@tonic-gate 	}
14627c478bd9Sstevel@tonic-gate 	*retval = value;
14637c478bd9Sstevel@tonic-gate 	return (1);
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate void
14677c478bd9Sstevel@tonic-gate limtail(tchar *cp, tchar *str0)
14687c478bd9Sstevel@tonic-gate {
14697c478bd9Sstevel@tonic-gate 	tchar *str = str0;
14707c478bd9Sstevel@tonic-gate #ifdef TRACE
14717c478bd9Sstevel@tonic-gate 	tprintf("TRACE- limtail()\n");
14727c478bd9Sstevel@tonic-gate #endif
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	while (*cp && *cp == *str) {
14757c478bd9Sstevel@tonic-gate 		cp++, str++;
14767c478bd9Sstevel@tonic-gate 	}
14777c478bd9Sstevel@tonic-gate 	if (*cp) {
14787c478bd9Sstevel@tonic-gate 		error("Bad scaling; did you mean ``%t''?", str0);
14797c478bd9Sstevel@tonic-gate 	}
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate void
14837c478bd9Sstevel@tonic-gate plim(struct limits *lp, tchar hard)
14847c478bd9Sstevel@tonic-gate {
14857c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
14867c478bd9Sstevel@tonic-gate 	char buf[BUFSZ];
14877c478bd9Sstevel@tonic-gate 	char *pbuf;
14887c478bd9Sstevel@tonic-gate 	rlim_t limit;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate #ifdef TRACE
14917c478bd9Sstevel@tonic-gate 	tprintf("TRACE- plim()\n");
14927c478bd9Sstevel@tonic-gate #endif
14937c478bd9Sstevel@tonic-gate 	printf("%t \t", lp->limname);
14947c478bd9Sstevel@tonic-gate 	(void) getrlimit(lp->limconst, &rlim);
14957c478bd9Sstevel@tonic-gate 	limit = hard ? rlim.rlim_max : rlim.rlim_cur;
14967c478bd9Sstevel@tonic-gate 	if (limit == RLIM_INFINITY) {
14977c478bd9Sstevel@tonic-gate 		printf("unlimited");
14987c478bd9Sstevel@tonic-gate 	} else if (lp->limconst == RLIMIT_CPU) {
14997c478bd9Sstevel@tonic-gate 		psecs_ull(limit);
15007c478bd9Sstevel@tonic-gate 	} else {
15017c478bd9Sstevel@tonic-gate 		buf[BUFSZ - 1] = '\0';
15027c478bd9Sstevel@tonic-gate 		pbuf = ulltostr((limit / lp->limdiv), &buf[BUFSZ - 1]);
15037c478bd9Sstevel@tonic-gate 		printf("%s %t", pbuf, lp->limscale);
15047c478bd9Sstevel@tonic-gate 	}
15057c478bd9Sstevel@tonic-gate 	printf("\n");
15067c478bd9Sstevel@tonic-gate }
15077c478bd9Sstevel@tonic-gate 
15087c478bd9Sstevel@tonic-gate void
15097c478bd9Sstevel@tonic-gate dounlimit(tchar **v)
15107c478bd9Sstevel@tonic-gate {
15117c478bd9Sstevel@tonic-gate 	struct limits *lp;
15127c478bd9Sstevel@tonic-gate 	int err = 0;
15137c478bd9Sstevel@tonic-gate 	tchar hard = 0;
15147c478bd9Sstevel@tonic-gate #ifdef TRACE
15157c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dounlimit()\n");
15167c478bd9Sstevel@tonic-gate #endif
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 	v++;
15197c478bd9Sstevel@tonic-gate 	if (*v && eq(*v, S_h)) {
15207c478bd9Sstevel@tonic-gate 		hard = 1;
15217c478bd9Sstevel@tonic-gate 		v++;
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate 	if (*v == 0) {
15247c478bd9Sstevel@tonic-gate 		for (lp = limits; lp->limconst >= 0; lp++) {
15257c478bd9Sstevel@tonic-gate 			if (setlim(lp, hard, RLIM_INFINITY) < 0) {
15267c478bd9Sstevel@tonic-gate 				err++;
15277c478bd9Sstevel@tonic-gate 			}
15287c478bd9Sstevel@tonic-gate 		}
15297c478bd9Sstevel@tonic-gate 		if (err) {
15307c478bd9Sstevel@tonic-gate 			error(NULL);
15317c478bd9Sstevel@tonic-gate 		}
15327c478bd9Sstevel@tonic-gate 		return;
15337c478bd9Sstevel@tonic-gate 	}
15347c478bd9Sstevel@tonic-gate 	while (*v) {
15357c478bd9Sstevel@tonic-gate 		lp = findlim(*v++);
15367c478bd9Sstevel@tonic-gate 		if (setlim(lp, hard, RLIM_INFINITY) < 0) {
15377c478bd9Sstevel@tonic-gate 			error(NULL);
15387c478bd9Sstevel@tonic-gate 		}
15397c478bd9Sstevel@tonic-gate 	}
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate int
15437c478bd9Sstevel@tonic-gate setlim(struct limits *lp, tchar hard, rlim_t limit)
15447c478bd9Sstevel@tonic-gate {
15457c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate #ifdef TRACE
15487c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setlim()\n");
15497c478bd9Sstevel@tonic-gate #endif
15507c478bd9Sstevel@tonic-gate 	(void) getrlimit(lp->limconst, &rlim);
15517c478bd9Sstevel@tonic-gate 	if (hard) {
15527c478bd9Sstevel@tonic-gate 		rlim.rlim_max = limit;
15537c478bd9Sstevel@tonic-gate 	} else if (limit == RLIM_INFINITY && geteuid() != 0) {
15547c478bd9Sstevel@tonic-gate 		rlim.rlim_cur = rlim.rlim_max;
15557c478bd9Sstevel@tonic-gate 	} else {
15567c478bd9Sstevel@tonic-gate 		rlim.rlim_cur = limit;
15577c478bd9Sstevel@tonic-gate 	}
15587c478bd9Sstevel@tonic-gate 	if (setrlimit(lp->limconst, &rlim) < 0) {
15597c478bd9Sstevel@tonic-gate 		printf("%t: %t: Can't %s%s limit\n", bname, lp->limname,
15607c478bd9Sstevel@tonic-gate 		    limit == RLIM_INFINITY ? "remove" : "set",
15617c478bd9Sstevel@tonic-gate 		    hard ? " hard" : "");
15627c478bd9Sstevel@tonic-gate 		return (-1);
15637c478bd9Sstevel@tonic-gate 	}
15647c478bd9Sstevel@tonic-gate 	return (0);
15657c478bd9Sstevel@tonic-gate }
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate void
15687c478bd9Sstevel@tonic-gate dosuspend()
15697c478bd9Sstevel@tonic-gate {
15707c478bd9Sstevel@tonic-gate 	int ctpgrp;
15717c478bd9Sstevel@tonic-gate 	void (*old)();
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate #ifdef TRACE
15747c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dosuspend()\n");
15757c478bd9Sstevel@tonic-gate #endif
15767c478bd9Sstevel@tonic-gate 	if (loginsh) {
15777c478bd9Sstevel@tonic-gate 		error("Can't suspend a login shell (yet)");
15787c478bd9Sstevel@tonic-gate 	}
15797c478bd9Sstevel@tonic-gate 	if (getpid() == getsid(0)) {
15807c478bd9Sstevel@tonic-gate 		error("Can't suspend this shell");
15817c478bd9Sstevel@tonic-gate 	}
15827c478bd9Sstevel@tonic-gate 	untty();
15837c478bd9Sstevel@tonic-gate 	old = (void (*)())signal(SIGTSTP, SIG_DFL);
15847c478bd9Sstevel@tonic-gate 	(void) kill(0, SIGTSTP);
15857c478bd9Sstevel@tonic-gate 	/* the shell stops here */
15867c478bd9Sstevel@tonic-gate 	(void) signal(SIGTSTP, old);
15877c478bd9Sstevel@tonic-gate 	if (tpgrp != -1) {
15887c478bd9Sstevel@tonic-gate retry:
15897c478bd9Sstevel@tonic-gate 		(void) ioctl(FSHTTY, TIOCGPGRP,  (char *)&ctpgrp);
15907c478bd9Sstevel@tonic-gate 		if (ctpgrp != opgrp) {
15917c478bd9Sstevel@tonic-gate 			old = (void (*)())signal(SIGTTIN, SIG_DFL);
15927c478bd9Sstevel@tonic-gate 			(void) kill(0, SIGTTIN);
15937c478bd9Sstevel@tonic-gate 			(void) signal(SIGTTIN, old);
15947c478bd9Sstevel@tonic-gate 			goto retry;
15957c478bd9Sstevel@tonic-gate 		}
15967c478bd9Sstevel@tonic-gate 		(void) setpgid(0, shpgrp);
15977c478bd9Sstevel@tonic-gate 		(void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp);
15987c478bd9Sstevel@tonic-gate 	}
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate 
16017c478bd9Sstevel@tonic-gate void
16027c478bd9Sstevel@tonic-gate doeval(tchar **v)
16037c478bd9Sstevel@tonic-gate {
16047c478bd9Sstevel@tonic-gate 	tchar **oevalvec = evalvec;
16057c478bd9Sstevel@tonic-gate 	tchar *oevalp = evalp;
16067c478bd9Sstevel@tonic-gate 	jmp_buf osetexit;
16077c478bd9Sstevel@tonic-gate 	int reenter;
16087c478bd9Sstevel@tonic-gate 	tchar **gv = 0;
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate #ifdef TRACE
16117c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doeval()\n");
16127c478bd9Sstevel@tonic-gate #endif
16137c478bd9Sstevel@tonic-gate 	v++;
16147c478bd9Sstevel@tonic-gate 	if (*v == 0) {
16157c478bd9Sstevel@tonic-gate 		return;
16167c478bd9Sstevel@tonic-gate 	}
16177c478bd9Sstevel@tonic-gate 	gflag = 0, tglob(v);
16187c478bd9Sstevel@tonic-gate 	if (gflag) {
16197c478bd9Sstevel@tonic-gate 		gv = v = glob(v);
16207c478bd9Sstevel@tonic-gate 		gargv = 0;
16217c478bd9Sstevel@tonic-gate 		if (v == 0) {
16227c478bd9Sstevel@tonic-gate 			error("No match");
16237c478bd9Sstevel@tonic-gate 		}
16247c478bd9Sstevel@tonic-gate 		v = copyblk(v);
16257c478bd9Sstevel@tonic-gate 	} else {
16267c478bd9Sstevel@tonic-gate 		trim(v);
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 	getexit(osetexit);
16297c478bd9Sstevel@tonic-gate 	reenter = 0;
16307c478bd9Sstevel@tonic-gate 	setexit();
16317c478bd9Sstevel@tonic-gate 	reenter++;
16327c478bd9Sstevel@tonic-gate 	if (reenter == 1) {
16337c478bd9Sstevel@tonic-gate 		evalvec = v;
16347c478bd9Sstevel@tonic-gate 		evalp = 0;
16357c478bd9Sstevel@tonic-gate 		process(0);
16367c478bd9Sstevel@tonic-gate 	}
16377c478bd9Sstevel@tonic-gate 	evalvec = oevalvec;
16387c478bd9Sstevel@tonic-gate 	evalp = oevalp;
16397c478bd9Sstevel@tonic-gate 	doneinp = 0;
16407c478bd9Sstevel@tonic-gate 	if (gv) {
16417c478bd9Sstevel@tonic-gate 		blkfree(gv);
16427c478bd9Sstevel@tonic-gate 	}
16437c478bd9Sstevel@tonic-gate 	resexit(osetexit);
16447c478bd9Sstevel@tonic-gate 	if (reenter >= 2) {
16457c478bd9Sstevel@tonic-gate 		error(NULL);
16467c478bd9Sstevel@tonic-gate 	}
16477c478bd9Sstevel@tonic-gate }
1648