xref: /original-bsd/bin/csh/func.c (revision 55330032)
1 static	char *sccsid = "@(#)func.c 4.1 10/09/80";
2 
3 #include "sh.h"
4 #include <sys/ioctl.h>
5 
6 /*
7  * C shell
8  */
9 
10 struct biltins *
11 isbfunc(t)
12 	register struct command *t;
13 {
14 	register char *cp = t->t_dcom[0];
15 	register char *dp;
16 	register struct biltins *bp;
17 	int dolabel(), dofg1(), dobg1();
18 	static struct biltins label = { "", dolabel, 0, 0 };
19 	static struct biltins foregnd = { "%job", dofg1, 0, 0 };
20 	static struct biltins backgnd = { "%job &", dobg1, 0, 0 };
21 
22 	if (lastchr(cp) == ':') {
23 		label.bname = cp;
24 		return (&label);
25 	}
26 	if (*cp == '%') {
27 		if (t->t_dflg & FAND) {
28 			t->t_dflg &= ~FAND;
29 			backgnd.bname = cp;
30 			return (&backgnd);
31 		}
32 		foregnd.bname = cp;
33 		return (&foregnd);
34 	}
35 	for (bp = bfunc; dp = bp->bname; bp++) {
36 		if (dp[0] == cp[0] && eq(dp, cp))
37 			return (bp);
38 		if (dp[0] > cp[0])
39 			break;
40 	}
41 	return (0);
42 }
43 
44 func(t, bp)
45 	register struct command *t;
46 	register struct biltins *bp;
47 {
48 	int i;
49 
50 	xechoit(t->t_dcom);
51 	setname(bp->bname);
52 	i = blklen(t->t_dcom) - 1;
53 	if (i < bp->minargs)
54 		bferr("Too few arguments");
55 	if (i > bp->maxargs)
56 		bferr("Too many arguments");
57 	(*bp->bfunct)(t->t_dcom, t);
58 }
59 
60 dolabel()
61 {
62 
63 }
64 
65 doonintr(v)
66 	char **v;
67 {
68 	register char *cp;
69 	register char *vv = v[1];
70 
71 	if (parintr == SIG_IGN)
72 		return;
73 	if (setintr && intty)
74 		bferr("Can't from terminal");
75 	cp = gointr, gointr = 0, xfree(cp);
76 	if (vv == 0) {
77 		if (setintr)
78 			sighold(SIGINT);
79 		else
80 			sigset(SIGINT, SIG_DFL);
81 		gointr = 0;
82 	} else if (eq((vv = strip(vv)), "-")) {
83 		sigset(SIGINT, SIG_IGN);
84 		gointr = "-";
85 	} else {
86 		gointr = savestr(vv);
87 		sigset(SIGINT, pintr);
88 	}
89 }
90 
91 donohup()
92 {
93 
94 	if (intty)
95 		bferr("Can't from terminal");
96 	if (setintr == 0) {
97 		signal(SIGHUP, SIG_IGN);
98 #ifdef CC
99 		submit(getpid());
100 #endif
101 	}
102 }
103 
104 dozip()
105 {
106 
107 	;
108 }
109 
110 prvars()
111 {
112 
113 	plist(&shvhed);
114 }
115 
116 doalias(v)
117 	register char **v;
118 {
119 	register struct varent *vp;
120 	register char *p;
121 
122 	v++;
123 	p = *v++;
124 	if (p == 0)
125 		plist(&aliases);
126 	else if (*v == 0) {
127 		vp = adrof1(strip(p), &aliases);
128 		if (vp)
129 			blkpr(vp->vec), printf("\n");
130 	} else {
131 		if (eq(p, "alias") || eq(p, "unalias")) {
132 			setname(p);
133 			bferr("Too dangerous to alias that");
134 		}
135 		set1(strip(p), saveblk(v), &aliases);
136 	}
137 }
138 
139 unalias(v)
140 	char **v;
141 {
142 
143 	unset1(v, &aliases);
144 }
145 
146 dologout()
147 {
148 
149 	islogin();
150 	goodbye();
151 }
152 
153 dologin(v)
154 	char **v;
155 {
156 
157 	islogin();
158 	signal(SIGTERM, parterm);
159 	execl("/bin/login", "login", v[1], 0);
160 	untty();
161 	exit(1);
162 }
163 
164 donewgrp(v)
165 	char **v;
166 {
167 
168 	signal(SIGTERM, parterm);
169 	execl("/bin/newgrp", "newgrp", v[1], 0);
170 	execl("/usr/bin/newgrp", "newgrp", v[1], 0);
171 	untty();
172 	exit(1);
173 }
174 
175 islogin()
176 {
177 
178 	if (chkstop == 0 && setintr)
179 		panystop(0);
180 	if (loginsh)
181 		return;
182 	error("Not login shell");
183 }
184 
185 doif(v, kp)
186 	char **v;
187 	struct command *kp;
188 {
189 	register int i;
190 	register char **vv;
191 
192 	v++;
193 	i = exp(&v);
194 	vv = v;
195 	if (*vv == NOSTR)
196 		bferr("Empty if");
197 	if (eq(*vv, "then")) {
198 		if (*++vv)
199 			bferr("Improper then");
200 		setname("then");
201 		/*
202 		 * If expression was zero, then scan to else,
203 		 * otherwise just fall into following code.
204 		 */
205 		if (!i)
206 			search(ZIF, 0);
207 		return;
208 	}
209 	/*
210 	 * Simple command attached to this if.
211 	 * Left shift the node in this tree, munging it
212 	 * so we can reexecute it.
213 	 */
214 	if (i) {
215 		lshift(kp->t_dcom, vv - kp->t_dcom);
216 		reexecute(kp);
217 		donefds();
218 	}
219 }
220 
221 /*
222  * Reexecute a command, being careful not
223  * to redo i/o redirection, which is already set up.
224  */
225 reexecute(kp)
226 	register struct command *kp;
227 {
228 
229 	kp->t_dflg &= FSAVE;
230 	kp->t_dflg |= FREDO;
231 	/*
232 	 * If tty is still ours to arbitrate, arbitrate it;
233 	 * otherwise dont even set pgrp's as the jobs would
234 	 * then have no way to get the tty (we can't give it
235 	 * to them, and our parent wouldn't know their pgrp, etc.
236 	 */
237 	execute(kp, tpgrp > 0 ? tpgrp : -1);
238 }
239 
240 doelse()
241 {
242 
243 	search(ZELSE, 0);
244 }
245 
246 dogoto(v)
247 	char **v;
248 {
249 	register struct whyle *wp;
250 	char *lp;
251 
252 	/*
253 	 * While we still can, locate any unknown ends of existing loops.
254 	 * This obscure code is the WORST result of the fact that we
255 	 * don't really parse.
256 	 */
257 	for (wp = whyles; wp; wp = wp->w_next)
258 		if (wp->w_end == 0) {
259 			search(ZBREAK, 0);
260 			wp->w_end = btell();
261 		} else
262 			bseek(wp->w_end);
263 	search(ZGOTO, 0, lp = globone(v[1]));
264 	xfree(lp);
265 	/*
266 	 * Eliminate loops which were exited.
267 	 */
268 	wfree();
269 }
270 
271 doswitch(v)
272 	register char **v;
273 {
274 	register char *cp, *lp;
275 
276 	v++;
277 	if (!*v || *(*v++) != '(')
278 		goto syntax;
279 	cp = **v == ')' ? "" : *v++;
280 	if (*(*v++) != ')')
281 		v--;
282 	if (*v)
283 syntax:
284 		error("Syntax error");
285 	search(ZSWITCH, 0, lp = globone(cp));
286 	xfree(lp);
287 }
288 
289 dobreak()
290 {
291 
292 	if (whyles)
293 		toend();
294 	else
295 		bferr("Not in while/foreach");
296 }
297 
298 doexit(v)
299 	char **v;
300 {
301 
302 	if (chkstop == 0)
303 		panystop(0);
304 	/*
305 	 * Don't DEMAND parentheses here either.
306 	 */
307 	v++;
308 	if (*v) {
309 		set("status", putn(exp(&v)));
310 		if (*v)
311 			bferr("Expression syntax");
312 	}
313 	btoeof();
314 	if (intty)
315 		close(SHIN);
316 }
317 
318 doforeach(v)
319 	register char **v;
320 {
321 	register char *cp;
322 	register struct whyle *nwp;
323 
324 	v++;
325 	cp = strip(*v);
326 	while (*cp && letter(*cp))
327 		cp++;
328 	if (*cp || strlen(*v) >= 20)
329 		bferr("Invalid variable");
330 	cp = *v++;
331 	if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
332 		bferr("Words not ()'ed");
333 	v++;
334 	gflag = 0, rscan(v, tglob);
335 	v = glob(v);
336 	if (v == 0)
337 		bferr("No match");
338 	nwp = (struct whyle *) calloc(1, sizeof *nwp);
339 	nwp->w_fe = nwp->w_fe0 = v; gargv = 0;
340 	nwp->w_start = btell();
341 	nwp->w_fename = savestr(cp);
342 	nwp->w_next = whyles;
343 	whyles = nwp;
344 	/*
345 	 * Pre-read the loop so as to be more
346 	 * comprehensible to a terminal user.
347 	 */
348 	if (intty)
349 		preread();
350 	doagain();
351 }
352 
353 dowhile(v)
354 	char **v;
355 {
356 	register int status;
357 	register bool again = whyles != 0 && whyles->w_start == lineloc &&
358 	    whyles->w_fename == 0;
359 
360 	v++;
361 	/*
362 	 * Implement prereading here also, taking care not to
363 	 * evaluate the expression before the loop has been read up
364 	 * from a terminal.
365 	 */
366 	if (intty && !again)
367 		status = !exp0(&v, 1);
368 	else
369 		status = !exp(&v);
370 	if (*v)
371 		bferr("Expression syntax");
372 	if (!again) {
373 		register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp));
374 
375 		nwp->w_start = lineloc;
376 		nwp->w_end = 0;
377 		nwp->w_next = whyles;
378 		whyles = nwp;
379 		if (intty) {
380 			/*
381 			 * The tty preread
382 			 */
383 			preread();
384 			doagain();
385 			return;
386 		}
387 	}
388 	if (status)
389 		/* We ain't gonna loop no more, no more! */
390 		toend();
391 }
392 
393 preread()
394 {
395 
396 	whyles->w_end = -1;
397 	if (setintr)
398 		sigrelse(SIGINT);
399 	search(ZBREAK, 0);
400 	if (setintr)
401 		sighold(SIGINT);
402 	whyles->w_end = btell();
403 }
404 
405 doend()
406 {
407 
408 	if (!whyles)
409 		bferr("Not in while/foreach");
410 	whyles->w_end = btell();
411 	doagain();
412 }
413 
414 docontin()
415 {
416 
417 	if (!whyles)
418 		bferr("Not in while/foreach");
419 	doagain();
420 }
421 
422 doagain()
423 {
424 
425 	/* Repeating a while is simple */
426 	if (whyles->w_fename == 0) {
427 		bseek(whyles->w_start);
428 		return;
429 	}
430 	/*
431 	 * The foreach variable list actually has a spurious word
432 	 * ")" at the end of the w_fe list.  Thus we are at the
433 	 * of the list if one word beyond this is 0.
434 	 */
435 	if (!whyles->w_fe[1]) {
436 		dobreak();
437 		return;
438 	}
439 	set(whyles->w_fename, savestr(*whyles->w_fe++));
440 	bseek(whyles->w_start);
441 }
442 
443 dorepeat(v, kp)
444 	char **v;
445 	struct command *kp;
446 {
447 	register int i;
448 
449 	i = getn(v[1]);
450 	if (setintr)
451 		sighold(SIGINT);
452 	lshift(v, 2);
453 	while (i > 0) {
454 		if (setintr)
455 			sigrelse(SIGINT);
456 		reexecute(kp);
457 		--i;
458 	}
459 	donefds();
460 	if (setintr)
461 		sigrelse(SIGINT);
462 }
463 
464 doswbrk()
465 {
466 
467 	search(ZBRKSW, 0);
468 }
469 
470 srchx(cp)
471 	register char *cp;
472 {
473 	register struct srch *sp;
474 
475 	for (sp = srchn; sp->s_name; sp++)
476 		if (eq(cp, sp->s_name))
477 			return (sp->s_value);
478 	return (-1);
479 }
480 
481 char	Stype;
482 char	*Sgoal;
483 
484 /*VARARGS2*/
485 search(type, level, goal)
486 	int type;
487 	register int level;
488 	char *goal;
489 {
490 	char wordbuf[BUFSIZ];
491 	register char *aword = wordbuf;
492 	register char *cp;
493 
494 	Stype = type; Sgoal = goal;
495 	if (type == ZGOTO)
496 		bseek(0l);
497 	do {
498 		if (intty && fseekp == feobp)
499 			printf("? "), flush();
500 		aword[0] = 0, getword(aword);
501 		switch (srchx(aword)) {
502 
503 		case ZELSE:
504 			if (level == 0 && type == ZIF)
505 				return;
506 			break;
507 
508 		case ZIF:
509 			while (getword(aword))
510 				continue;
511 			if ((type == ZIF || type == ZELSE) && eq(aword, "then"))
512 				level++;
513 			break;
514 
515 		case ZENDIF:
516 			if (type == ZIF || type == ZELSE)
517 				level--;
518 			break;
519 
520 		case ZFOREACH:
521 		case ZWHILE:
522 			if (type == ZBREAK)
523 				level++;
524 			break;
525 
526 		case ZEND:
527 			if (type == ZBREAK)
528 				level--;
529 			break;
530 
531 		case ZSWITCH:
532 			if (type == ZSWITCH || type == ZBRKSW)
533 				level++;
534 			break;
535 
536 		case ZENDSW:
537 			if (type == ZSWITCH || type == ZBRKSW)
538 				level--;
539 			break;
540 
541 		case ZLABEL:
542 			if (type == ZGOTO && getword(aword) && eq(aword, goal))
543 				level = -1;
544 			break;
545 
546 		default:
547 			if (type != ZGOTO && (type != ZSWITCH || level != 0))
548 				break;
549 			if (lastchr(aword) != ':')
550 				break;
551 			aword[strlen(aword) - 1] = 0;
552 			if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default"))
553 				level = -1;
554 			break;
555 
556 		case ZCASE:
557 			if (type != ZSWITCH || level != 0)
558 				break;
559 			getword(aword);
560 			if (lastchr(aword) == ':')
561 				aword[strlen(aword) - 1] = 0;
562 			cp = strip(Dfix1(aword));
563 			if (Gmatch(goal, cp))
564 				level = -1;
565 			xfree(cp);
566 			break;
567 
568 		case ZDEFAULT:
569 			if (type == ZSWITCH && level == 0)
570 				level = -1;
571 			break;
572 		}
573 		getword(NOSTR);
574 	} while (level >= 0);
575 }
576 
577 getword(wp)
578 	register char *wp;
579 {
580 	register int found = 0;
581 	register int c, d;
582 
583 	c = readc(1);
584 	d = 0;
585 	do {
586 		while (c == ' ' || c == '\t')
587 			c = readc(1);
588 		if (c < 0)
589 			goto past;
590 		if (c == '\n') {
591 			if (wp)
592 				break;
593 			return (0);
594 		}
595 		unreadc(c);
596 		found = 1;
597 		do {
598 			c = readc(1);
599 			if (c == '\\' && (c = readc(1)) == '\n')
600 				c = ' ';
601 			if (any(c, "'\""))
602 				if (d == 0)
603 					d = c;
604 				else if (d == c)
605 					d = 0;
606 			if (c < 0)
607 				goto past;
608 			if (wp)
609 				*wp++ = c;
610 		} while ((d || c != ' ' && c != '\t') && c != '\n');
611 	} while (wp == 0);
612 	unreadc(c);
613 	if (found)
614 		*--wp = 0;
615 	return (found);
616 
617 past:
618 	switch (Stype) {
619 
620 	case ZIF:
621 		bferr("then/endif not found");
622 
623 	case ZELSE:
624 		bferr("endif not found");
625 
626 	case ZBRKSW:
627 	case ZSWITCH:
628 		bferr("endsw not found");
629 
630 	case ZBREAK:
631 		bferr("end not found");
632 
633 	case ZGOTO:
634 		setname(Sgoal);
635 		bferr("label not found");
636 	}
637 	/*NOTREACHED*/
638 }
639 
640 toend()
641 {
642 
643 	if (whyles->w_end == 0) {
644 		search(ZBREAK, 0);
645 		whyles->w_end = btell() - 1;
646 	} else
647 		bseek(whyles->w_end);
648 	wfree();
649 }
650 
651 wfree()
652 {
653 	long o = btell();
654 
655 	while (whyles) {
656 		register struct whyle *wp = whyles;
657 		register struct whyle *nwp = wp->w_next;
658 
659 		if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end))
660 			break;
661 		if (wp->w_fe0)
662 			blkfree(wp->w_fe0);
663 		if (wp->w_fename)
664 			xfree(wp->w_fename);
665 		xfree((char *)wp);
666 		whyles = nwp;
667 	}
668 }
669 
670 doecho(v)
671 	char **v;
672 {
673 
674 	echo(' ', v);
675 }
676 
677 doglob(v)
678 	char **v;
679 {
680 
681 	echo(0, v);
682 	flush();
683 }
684 
685 echo(sep, v)
686 	char sep;
687 	register char **v;
688 {
689 	register char *cp;
690 	int nonl = 0;
691 
692 	if (setintr)
693 		sigrelse(SIGINT);
694 	v++;
695 	if (*v == 0)
696 		return;
697 	gflag = 0; rscan(v, tglob);
698 	if (gflag) {
699 		v = glob(v);
700 		if (v == 0)
701 			bferr("No match");
702 	} else
703 		scan(v, trim);
704 	if (sep == ' ' && !strcmp(*v, "-n"))
705 		nonl++, v++;
706 	while (cp = *v++) {
707 		register int c;
708 
709 		while (c = *cp++)
710 			putchar(c | QUOTE);
711 		if (*v)
712 			putchar(sep | QUOTE);
713 	}
714 	if (sep && nonl == 0)
715 		putchar('\n');
716 	else
717 		flush();
718 	if (setintr)
719 		sighold(SIGINT);
720 	if (gargv)
721 		blkfree(gargv), gargv = 0;
722 }
723 
724 char	**environ;
725 
726 dosetenv(v)
727 	register char **v;
728 {
729 	char *lp = globone(v[2]);
730 
731 	setenv(v[1], lp);
732 	if (eq(v[1], "PATH")) {
733 		importpath(lp);
734 		dohash();
735 	}
736 	xfree(lp);
737 }
738 
739 dounsetenv(v)
740 	register char **v;
741 {
742 
743 	v++;
744 	do
745 		unsetenv(*v++);
746 	while (*v);
747 }
748 
749 setenv(name, value)
750 	char *name, *value;
751 {
752 	register char **ep = environ;
753 	register char *cp, *dp;
754 	char *blk[2], **oep = ep;
755 
756 	for (; *ep; ep++) {
757 		for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
758 			continue;
759 		if (*cp != 0 || *dp != '=')
760 			continue;
761 		cp = strspl("=", value);
762 		xfree(*ep);
763 		*ep = strspl(name, cp);
764 		xfree(cp);
765 		scan(ep, trim);
766 		return;
767 	}
768 	blk[0] = strspl(name, "="); blk[1] = 0;
769 	environ = blkspl(environ, blk);
770 	xfree((char *)oep);
771 	setenv(name, value);
772 }
773 
774 unsetenv(name)
775 	char *name;
776 {
777 	register char **ep = environ;
778 	register char *cp, *dp;
779 	char **oep = ep;
780 
781 	for (; *ep; ep++) {
782 		for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
783 			continue;
784 		if (*cp != 0 || *dp != '=')
785 			continue;
786 		cp = *ep;
787 		*ep = 0;
788 		environ = blkspl(environ, ep+1);
789 		*ep = cp;
790 		xfree(cp);
791 		xfree((char *)oep);
792 		return;
793 	}
794 }
795 
796 doumask(v)
797 	register char **v;
798 {
799 	register char *cp = v[1];
800 	register int i;
801 
802 	if (cp == 0) {
803 		i = umask(0);
804 		umask(i);
805 		printf("%o\n", i);
806 		return;
807 	}
808 	i = 0;
809 	while (digit(*cp) && *cp != '8' && *cp != '9')
810 		i = i * 8 + *cp++ - '0';
811 	if (*cp || i < 0 || i > 0777)
812 		bferr("Improper mask");
813 	umask(i);
814 }
815 
816 #include <sys/limit.h>
817 
818 struct limits {
819 	int	limconst;
820 	char	*limname;
821 	int	limdiv;
822 	char	*limscale;
823 } limits[] = {
824 	LIM_NORAISE,	"noraise",	1,	"",
825 	LIM_CPU,	"cputime",	1,	"seconds",
826 	LIM_FSIZE,	"filesize",	1024,	"kbytes",
827 	LIM_DATA,	"datasize",	1024,	"kbytes",
828 	LIM_STACK,	"stacksize",	1024,	"kbytes",
829 	LIM_CORE,	"coredumpsize",	1024,	"kbytes",
830 	-1,		0,
831 };
832 
833 struct limits *
834 findlim(cp)
835 	char *cp;
836 {
837 	register struct limits *lp, *res;
838 
839 	res = 0;
840 	for (lp = limits; lp->limconst >= 0; lp++)
841 		if (prefix(cp, lp->limname)) {
842 			if (res)
843 				bferr("Ambiguous");
844 			res = lp;
845 		}
846 	if (res)
847 		return (res);
848 	bferr("No such limit");
849 }
850 
851 dolimit(v)
852 	register char **v;
853 {
854 	register struct limits *lp;
855 	register int limit;
856 
857 	v++;
858 	if (*v == 0) {
859 		for (lp = limits+1; lp->limconst >= 0; lp++)
860 			plim(lp);
861 		if (vlimit(LIM_NORAISE, -1) && getuid())
862 			printf("Limits cannot be raised\n");
863 		return;
864 	}
865 	lp = findlim(v[0]);
866 	if (v[1] == 0) {
867 		plim(lp);
868 		return;
869 	}
870 	limit = getval(lp, v+1);
871 	setlim(lp, limit);
872 }
873 
874 getval(lp, v)
875 	register struct limits *lp;
876 	char **v;
877 {
878 	register float f;
879 	double atof();
880 	char *cp = *v++;
881 
882 	f = atof(cp);
883 	while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
884 		cp++;
885 	if (*cp == 0) {
886 		if (*v == 0)
887 			return ((int)(f+0.5) * lp->limdiv);
888 		cp = *v;
889 	}
890 	if (lp->limconst == LIM_NORAISE)
891 		goto badscal;
892 	switch (*cp) {
893 
894 	case ':':
895 		if (lp->limconst != LIM_CPU)
896 			goto badscal;
897 		return ((int)(f * 60.0 + atof(cp+1)));
898 
899 	case 'h':
900 		if (lp->limconst != LIM_CPU)
901 			goto badscal;
902 		limtail(cp, "hours");
903 		f *= 3600.;
904 		break;
905 
906 	case 'm':
907 		if (lp->limconst == LIM_CPU) {
908 			limtail(cp, "minutes");
909 			f *= 60.;
910 			break;
911 		}
912 	case 'M':
913 		if (lp->limconst == LIM_CPU)
914 			goto badscal;
915 		*cp = 'm';
916 		limtail(cp, "megabytes");
917 		f *= 1024.*1024.;
918 		break;
919 
920 	case 's':
921 		if (lp->limconst != LIM_CPU)
922 			goto badscal;
923 		limtail(cp, "seconds");
924 		break;
925 
926 	case 'k':
927 		if (lp->limconst == LIM_CPU)
928 			goto badscal;
929 		limtail(cp, "kbytes");
930 		f *= 1024;
931 		break;
932 
933 	case 'u':
934 		limtail(cp, "unlimited");
935 		return (INFINITY);
936 
937 	default:
938 badscal:
939 		bferr("Improper or unknown scale factor");
940 	}
941 	return ((int)(f+0.5));
942 }
943 
944 limtail(cp, str0)
945 	char *cp, *str0;
946 {
947 	register char *str = str0;
948 
949 	while (*cp && *cp == *str)
950 		cp++, str++;
951 	if (*cp)
952 		error("Bad scaling; did you mean ``%s''?", str0);
953 }
954 
955 plim(lp)
956 	register struct limits *lp;
957 {
958 	register int lim;
959 
960 	printf("%s \t", lp->limname);
961 	lim = vlimit(lp->limconst, -1);
962 	if (lim == INFINITY)
963 		printf("unlimited");
964 	else if (lp->limconst == LIM_CPU)
965 		psecs((long)lim);
966 	else
967 		printf("%d %s", lim / lp->limdiv, lp->limscale);
968 	printf("\n");
969 }
970 
971 dounlimit(v)
972 	register char **v;
973 {
974 	register struct limits *lp;
975 
976 	v++;
977 	if (*v == 0) {
978 		for (lp = limits+1; lp->limconst >= 0; lp++)
979 			setlim(lp, INFINITY);
980 		return;
981 	}
982 	while (*v) {
983 		lp = findlim(*v++);
984 		setlim(lp, INFINITY);
985 	}
986 }
987 
988 setlim(lp, limit)
989 	register struct limits *lp;
990 {
991 
992 	if (vlimit(lp->limconst, limit) < 0)
993 		Perror(bname);
994 }
995 
996 dosuspend()
997 {
998 	int old, ldisc;
999 	short ctpgrp;
1000 
1001 	if (loginsh)
1002 		error("Can't suspend a login shell (yet)");
1003 	untty();
1004 	old = sigsys(SIGTSTP, SIG_DFL);
1005 	kill(0, SIGTSTP);
1006 	/* the shell stops here */
1007 	sigsys(SIGTSTP, old);
1008 	if (tpgrp != -1) {
1009 retry:
1010 		ioctl(FSHTTY, TIOCGPGRP, &ctpgrp);
1011 		if (ctpgrp != opgrp) {
1012 			old = sigsys(SIGTTIN, SIG_DFL);
1013 			kill(0, SIGTTIN);
1014 			sigsys(SIGTTIN, old);
1015 			goto retry;
1016 		}
1017 		ioctl(FSHTTY, TIOCSPGRP, &shpgrp);
1018 		setpgrp(0, shpgrp);
1019 	}
1020 	ioctl(FSHTTY, TIOCGETD, &oldisc);
1021 	if (oldisc != NTTYDISC) {
1022 		printf("Switching to new tty driver...\n");
1023 		ldisc = NTTYDISC;
1024 		ioctl(FSHTTY, TIOCSETD, &ldisc);
1025 	}
1026 }
1027 
1028 doeval(v)
1029 	char **v;
1030 {
1031 	char **oevalvec = evalvec;
1032 	char *oevalp = evalp;
1033 	jmp_buf osetexit;
1034 	int reenter;
1035 	char **gv = 0;
1036 
1037 	v++;
1038 	if (*v == 0)
1039 		return;
1040 	gflag = 0; rscan(v, tglob);
1041 	if (gflag) {
1042 		gv = v = glob(v);
1043 		gargv = 0;
1044 		if (v == 0)
1045 			error("No match");
1046 		v = copyblk(v);
1047 	} else
1048 		scan(v, trim);
1049 	getexit(osetexit);
1050 	reenter = 0;
1051 	setexit();
1052 	reenter++;
1053 	if (reenter == 1) {
1054 		evalvec = v;
1055 		evalp = 0;
1056 		process(0);
1057 	}
1058 	evalvec = oevalvec;
1059 	evalp = oevalp;
1060 	doneinp = 0;
1061 	if (gv)
1062 		blkfree(gv);
1063 	resexit(osetexit);
1064 	if (reenter >= 2)
1065 		error(NOSTR);
1066 }
1067