1 /* $NetBSD: func.c,v 1.40 2013/07/16 17:47:43 christos 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.40 2013/07/16 17:47:43 christos Exp $");
42 #include <sys/types.h>
55 #include "pathnames.h"
57 extern char **environ
;
58 extern int progprintf(int, char **);
60 static void islogin(void);
61 static void reexecute(struct command
*);
62 static void preread(void);
63 static void doagain(void);
64 static void search(int, int, Char
*);
65 static int getword(Char
*);
66 static int keyword(Char
*);
67 static void toend(void);
68 static void xecho(int, Char
**);
69 static void Unsetenv(Char
*);
70 static void wpfree(struct whyle
*);
73 isbfunc(struct command
*t
)
75 static struct biltins label
= {"", dozip
, 0, 0};
76 static struct biltins foregnd
= {"%job", dofg1
, 0, 0};
77 static struct biltins backgnd
= {"%job &", dobg1
, 0, 0};
78 struct biltins
*bp
, *bp1
, *bp2
;
83 if (lastchr(cp
) == ':') {
84 label
.bname
= short2str(cp
);
88 if (t
->t_dflg
& F_AMPERSAND
) {
89 t
->t_dflg
&= ~F_AMPERSAND
;
90 backgnd
.bname
= short2str(cp
);
93 foregnd
.bname
= short2str(cp
);
97 * Binary search Bp1 is the beginning of the current search range. Bp2 is
100 for (bp1
= bfunc
, bp2
= bfunc
+ nbfunc
; bp1
< bp2
;) {
103 bp
= bp1
+ ((bp2
- bp1
) >> 1);
104 if ((i
= *cp
- *bp
->bname
) == 0 &&
105 (i
= Strcmp(cp
, str2short(bp
->bname
))) == 0)
116 func(struct command
*t
, struct biltins
*bp
)
122 i
= blklen(t
->t_dcom
) - 1;
124 stderror(ERR_NAME
| ERR_TOOFEW
);
126 stderror(ERR_NAME
| ERR_TOOMANY
);
127 (*bp
->bfunct
) (t
->t_dcom
, t
);
132 doonintr(Char
**v
, struct command
*t
)
138 if (parintr
== SIG_IGN
)
140 if (setintr
&& intty
)
141 stderror(ERR_NAME
| ERR_TERMINAL
);
147 sigemptyset(&nsigset
);
148 (void)sigaddset(&nsigset
, SIGINT
);
149 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
151 (void)signal(SIGINT
, SIG_DFL
);
154 else if (eq((vv
= strip(vv
)), STRminus
)) {
155 (void)signal(SIGINT
, SIG_IGN
);
156 gointr
= Strsave(STRminus
);
159 gointr
= Strsave(vv
);
160 (void)signal(SIGINT
, pintr
);
166 donohup(Char
**v
, struct command
*t
)
169 stderror(ERR_NAME
| ERR_TERMINAL
);
171 (void) signal(SIGHUP
, SIG_IGN
);
177 dozip(Char
**v
, struct command
*t
)
190 doalias(Char
**v
, struct command
*t
)
200 vp
= adrof1(strip(p
), &aliases
);
202 blkpr(cshout
, vp
->vec
);
203 (void) fputc('\n', cshout
);
207 if (eq(p
, STRalias
) || eq(p
, STRunalias
)) {
209 stderror(ERR_NAME
| ERR_DANGER
);
211 set1(strip(p
), saveblk(v
), &aliases
);
217 unalias(Char
**v
, struct command
*t
)
224 dologout(Char
**v
, struct command
*t
)
232 dologin(Char
**v
, struct command
*t
)
236 (void)signal(SIGTERM
, parterm
);
237 (void)execl(_PATH_LOGIN
, "login", short2str(v
[1]), NULL
);
246 if (chkstop
== 0 && setintr
)
250 stderror(ERR_NOTLOGIN
);
255 doif(Char
**v
, struct command
*kp
)
264 stderror(ERR_NAME
| ERR_EMPTYIF
);
265 if (eq(*vv
, STRthen
)) {
267 stderror(ERR_NAME
| ERR_IMPRTHEN
);
268 setname(vis_str(STRthen
));
270 * If expression was zero, then scan to else, otherwise just fall into
274 search(T_IF
, 0, NULL
);
278 * Simple command attached to this if. Left shift the node in this tree,
279 * munging it so we can reexecute it.
282 lshift(kp
->t_dcom
, (size_t)(vv
- kp
->t_dcom
));
289 * Reexecute a command, being careful not
290 * to redo i/o redirection, which is already set up.
293 reexecute(struct command
*kp
)
295 kp
->t_dflg
&= F_SAVE
;
296 kp
->t_dflg
|= F_REPEAT
;
298 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
299 * pgrp's as the jobs would then have no way to get the tty (we can't give
300 * it to them, and our parent wouldn't know their pgrp, etc.
302 execute(kp
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
);
307 doelse(Char
**v
, struct command
*t
)
309 search(T_ELSE
, 0, NULL
);
314 dogoto(Char
**v
, struct command
*t
)
318 gotolab(lp
= globone(v
[1], G_ERROR
));
327 * While we still can, locate any unknown ends of existing loops. This
328 * obscure code is the WORST result of the fact that we don't really parse.
330 for (wp
= whyles
; wp
; wp
= wp
->w_next
)
331 if (wp
->w_end
.type
== F_SEEK
&& wp
->w_end
.f_seek
== 0) {
332 search(T_BREAK
, 0, NULL
);
337 search(T_GOTO
, 0, lab
);
339 * Eliminate loops which were exited.
346 doswitch(Char
**v
, struct command
*t
)
351 if (!*v
|| *(*v
++) != '(')
352 stderror(ERR_SYNTAX
);
353 cp
= **v
== ')' ? STRNULL
: *v
++;
357 stderror(ERR_SYNTAX
);
358 search(T_SWITCH
, 0, lp
= globone(cp
, G_ERROR
));
364 dobreak(Char
**v
, struct command
*t
)
369 stderror(ERR_NAME
| ERR_NOTWHILE
);
374 doexit(Char
**v
, struct command
*t
)
376 if (chkstop
== 0 && (intty
|| intact
) && evalvec
== 0)
379 * Don't DEMAND parentheses here either.
383 set(STRstatus
, putn(expr(&v
)));
385 stderror(ERR_NAME
| ERR_EXPRESSION
);
394 doforeach(Char
**v
, struct command
*t
)
402 stderror(ERR_NAME
| ERR_VARBEGIN
);
403 while (*cp
&& alnum(*cp
))
406 stderror(ERR_NAME
| ERR_VARALNUM
);
407 if ((cp
- sp
) > MAXVARLEN
)
408 stderror(ERR_NAME
| ERR_VARTOOLONG
);
410 if (v
[0][0] != '(' || v
[blklen(v
) - 1][0] != ')')
411 stderror(ERR_NAME
| ERR_NOPAREN
);
416 stderror(ERR_NAME
| ERR_NOMATCH
);
417 nwp
= (struct whyle
*) xcalloc(1, sizeof *nwp
);
418 nwp
->w_fe
= nwp
->w_fe0
= v
;
420 btell(&nwp
->w_start
);
421 nwp
->w_fename
= Strsave(cp
);
422 nwp
->w_next
= whyles
;
423 nwp
->w_end
.type
= F_SEEK
;
426 * Pre-read the loop so as to be more comprehensible to a terminal user.
435 dowhile(Char
**v
, struct command
*t
)
440 again
= whyles
!= 0 && SEEKEQ(&whyles
->w_start
, &lineloc
) &&
441 whyles
->w_fename
== 0;
444 * Implement prereading here also, taking care not to evaluate the
445 * expression before the loop has been read up from a terminal.
448 status
= !exp0(&v
, 1);
452 stderror(ERR_NAME
| ERR_EXPRESSION
);
455 (struct whyle
*)xcalloc(1, sizeof(*nwp
));
457 nwp
->w_start
= lineloc
;
458 nwp
->w_end
.type
= F_SEEK
;
459 nwp
->w_end
.f_seek
= 0;
460 nwp
->w_next
= whyles
;
472 /* We ain't gonna loop no more, no more! */
481 whyles
->w_end
.type
= I_SEEK
;
483 sigemptyset(&nsigset
);
484 (void) sigaddset(&nsigset
, SIGINT
);
485 (void) sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
488 search(T_BREAK
, 0, NULL
); /* read the expression in */
490 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
491 btell(&whyles
->w_end
);
496 doend(Char
**v
, struct command
*t
)
499 stderror(ERR_NAME
| ERR_NOTWHILE
);
500 btell(&whyles
->w_end
);
506 docontin(Char
**v
, struct command
*t
)
509 stderror(ERR_NAME
| ERR_NOTWHILE
);
516 /* Repeating a while is simple */
517 if (whyles
->w_fename
== 0) {
518 bseek(&whyles
->w_start
);
522 * The foreach variable list actually has a spurious word ")" at the end of
523 * the w_fe list. Thus we are at the of the list if one word beyond this
526 if (!whyles
->w_fe
[1]) {
530 set(whyles
->w_fename
, Strsave(*whyles
->w_fe
++));
531 bseek(&whyles
->w_start
);
535 dorepeat(Char
**v
, struct command
*kp
)
542 sigemptyset(&nsigset
);
543 (void)sigaddset(&nsigset
, SIGINT
);
544 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
549 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
555 (void) sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
560 doswbrk(Char
**v
, struct command
*t
)
562 search(T_BRKSW
, 0, NULL
);
568 struct srch
*sp
, *sp1
, *sp2
;
572 * Binary search Sp1 is the beginning of the current search range. Sp2 is
575 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
576 sp
= sp1
+ ((sp2
- sp1
) >> 1);
577 if ((i
= *cp
- *sp
->s_name
) == 0 &&
578 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
593 search(int type
, int level
, Char
*goal
)
595 Char wordbuf
[BUFSIZE
];
603 if (type
== T_GOTO
) {
610 if (intty
&& fseekp
== feobp
&& aret
== F_SEEK
)
611 (void)fprintf(cshout
, "? "), (void)fflush(cshout
);
613 (void)getword(aword
);
614 switch (srchx(aword
)) {
616 if (type
!= T_SWITCH
|| level
!= 0)
618 (void) getword(aword
);
619 if (lastchr(aword
) == ':')
620 aword
[Strlen(aword
) - 1] = 0;
621 cp
= strip(Dfix1(aword
));
622 if (Gmatch(goal
, cp
))
627 if (type
== T_SWITCH
&& level
== 0)
631 if (level
== 0 && type
== T_IF
)
635 if (type
== T_BRKSW
) {
649 if (type
== T_IF
|| type
== T_ELSE
)
653 if (type
== T_SWITCH
|| type
== T_BRKSW
)
657 while (getword(aword
))
659 if ((type
== T_IF
|| type
== T_ELSE
) &&
664 if (type
== T_GOTO
&& getword(aword
) && eq(aword
, goal
))
668 if (type
== T_SWITCH
|| type
== T_BRKSW
)
678 if (type
!= T_GOTO
&& (type
!= T_SWITCH
|| level
!= 0))
680 if (lastchr(aword
) != ':')
682 aword
[Strlen(aword
) - 1] = 0;
683 if ((type
== T_GOTO
&& eq(aword
, goal
)) ||
684 (type
== T_SWITCH
&& eq(aword
, STRdefault
)))
688 (void) getword(NULL
);
689 } while (level
>= 0);
693 wpfree(struct whyle
*wp
)
698 xfree((ptr_t
) wp
->w_fename
);
705 int c
, d
, found
, kwd
;
714 while (c
== ' ' || c
== '\t')
719 while (c
>= 0 && c
!= '\n');
731 if (c
== '\\' && (c
= readc(1)) == '\n')
733 if (c
== '\'' || c
== '"') {
743 *wp
= 0; /* end the string b4 test */
745 } while ((d
|| (!(kwd
= keyword(owp
)) && c
!= ' '
746 && c
!= '\t')) && c
!= '\n');
750 * if we have read a keyword ( "if", "switch" or "while" ) then we do not
751 * need to unreadc the look-ahead char
764 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
767 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
770 setname(vis_str(Sgoal
));
771 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
774 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
778 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
785 * keyword(wp) determines if wp is one of the built-n functions if,
786 * switch or while. It seems that when an if statement looks like
787 * "if(" then getword above sucks in the '(' and so the search routine
788 * never finds what it is scanning for. Rather than rewrite doword, I hack
789 * in a test to see if the string forms a keyword. Then doword stops
790 * and returns the word "if" -strike
796 static Char STRswitch
[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
797 static Char STRwhile
[] = {'w', 'h', 'i', 'l', 'e', '\0'};
798 static Char STRif
[] = {'i', 'f', '\0'};
803 if ((Strcmp(wp
, STRif
) == 0) || (Strcmp(wp
, STRwhile
) == 0)
804 || (Strcmp(wp
, STRswitch
) == 0))
813 if (whyles
->w_end
.type
== F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
814 search(T_BREAK
, 0, NULL
);
815 btell(&whyles
->w_end
);
816 whyles
->w_end
.f_seek
--;
819 bseek(&whyles
->w_end
);
831 for (; whyles
; whyles
= nwp
) {
832 struct whyle
*wp
= whyles
;
836 * We free loops that have different seek types.
838 if (wp
->w_end
.type
!= I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
839 wp
->w_start
.type
== o
.type
) {
840 if (wp
->w_end
.type
== F_SEEK
) {
841 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
842 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
846 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
847 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
858 doecho(Char
**v
, struct command
*t
)
865 doglob(Char
**v
, struct command
*t
)
868 (void)fflush(cshout
);
872 xecho(int sep
, Char
**v
)
880 sigemptyset(&nsigset
);
881 (void)sigaddset(&nsigset
, SIGINT
);
882 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
891 stderror(ERR_NAME
| ERR_NOMATCH
);
894 v
= gargv
= saveblk(v
);
897 if (sep
== ' ' && *v
&& eq(*v
, STRmn
))
899 while ((cp
= *v
++) != NULL
) {
902 while ((c
= *cp
++) != '\0')
903 (void)vis_fputc(c
| QUOTE
, cshout
);
906 (void)vis_fputc(sep
| QUOTE
, cshout
);
909 if (sep
&& nonl
== 0)
910 (void)fputc('\n', cshout
);
912 (void)fflush(cshout
);
914 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
916 blkfree(gargv
), gargv
= 0;
921 dosetenv(Char
**v
, struct command
*t
)
927 if ((vp
= *v
++) == 0) {
931 sigemptyset(&nsigset
);
932 (void)sigaddset(&nsigset
, SIGINT
);
933 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
935 for (ep
= STR_environ
; *ep
; ep
++)
936 (void)fprintf(cshout
, "%s\n", vis_str(*ep
));
939 if ((lp
= *v
++) == 0)
941 Setenv(vp
, lp
= globone(lp
, G_APPEND
));
942 if (eq(vp
, STRPATH
)) {
946 else if (eq(vp
, STRLANG
) || eq(vp
, STRLC_CTYPE
)) {
950 (void)setlocale(LC_ALL
, "");
951 for (k
= 0200; k
<= 0377 && !Isprint(k
); k
++)
953 AsciiOnly
= k
> 0377;
963 dounsetenv(Char
**v
, struct command
*t
)
965 static Char
*name
= NULL
;
972 * Find the longest environment variable
974 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
975 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
981 name
= xmalloc((size_t)(maxi
+ 1) * sizeof(Char
));
984 for (maxi
= 1; maxi
;)
985 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
986 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
989 if (!Gmatch(name
, *v
))
992 if (eq(name
, STRLANG
) || eq(name
, STRLC_CTYPE
)) {
996 (void) setlocale(LC_ALL
, "");
997 for (k
= 0200; k
<= 0377 && !Isprint(k
); k
++)
999 AsciiOnly
= k
> 0377;
1001 AsciiOnly
= getenv("LANG") == NULL
&&
1002 getenv("LC_CTYPE") == NULL
;
1006 * Delete name, and start again cause the environment changes
1011 xfree((ptr_t
) name
);
1016 Setenv(Char
*name
, Char
*val
)
1018 Char
*blk
[2], *cp
, *dp
, **ep
, **oep
;
1024 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1026 if (*cp
!= 0 || *dp
!= '=')
1028 cp
= Strspl(STRequal
, val
);
1030 *ep
= strip(Strspl(name
, cp
));
1032 blkfree((Char
**)environ
);
1033 environ
= short2blk(STR_environ
);
1036 cp
= Strspl(name
, STRequal
);
1037 blk
[0] = strip(Strspl(cp
, val
));
1040 STR_environ
= blkspl(STR_environ
, blk
);
1041 blkfree((Char
**)environ
);
1042 environ
= short2blk(STR_environ
);
1047 Unsetenv(Char
*name
)
1049 Char
*cp
, *dp
, **ep
, **oep
;
1055 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1057 if (*cp
!= 0 || *dp
!= '=')
1061 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1062 environ
= short2blk(STR_environ
);
1072 doumask(Char
**v
, struct command
*t
)
1081 (void)fprintf(cshout
, "%o\n", i
);
1085 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1086 i
= i
* 8 + (mode_t
)(*cp
++ - '0');
1087 if (*cp
|| i
> 0777)
1088 stderror(ERR_NAME
| ERR_MASK
);
1092 typedef rlim_t RLIM_TYPE
;
1094 static const struct limits
{
1096 const char *limname
;
1098 const char *limscale
;
1100 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1101 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1102 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1103 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1104 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1105 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1106 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1107 { RLIMIT_NPROC
, "maxproc", 1, "" },
1108 { RLIMIT_NTHR
, "maxthread", 1, "" },
1109 { RLIMIT_NOFILE
, "openfiles", 1, "" },
1110 { RLIMIT_SBSIZE
, "sbsize", 1, "bytes" },
1111 { RLIMIT_AS
, "vmemoryuse", 1024, "kbytes" },
1112 { -1, NULL
, 0, NULL
}
1115 static const struct limits
*findlim(Char
*);
1116 static RLIM_TYPE
getval(const struct limits
*, Char
**);
1117 static void limtail(Char
*, const char *);
1118 static void plim(const struct limits
*, Char
);
1119 static int setlim(const struct limits
*, Char
, RLIM_TYPE
);
1121 static const struct limits
*
1124 const struct limits
*lp
, *res
;
1127 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1128 if (prefix(cp
, str2short(lp
->limname
))) {
1130 stderror(ERR_NAME
| ERR_AMBIG
);
1135 stderror(ERR_NAME
| ERR_LIMIT
);
1141 dolimit(Char
**v
, struct command
*t
)
1143 const struct limits
*lp
;
1149 if (*v
&& eq(*v
, STRmh
)) {
1154 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1163 limit
= getval(lp
, v
+ 1);
1164 if (setlim(lp
, hard
, limit
) < 0)
1165 stderror(ERR_SILENT
);
1169 getval(const struct limits
*lp
, Char
**v
)
1175 d
= atof(short2str(cp
));
1177 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
1181 return ((RLIM_TYPE
)((d
+ 0.5) * lp
->limdiv
));
1186 if (lp
->limconst
!= RLIMIT_CPU
)
1188 return ((RLIM_TYPE
)(d
* 60.0 + atof(short2str(cp
+ 1))));
1190 if (lp
->limconst
== RLIMIT_CPU
)
1193 limtail(cp
, "megabytes");
1194 d
*= 1024.0 * 1024.0;
1197 if (lp
->limconst
!= RLIMIT_CPU
)
1199 limtail(cp
, "hours");
1203 if (lp
->limconst
== RLIMIT_CPU
)
1205 limtail(cp
, "kbytes");
1209 if (lp
->limconst
== RLIMIT_CPU
) {
1210 limtail(cp
, "minutes");
1215 limtail(cp
, "megabytes");
1216 d
*= 1024.0 * 1024.0;
1219 if (lp
->limconst
!= RLIMIT_CPU
)
1221 limtail(cp
, "seconds");
1224 limtail(cp
, "unlimited");
1225 return (RLIM_INFINITY
);
1228 stderror(ERR_NAME
| ERR_SCALEF
);
1232 if (d
> (double) RLIM_INFINITY
)
1233 return RLIM_INFINITY
;
1235 return ((RLIM_TYPE
)d
);
1239 limtail(Char
*cp
, const char *str
)
1241 while (*cp
&& *cp
== *str
)
1244 stderror(ERR_BADSCALE
, str
);
1250 plim(const struct limits
*lp
, Char hard
)
1255 (void)fprintf(cshout
, "%-13.13s", lp
->limname
);
1257 (void)getrlimit(lp
->limconst
, &rlim
);
1258 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
1260 if (limit
== RLIM_INFINITY
)
1261 (void)fprintf(cshout
, "unlimited");
1262 else if (lp
->limconst
== RLIMIT_CPU
)
1263 psecs((long) limit
);
1265 (void)fprintf(cshout
, "%jd %s",
1266 (intmax_t) (limit
/ (RLIM_TYPE
)lp
->limdiv
), lp
->limscale
);
1267 (void)fputc('\n', cshout
);
1272 dounlimit(Char
**v
, struct command
*t
)
1274 const struct limits
*lp
;
1281 if (*v
&& eq(*v
, STRmh
)) {
1286 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1287 if (setlim(lp
, hard
, (RLIM_TYPE
)RLIM_INFINITY
) < 0)
1290 stderror(ERR_SILENT
);
1295 if (setlim(lp
, hard
, (RLIM_TYPE
)RLIM_INFINITY
) < 0)
1296 stderror(ERR_SILENT
);
1301 setlim(const struct limits
*lp
, Char hard
, RLIM_TYPE limit
)
1305 (void)getrlimit(lp
->limconst
, &rlim
);
1308 rlim
.rlim_max
= limit
;
1309 else if (limit
== RLIM_INFINITY
&& geteuid() != 0)
1310 rlim
.rlim_cur
= rlim
.rlim_max
;
1312 rlim
.rlim_cur
= limit
;
1314 if (rlim
.rlim_max
< rlim
.rlim_cur
)
1315 rlim
.rlim_max
= rlim
.rlim_cur
;
1317 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
1318 (void)fprintf(csherr
, "%s: %s: Can't %s%s limit (%s)\n", bname
,
1319 lp
->limname
, limit
== RLIM_INFINITY
? "remove" : "set",
1320 hard
? " hard" : "", strerror(errno
));
1328 dosuspend(Char
**v
, struct command
*t
)
1334 stderror(ERR_SUSPLOG
);
1337 old
= signal(SIGTSTP
, SIG_DFL
);
1338 (void)kill(0, SIGTSTP
);
1339 /* the shell stops here */
1340 (void)signal(SIGTSTP
, old
);
1344 ctpgrp
= tcgetpgrp(FSHTTY
);
1345 if (ctpgrp
!= opgrp
) {
1346 old
= signal(SIGTTIN
, SIG_DFL
);
1347 (void)kill(0, SIGTTIN
);
1348 (void)signal(SIGTTIN
, old
);
1351 (void)setpgid(0, shpgrp
);
1352 (void)tcsetpgrp(FSHTTY
, shpgrp
);
1356 /* This is the dreaded EVAL built-in.
1357 * If you don't fiddle with file descriptors, and reset didfds,
1358 * this command will either ignore redirection inside or outside
1359 * its arguments, e.g. eval "date >x" vs. eval "date" >x
1360 * The stuff here seems to work, but I did it by trial and error rather
1361 * than really knowing what was going on. If tpgrp is zero, we are
1362 * probably a background eval, e.g. "eval date &", and we want to
1363 * make sure that any processes we start stay in our pgrp.
1364 * This is also the case for "time eval date" -- stay in same pgrp.
1365 * Otherwise, under stty tostop, processes will stop in the wrong
1366 * pgrp, with no way for the shell to get them going again. -IAN!
1368 static Char
**gv
= NULL
;
1372 doeval(Char
**v
, struct command
*t
)
1375 Char
*oevalp
, **oevalvec
, **savegv
;
1376 int my_reenter
, odidfds
, oSHERR
, oSHIN
, oSHOUT
, saveERR
, saveIN
, saveOUT
;
1391 gflag
= 0, tglob(v
);
1393 gv
= v
= globall(v
);
1396 stderror(ERR_NOMATCH
);
1405 saveIN
= dcopy(SHIN
, -1);
1406 saveOUT
= dcopy(SHOUT
, -1);
1407 saveERR
= dcopy(SHERR
, -1);
1411 if ((my_reenter
= setexit()) == 0) {
1414 SHIN
= dcopy(0, -1);
1415 SHOUT
= dcopy(1, -1);
1416 SHERR
= dcopy(2, -1);
1431 SHIN
= dmove(saveIN
, oSHIN
);
1432 SHOUT
= dmove(saveOUT
, oSHOUT
);
1433 SHERR
= dmove(saveERR
, oSHERR
);
1435 blkfree(gv
), gv
= NULL
;
1439 stderror(ERR_SILENT
);
1444 doprintf(Char
**v
, struct command
*t
)
1449 ret
= progprintf(blklen(v
), c
= short2blk(v
));
1450 (void)fflush(cshout
);
1451 (void)fflush(csherr
);
1453 blkfree((Char
**) c
);
1455 stderror(ERR_SILENT
);