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