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