1 /* $NetBSD: func.c,v 1.36 2007/09/15 14:33:05 ragge Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)func.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: func.c,v 1.36 2007/09/15 14:33:05 ragge Exp $");
42 #include <sys/types.h>
54 #include "pathnames.h"
56 extern char **environ
;
57 extern int progprintf(int, char **);
59 static void islogin(void);
60 static void reexecute(struct command
*);
61 static void preread(void);
62 static void doagain(void);
63 static void search(int, int, Char
*);
64 static int getword(Char
*);
65 static int keyword(Char
*);
66 static void toend(void);
67 static void xecho(int, Char
**);
68 static void Unsetenv(Char
*);
69 static void wpfree(struct whyle
*);
72 isbfunc(struct command
*t
)
74 static struct biltins label
= {"", dozip
, 0, 0};
75 static struct biltins foregnd
= {"%job", dofg1
, 0, 0};
76 static struct biltins backgnd
= {"%job &", dobg1
, 0, 0};
77 struct biltins
*bp
, *bp1
, *bp2
;
82 if (lastchr(cp
) == ':') {
83 label
.bname
= short2str(cp
);
87 if (t
->t_dflg
& F_AMPERSAND
) {
88 t
->t_dflg
&= ~F_AMPERSAND
;
89 backgnd
.bname
= short2str(cp
);
92 foregnd
.bname
= short2str(cp
);
96 * Binary search Bp1 is the beginning of the current search range. Bp2 is
99 for (bp1
= bfunc
, bp2
= bfunc
+ nbfunc
; bp1
< bp2
;) {
102 bp
= bp1
+ ((bp2
- bp1
) >> 1);
103 if ((i
= *cp
- *bp
->bname
) == 0 &&
104 (i
= Strcmp(cp
, str2short(bp
->bname
))) == 0)
115 func(struct command
*t
, struct biltins
*bp
)
121 i
= blklen(t
->t_dcom
) - 1;
123 stderror(ERR_NAME
| ERR_TOOFEW
);
125 stderror(ERR_NAME
| ERR_TOOMANY
);
126 (*bp
->bfunct
) (t
->t_dcom
, t
);
131 doonintr(Char
**v
, struct command
*t
)
137 if (parintr
== SIG_IGN
)
139 if (setintr
&& intty
)
140 stderror(ERR_NAME
| ERR_TERMINAL
);
146 sigemptyset(&nsigset
);
147 (void)sigaddset(&nsigset
, SIGINT
);
148 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
150 (void)signal(SIGINT
, SIG_DFL
);
153 else if (eq((vv
= strip(vv
)), STRminus
)) {
154 (void)signal(SIGINT
, SIG_IGN
);
155 gointr
= Strsave(STRminus
);
158 gointr
= Strsave(vv
);
159 (void)signal(SIGINT
, pintr
);
165 donohup(Char
**v
, struct command
*t
)
168 stderror(ERR_NAME
| ERR_TERMINAL
);
170 (void) signal(SIGHUP
, SIG_IGN
);
176 dozip(Char
**v
, struct command
*t
)
189 doalias(Char
**v
, struct command
*t
)
199 vp
= adrof1(strip(p
), &aliases
);
201 blkpr(cshout
, vp
->vec
);
202 (void) fputc('\n', cshout
);
206 if (eq(p
, STRalias
) || eq(p
, STRunalias
)) {
208 stderror(ERR_NAME
| ERR_DANGER
);
210 set1(strip(p
), saveblk(v
), &aliases
);
216 unalias(Char
**v
, struct command
*t
)
223 dologout(Char
**v
, struct command
*t
)
231 dologin(Char
**v
, struct command
*t
)
235 (void)signal(SIGTERM
, parterm
);
236 (void)execl(_PATH_LOGIN
, "login", short2str(v
[1]), NULL
);
245 if (chkstop
== 0 && setintr
)
249 stderror(ERR_NOTLOGIN
);
254 doif(Char
**v
, struct command
*kp
)
263 stderror(ERR_NAME
| ERR_EMPTYIF
);
264 if (eq(*vv
, STRthen
)) {
266 stderror(ERR_NAME
| ERR_IMPRTHEN
);
267 setname(vis_str(STRthen
));
269 * If expression was zero, then scan to else, otherwise just fall into
273 search(T_IF
, 0, NULL
);
277 * Simple command attached to this if. Left shift the node in this tree,
278 * munging it so we can reexecute it.
281 lshift(kp
->t_dcom
, vv
- kp
->t_dcom
);
288 * Reexecute a command, being careful not
289 * to redo i/o redirection, which is already set up.
292 reexecute(struct command
*kp
)
294 kp
->t_dflg
&= F_SAVE
;
295 kp
->t_dflg
|= F_REPEAT
;
297 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
298 * pgrp's as the jobs would then have no way to get the tty (we can't give
299 * it to them, and our parent wouldn't know their pgrp, etc.
301 execute(kp
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
);
306 doelse(Char
**v
, struct command
*t
)
308 search(T_ELSE
, 0, NULL
);
313 dogoto(Char
**v
, struct command
*t
)
317 gotolab(lp
= globone(v
[1], G_ERROR
));
326 * While we still can, locate any unknown ends of existing loops. This
327 * obscure code is the WORST result of the fact that we don't really parse.
329 for (wp
= whyles
; wp
; wp
= wp
->w_next
)
330 if (wp
->w_end
.type
== F_SEEK
&& wp
->w_end
.f_seek
== 0) {
331 search(T_BREAK
, 0, NULL
);
336 search(T_GOTO
, 0, lab
);
338 * Eliminate loops which were exited.
345 doswitch(Char
**v
, struct command
*t
)
350 if (!*v
|| *(*v
++) != '(')
351 stderror(ERR_SYNTAX
);
352 cp
= **v
== ')' ? STRNULL
: *v
++;
356 stderror(ERR_SYNTAX
);
357 search(T_SWITCH
, 0, lp
= globone(cp
, G_ERROR
));
363 dobreak(Char
**v
, struct command
*t
)
368 stderror(ERR_NAME
| ERR_NOTWHILE
);
373 doexit(Char
**v
, struct command
*t
)
375 if (chkstop
== 0 && (intty
|| intact
) && evalvec
== 0)
378 * Don't DEMAND parentheses here either.
382 set(STRstatus
, putn(expr(&v
)));
384 stderror(ERR_NAME
| ERR_EXPRESSION
);
393 doforeach(Char
**v
, struct command
*t
)
401 stderror(ERR_NAME
| ERR_VARBEGIN
);
402 while (*cp
&& alnum(*cp
))
405 stderror(ERR_NAME
| ERR_VARALNUM
);
406 if ((cp
- sp
) > MAXVARLEN
)
407 stderror(ERR_NAME
| ERR_VARTOOLONG
);
409 if (v
[0][0] != '(' || v
[blklen(v
) - 1][0] != ')')
410 stderror(ERR_NAME
| ERR_NOPAREN
);
415 stderror(ERR_NAME
| ERR_NOMATCH
);
416 nwp
= (struct whyle
*) xcalloc(1, sizeof *nwp
);
417 nwp
->w_fe
= nwp
->w_fe0
= v
;
419 btell(&nwp
->w_start
);
420 nwp
->w_fename
= Strsave(cp
);
421 nwp
->w_next
= whyles
;
422 nwp
->w_end
.type
= F_SEEK
;
425 * Pre-read the loop so as to be more comprehensible to a terminal user.
434 dowhile(Char
**v
, struct command
*t
)
439 again
= whyles
!= 0 && SEEKEQ(&whyles
->w_start
, &lineloc
) &&
440 whyles
->w_fename
== 0;
443 * Implement prereading here also, taking care not to evaluate the
444 * expression before the loop has been read up from a terminal.
447 status
= !exp0(&v
, 1);
451 stderror(ERR_NAME
| ERR_EXPRESSION
);
454 (struct whyle
*)xcalloc(1, sizeof(*nwp
));
456 nwp
->w_start
= lineloc
;
457 nwp
->w_end
.type
= F_SEEK
;
458 nwp
->w_end
.f_seek
= 0;
459 nwp
->w_next
= whyles
;
471 /* We ain't gonna loop no more, no more! */
480 whyles
->w_end
.type
= I_SEEK
;
482 sigemptyset(&nsigset
);
483 (void) sigaddset(&nsigset
, SIGINT
);
484 (void) sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
487 search(T_BREAK
, 0, NULL
); /* read the expression in */
489 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
490 btell(&whyles
->w_end
);
495 doend(Char
**v
, struct command
*t
)
498 stderror(ERR_NAME
| ERR_NOTWHILE
);
499 btell(&whyles
->w_end
);
505 docontin(Char
**v
, struct command
*t
)
508 stderror(ERR_NAME
| ERR_NOTWHILE
);
515 /* Repeating a while is simple */
516 if (whyles
->w_fename
== 0) {
517 bseek(&whyles
->w_start
);
521 * The foreach variable list actually has a spurious word ")" at the end of
522 * the w_fe list. Thus we are at the of the list if one word beyond this
525 if (!whyles
->w_fe
[1]) {
529 set(whyles
->w_fename
, Strsave(*whyles
->w_fe
++));
530 bseek(&whyles
->w_start
);
534 dorepeat(Char
**v
, struct command
*kp
)
541 sigemptyset(&nsigset
);
542 (void)sigaddset(&nsigset
, SIGINT
);
543 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
548 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
554 (void) sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
559 doswbrk(Char
**v
, struct command
*t
)
561 search(T_BRKSW
, 0, NULL
);
567 struct srch
*sp
, *sp1
, *sp2
;
571 * Binary search Sp1 is the beginning of the current search range. Sp2 is
574 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
575 sp
= sp1
+ ((sp2
- sp1
) >> 1);
576 if ((i
= *cp
- *sp
->s_name
) == 0 &&
577 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
592 search(int type
, int level
, Char
*goal
)
594 Char wordbuf
[BUFSIZE
];
602 if (type
== T_GOTO
) {
609 if (intty
&& fseekp
== feobp
&& aret
== F_SEEK
)
610 (void)fprintf(cshout
, "? "), (void)fflush(cshout
);
612 (void)getword(aword
);
613 switch (srchx(aword
)) {
615 if (type
!= T_SWITCH
|| level
!= 0)
617 (void) getword(aword
);
618 if (lastchr(aword
) == ':')
619 aword
[Strlen(aword
) - 1] = 0;
620 cp
= strip(Dfix1(aword
));
621 if (Gmatch(goal
, cp
))
626 if (type
== T_SWITCH
&& level
== 0)
630 if (level
== 0 && type
== T_IF
)
634 if (type
== T_BRKSW
) {
648 if (type
== T_IF
|| type
== T_ELSE
)
652 if (type
== T_SWITCH
|| type
== T_BRKSW
)
656 while (getword(aword
))
658 if ((type
== T_IF
|| type
== T_ELSE
) &&
663 if (type
== T_GOTO
&& getword(aword
) && eq(aword
, goal
))
667 if (type
== T_SWITCH
|| type
== T_BRKSW
)
677 if (type
!= T_GOTO
&& (type
!= T_SWITCH
|| level
!= 0))
679 if (lastchr(aword
) != ':')
681 aword
[Strlen(aword
) - 1] = 0;
682 if ((type
== T_GOTO
&& eq(aword
, goal
)) ||
683 (type
== T_SWITCH
&& eq(aword
, STRdefault
)))
687 (void) getword(NULL
);
688 } while (level
>= 0);
692 wpfree(struct whyle
*wp
)
697 xfree((ptr_t
) wp
->w_fename
);
704 int c
, d
, found
, kwd
;
713 while (c
== ' ' || c
== '\t')
718 while (c
>= 0 && c
!= '\n');
730 if (c
== '\\' && (c
= readc(1)) == '\n')
732 if (c
== '\'' || c
== '"') {
742 *wp
= 0; /* end the string b4 test */
744 } while ((d
|| (!(kwd
= keyword(owp
)) && c
!= ' '
745 && c
!= '\t')) && c
!= '\n');
749 * if we have read a keyword ( "if", "switch" or "while" ) then we do not
750 * need to unreadc the look-ahead char
763 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
766 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
769 setname(vis_str(Sgoal
));
770 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
773 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
777 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
784 * keyword(wp) determines if wp is one of the built-n functions if,
785 * switch or while. It seems that when an if statement looks like
786 * "if(" then getword above sucks in the '(' and so the search routine
787 * never finds what it is scanning for. Rather than rewrite doword, I hack
788 * in a test to see if the string forms a keyword. Then doword stops
789 * and returns the word "if" -strike
795 static Char STRswitch
[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
796 static Char STRwhile
[] = {'w', 'h', 'i', 'l', 'e', '\0'};
797 static Char STRif
[] = {'i', 'f', '\0'};
802 if ((Strcmp(wp
, STRif
) == 0) || (Strcmp(wp
, STRwhile
) == 0)
803 || (Strcmp(wp
, STRswitch
) == 0))
812 if (whyles
->w_end
.type
== F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
813 search(T_BREAK
, 0, NULL
);
814 btell(&whyles
->w_end
);
815 whyles
->w_end
.f_seek
--;
818 bseek(&whyles
->w_end
);
830 for (; whyles
; whyles
= nwp
) {
831 struct whyle
*wp
= whyles
;
835 * We free loops that have different seek types.
837 if (wp
->w_end
.type
!= I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
838 wp
->w_start
.type
== o
.type
) {
839 if (wp
->w_end
.type
== F_SEEK
) {
840 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
841 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
845 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
846 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
857 doecho(Char
**v
, struct command
*t
)
864 doglob(Char
**v
, struct command
*t
)
867 (void)fflush(cshout
);
871 xecho(int sep
, Char
**v
)
879 sigemptyset(&nsigset
);
880 (void)sigaddset(&nsigset
, SIGINT
);
881 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
890 stderror(ERR_NAME
| ERR_NOMATCH
);
893 v
= gargv
= saveblk(v
);
896 if (sep
== ' ' && *v
&& eq(*v
, STRmn
))
898 while ((cp
= *v
++) != NULL
) {
901 while ((c
= *cp
++) != '\0')
902 (void)vis_fputc(c
| QUOTE
, cshout
);
905 (void)vis_fputc(sep
| QUOTE
, cshout
);
908 if (sep
&& nonl
== 0)
909 (void)fputc('\n', cshout
);
911 (void)fflush(cshout
);
913 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
915 blkfree(gargv
), gargv
= 0;
920 dosetenv(Char
**v
, struct command
*t
)
926 if ((vp
= *v
++) == 0) {
930 sigemptyset(&nsigset
);
931 (void)sigaddset(&nsigset
, SIGINT
);
932 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
934 for (ep
= STR_environ
; *ep
; ep
++)
935 (void)fprintf(cshout
, "%s\n", vis_str(*ep
));
938 if ((lp
= *v
++) == 0)
940 Setenv(vp
, lp
= globone(lp
, G_APPEND
));
941 if (eq(vp
, STRPATH
)) {
945 else if (eq(vp
, STRLANG
) || eq(vp
, STRLC_CTYPE
)) {
949 (void)setlocale(LC_ALL
, "");
950 for (k
= 0200; k
<= 0377 && !Isprint(k
); k
++)
952 AsciiOnly
= k
> 0377;
962 dounsetenv(Char
**v
, struct command
*t
)
964 static Char
*name
= NULL
;
971 * Find the longest environment variable
973 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
974 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
980 name
= (Char
*)xmalloc((size_t) (maxi
+ 1) * sizeof(Char
));
983 for (maxi
= 1; maxi
;)
984 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
985 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
988 if (!Gmatch(name
, *v
))
991 if (eq(name
, STRLANG
) || eq(name
, STRLC_CTYPE
)) {
995 (void) setlocale(LC_ALL
, "");
996 for (k
= 0200; k
<= 0377 && !Isprint(k
); k
++)
998 AsciiOnly
= k
> 0377;
1000 AsciiOnly
= getenv("LANG") == NULL
&&
1001 getenv("LC_CTYPE") == NULL
;
1005 * Delete name, and start again cause the environment changes
1010 xfree((ptr_t
) name
);
1015 Setenv(Char
*name
, Char
*val
)
1017 Char
*blk
[2], *cp
, *dp
, **ep
, **oep
;
1023 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1025 if (*cp
!= 0 || *dp
!= '=')
1027 cp
= Strspl(STRequal
, val
);
1029 *ep
= strip(Strspl(name
, cp
));
1031 blkfree((Char
**)environ
);
1032 environ
= short2blk(STR_environ
);
1035 cp
= Strspl(name
, STRequal
);
1036 blk
[0] = strip(Strspl(cp
, val
));
1039 STR_environ
= blkspl(STR_environ
, blk
);
1040 blkfree((Char
**)environ
);
1041 environ
= short2blk(STR_environ
);
1046 Unsetenv(Char
*name
)
1048 Char
*cp
, *dp
, **ep
, **oep
;
1054 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1056 if (*cp
!= 0 || *dp
!= '=')
1060 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1061 environ
= short2blk(STR_environ
);
1071 doumask(Char
**v
, struct command
*t
)
1080 (void)fprintf(cshout
, "%o\n", i
);
1084 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1085 i
= i
* 8 + *cp
++ - '0';
1086 if (*cp
|| i
< 0 || i
> 0777)
1087 stderror(ERR_NAME
| ERR_MASK
);
1091 typedef rlim_t RLIM_TYPE
;
1093 static const struct limits
{
1095 const char *limname
;
1097 const char *limscale
;
1099 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1100 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1101 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1102 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1103 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1104 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1105 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1106 { RLIMIT_NPROC
, "maxproc", 1, "" },
1107 { RLIMIT_NOFILE
, "openfiles", 1, "" },
1108 { RLIMIT_SBSIZE
, "sbsize", 1, "bytes" },
1109 { RLIMIT_AS
, "vmemoryuse", 1024, "kbytes" },
1110 { -1, NULL
, 0, NULL
}
1113 static const struct limits
*findlim(Char
*);
1114 static RLIM_TYPE
getval(const struct limits
*, Char
**);
1115 static void limtail(Char
*, const char *);
1116 static void plim(const struct limits
*, Char
);
1117 static int setlim(const struct limits
*, Char
, RLIM_TYPE
);
1119 static const struct limits
*
1122 const struct limits
*lp
, *res
;
1124 res
= (struct limits
*) NULL
;
1125 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1126 if (prefix(cp
, str2short(lp
->limname
))) {
1128 stderror(ERR_NAME
| ERR_AMBIG
);
1133 stderror(ERR_NAME
| ERR_LIMIT
);
1139 dolimit(Char
**v
, struct command
*t
)
1141 const struct limits
*lp
;
1147 if (*v
&& eq(*v
, STRmh
)) {
1152 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1161 limit
= getval(lp
, v
+ 1);
1162 if (setlim(lp
, hard
, limit
) < 0)
1163 stderror(ERR_SILENT
);
1167 getval(const struct limits
*lp
, Char
**v
)
1173 f
= atof(short2str(cp
));
1175 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
1179 return ((RLIM_TYPE
)((f
+ 0.5) * lp
->limdiv
));
1184 if (lp
->limconst
!= RLIMIT_CPU
)
1186 return ((RLIM_TYPE
)(f
* 60.0 + atof(short2str(cp
+ 1))));
1188 if (lp
->limconst
== RLIMIT_CPU
)
1191 limtail(cp
, "megabytes");
1192 f
*= 1024.0 * 1024.0;
1195 if (lp
->limconst
!= RLIMIT_CPU
)
1197 limtail(cp
, "hours");
1201 if (lp
->limconst
== RLIMIT_CPU
)
1203 limtail(cp
, "kbytes");
1207 if (lp
->limconst
== RLIMIT_CPU
) {
1208 limtail(cp
, "minutes");
1213 limtail(cp
, "megabytes");
1214 f
*= 1024.0 * 1024.0;
1217 if (lp
->limconst
!= RLIMIT_CPU
)
1219 limtail(cp
, "seconds");
1222 limtail(cp
, "unlimited");
1223 return (RLIM_INFINITY
);
1226 stderror(ERR_NAME
| ERR_SCALEF
);
1230 if (f
> (float) RLIM_INFINITY
)
1231 return RLIM_INFINITY
;
1233 return ((RLIM_TYPE
)f
);
1237 limtail(Char
*cp
, const char *str
)
1239 while (*cp
&& *cp
== *str
)
1242 stderror(ERR_BADSCALE
, str
);
1248 plim(const struct limits
*lp
, Char hard
)
1253 (void)fprintf(cshout
, "%-13.13s", lp
->limname
);
1255 (void)getrlimit(lp
->limconst
, &rlim
);
1256 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
1258 if (limit
== RLIM_INFINITY
)
1259 (void)fprintf(cshout
, "unlimited");
1260 else if (lp
->limconst
== RLIMIT_CPU
)
1261 psecs((long) limit
);
1263 (void)fprintf(cshout
, "%ld %s", (long) (limit
/ lp
->limdiv
),
1265 (void)fputc('\n', cshout
);
1270 dounlimit(Char
**v
, struct command
*t
)
1272 const struct limits
*lp
;
1279 if (*v
&& eq(*v
, STRmh
)) {
1284 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1285 if (setlim(lp
, hard
, (RLIM_TYPE
)RLIM_INFINITY
) < 0)
1288 stderror(ERR_SILENT
);
1293 if (setlim(lp
, hard
, (RLIM_TYPE
)RLIM_INFINITY
) < 0)
1294 stderror(ERR_SILENT
);
1299 setlim(const struct limits
*lp
, Char hard
, RLIM_TYPE limit
)
1303 (void)getrlimit(lp
->limconst
, &rlim
);
1306 rlim
.rlim_max
= limit
;
1307 else if (limit
== RLIM_INFINITY
&& geteuid() != 0)
1308 rlim
.rlim_cur
= rlim
.rlim_max
;
1310 rlim
.rlim_cur
= limit
;
1312 if (rlim
.rlim_max
< rlim
.rlim_cur
)
1313 rlim
.rlim_max
= rlim
.rlim_cur
;
1315 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
1316 (void)fprintf(csherr
, "%s: %s: Can't %s%s limit (%s)\n", bname
,
1317 lp
->limname
, limit
== RLIM_INFINITY
? "remove" : "set",
1318 hard
? " hard" : "", strerror(errno
));
1326 dosuspend(Char
**v
, struct command
*t
)
1332 stderror(ERR_SUSPLOG
);
1335 old
= signal(SIGTSTP
, SIG_DFL
);
1336 (void)kill(0, SIGTSTP
);
1337 /* the shell stops here */
1338 (void)signal(SIGTSTP
, old
);
1342 ctpgrp
= tcgetpgrp(FSHTTY
);
1343 if (ctpgrp
!= opgrp
) {
1344 old
= signal(SIGTTIN
, SIG_DFL
);
1345 (void)kill(0, SIGTTIN
);
1346 (void)signal(SIGTTIN
, old
);
1349 (void)setpgid(0, shpgrp
);
1350 (void)tcsetpgrp(FSHTTY
, shpgrp
);
1354 /* This is the dreaded EVAL built-in.
1355 * If you don't fiddle with file descriptors, and reset didfds,
1356 * this command will either ignore redirection inside or outside
1357 * its arguments, e.g. eval "date >x" vs. eval "date" >x
1358 * The stuff here seems to work, but I did it by trial and error rather
1359 * than really knowing what was going on. If tpgrp is zero, we are
1360 * probably a background eval, e.g. "eval date &", and we want to
1361 * make sure that any processes we start stay in our pgrp.
1362 * This is also the case for "time eval date" -- stay in same pgrp.
1363 * Otherwise, under stty tostop, processes will stop in the wrong
1364 * pgrp, with no way for the shell to get them going again. -IAN!
1366 static Char
**gv
= NULL
;
1370 doeval(Char
**v
, struct command
*t
)
1373 Char
*oevalp
, **oevalvec
, **savegv
;
1374 int my_reenter
, odidfds
, oSHERR
, oSHIN
, oSHOUT
, saveERR
, saveIN
, saveOUT
;
1389 gflag
= 0, tglob(v
);
1391 gv
= v
= globall(v
);
1394 stderror(ERR_NOMATCH
);
1403 saveIN
= dcopy(SHIN
, -1);
1404 saveOUT
= dcopy(SHOUT
, -1);
1405 saveERR
= dcopy(SHERR
, -1);
1409 if ((my_reenter
= setexit()) == 0) {
1412 SHIN
= dcopy(0, -1);
1413 SHOUT
= dcopy(1, -1);
1414 SHERR
= dcopy(2, -1);
1429 SHIN
= dmove(saveIN
, oSHIN
);
1430 SHOUT
= dmove(saveOUT
, oSHOUT
);
1431 SHERR
= dmove(saveERR
, oSHERR
);
1433 blkfree(gv
), gv
= NULL
;
1437 stderror(ERR_SILENT
);
1442 doprintf(Char
**v
, struct command
*t
)
1447 ret
= progprintf(blklen(v
), c
= short2blk(v
));
1448 (void)fflush(cshout
);
1449 (void)fflush(csherr
);
1451 blkfree((Char
**) c
);
1453 stderror(ERR_SILENT
);