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