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