1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.162 2011/02/26 00:07:06 christos Exp $ */
3 * sh.func.c: csh builtin functions
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 RCSID("$tcsh: sh.func.c,v 3.162 2011/02/26 00:07:06 christos Exp $")
42 #endif /* WINNT_NATIVE */
44 #if defined (NLS_CATALOGS) && defined(HAVE_ICONV)
45 static iconv_t catgets_iconv
; /* Or (iconv_t)-1 */
52 extern int MapsAreInited
;
53 extern int NLSMapsAreInited
;
54 extern int GotTermCaps
;
56 static int zlast
= -1;
58 static void islogin (void);
59 static void preread (void);
60 static void doagain (void);
61 static const char *isrchx (int);
62 static void search (int, int, Char
*);
63 static int getword (struct Strbuf
*);
64 static struct wordent
*histgetword (struct wordent
*);
65 static void toend (void);
66 static void xecho (int, Char
**);
67 static int islocale_var (Char
*);
68 static void wpfree (struct whyle
*);
70 const struct biltins
*
71 isbfunc(struct command
*t
)
73 Char
*cp
= t
->t_dcom
[0];
74 const struct biltins
*bp
, *bp1
, *bp2
;
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};
80 * We never match a builtin that has quoted the first
81 * character; this has been the traditional way to escape
87 if (*cp
!= ':' && lastchr(cp
) == ':') {
88 label
.bname
= short2str(cp
);
92 if (t
->t_dflg
& F_AMPERSAND
) {
93 t
->t_dflg
&= ~F_AMPERSAND
;
94 backgnd
.bname
= short2str(cp
);
97 foregnd
.bname
= short2str(cp
);
102 * This is a perhaps kludgy way to determine if the warp builtin is to be
103 * acknowledged or not. If checkwarp() fails, then we are to assume that
104 * the warp command is invalid, and carry on as we would handle any other
105 * non-builtin command. -- JDK 2/4/88
107 if (eq(STRwarp
, cp
) && !checkwarp()) {
108 return (0); /* this builtin disabled */
112 * Binary search Bp1 is the beginning of the current search range. Bp2 is
115 for (bp1
= bfunc
, bp2
= bfunc
+ nbfunc
; bp1
< bp2
;) {
118 bp
= bp1
+ ((bp2
- bp1
) >> 1);
119 if ((i
= ((char) *cp
) - *bp
->bname
) == 0 &&
120 (i
= StrQcmp(cp
, str2short(bp
->bname
))) == 0)
128 return nt_check_additional_builtins(cp
);
129 #endif /*WINNT_NATIVE*/
134 func(struct command
*t
, const struct biltins
*bp
)
140 i
= blklen(t
->t_dcom
) - 1;
142 stderror(ERR_NAME
| ERR_TOOFEW
);
144 stderror(ERR_NAME
| ERR_TOOMANY
);
145 (*bp
->bfunct
) (t
->t_dcom
, t
);
150 doonintr(Char
**v
, struct command
*c
)
156 if (parintr
.sa_handler
== SIG_IGN
)
158 if (setintr
&& intty
)
159 stderror(ERR_NAME
| ERR_TERMINAL
);
165 sigset_interrupting(SIGINT
, queue_pintr
);
167 (void) signal(SIGINT
, SIG_DFL
);
170 else if (eq((vv
= strip(vv
)), STRminus
)) {
171 (void) signal(SIGINT
, SIG_IGN
);
172 gointr
= Strsave(STRminus
);
175 gointr
= Strsave(vv
);
176 sigset_interrupting(SIGINT
, queue_pintr
);
182 donohup(Char
**v
, struct command
*c
)
187 stderror(ERR_NAME
| ERR_TERMINAL
);
189 (void) signal(SIGHUP
, SIG_IGN
);
199 dohup(Char
**v
, struct command
*c
)
204 stderror(ERR_NAME
| ERR_TERMINAL
);
206 (void) signal(SIGHUP
, SIG_DFL
);
212 dozip(Char
**v
, struct command
*c
)
220 dofiletest(Char
**v
, struct command
*c
)
222 Char
**globbed
, **fileptr
, *ftest
, *res
;
225 if (*(ftest
= *++v
) != '-')
226 stderror(ERR_NAME
| ERR_FILEINQ
);
229 v
= glob_all_or_error(v
);
231 cleanup_push(globbed
, blk_cleanup
);
233 while (*(fileptr
= v
++) != '\0') {
234 res
= filetest(ftest
, &fileptr
, 0);
235 cleanup_push(res
, xfree
);
243 cleanup_until(globbed
);
249 plist(&shvhed
, VAR_ALL
);
254 doalias(Char
**v
, struct command
*c
)
263 plist(&aliases
, VAR_ALL
);
265 vp
= adrof1(strip(p
), &aliases
);
267 blkpr(vp
->vec
), xputchar('\n');
270 if (eq(p
, STRalias
) || eq(p
, STRunalias
)) {
271 setname(short2str(p
));
272 stderror(ERR_NAME
| ERR_DANGER
);
274 set1(strip(p
), saveblk(v
), &aliases
, VAR_READWRITE
);
281 unalias(Char
**v
, struct command
*c
)
290 dologout(Char
**v
, struct command
*c
)
300 dologin(Char
**v
, struct command
*c
)
305 #else /* !WINNT_NATIVE */
306 char **p
= short2blk(v
);
309 cleanup_push((Char
**)p
, blk_cleanup
);
311 rechist(NULL
, adrof(STRsavehist
) != NULL
);
312 sigaction(SIGTERM
, &parterm
, NULL
);
313 (void) execv(_PATH_BIN_LOGIN
, p
);
314 (void) execv(_PATH_USRBIN_LOGIN
, p
);
315 cleanup_until((Char
**)p
);
318 #endif /* !WINNT_NATIVE */
325 donewgrp(Char
**v
, struct command
*c
)
328 if (chkstop
== 0 && setintr
)
330 sigaction(SIGTERM
, &parterm
, NULL
);
333 * From Beto Appleton (beto@aixwiz.austin.ibm.com)
334 * Newgrp can take 2 arguments...
336 (void) execv(_PATH_BIN_NEWGRP
, p
);
337 (void) execv(_PATH_USRBIN_NEWGRP
, p
);
338 blkfree((Char
**) p
);
347 if (chkstop
== 0 && setintr
)
351 stderror(ERR_NOTLOGIN
);
355 doif(Char
**v
, struct command
*kp
)
361 i
= noexec
? 1 : expr(&v
);
364 stderror(ERR_NAME
| ERR_EMPTYIF
);
365 if (eq(*vv
, STRthen
)) {
367 stderror(ERR_NAME
| ERR_IMPRTHEN
);
368 setname(short2str(STRthen
));
370 * If expression was zero, then scan to else , otherwise just fall into
374 search(TC_IF
, 0, NULL
);
378 * Simple command attached to this if. Left shift the node in this tree,
379 * munging it so we can reexecute it.
382 lshift(kp
->t_dcom
, vv
- kp
->t_dcom
);
389 * Reexecute a command, being careful not
390 * to redo i/o redirection, which is already set up.
393 reexecute(struct command
*kp
)
395 kp
->t_dflg
&= F_SAVE
;
396 kp
->t_dflg
|= F_REPEAT
;
398 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
399 * pgrp's as the jobs would then have no way to get the tty (we can't give
400 * it to them, and our parent wouldn't know their pgrp, etc.
402 execute(kp
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
, TRUE
);
407 doelse (Char
**v
, struct command
*c
)
412 search(TC_ELSE
, 0, NULL
);
417 dogoto(Char
**v
, struct command
*c
)
422 lp
= globone(v
[1], G_ERROR
);
423 cleanup_push(lp
, xfree
);
434 * While we still can, locate any unknown ends of existing loops. This
435 * obscure code is the WORST result of the fact that we don't really parse.
438 for (wp
= whyles
; wp
; wp
= wp
->w_next
)
439 if (wp
->w_end
.type
== TCSH_F_SEEK
&& wp
->w_end
.f_seek
== 0) {
440 search(TC_BREAK
, 0, NULL
);
446 search(TC_GOTO
, 0, lab
);
448 * Eliminate loops which were exited.
455 doswitch(Char
**v
, struct command
*c
)
461 if (!*v
|| *(*v
++) != '(')
462 stderror(ERR_SYNTAX
);
463 cp
= **v
== ')' ? STRNULL
: *v
++;
467 stderror(ERR_SYNTAX
);
468 lp
= globone(cp
, G_ERROR
);
469 cleanup_push(lp
, xfree
);
471 search(TC_SWITCH
, 0, lp
);
477 dobreak(Char
**v
, struct command
*c
)
482 stderror(ERR_NAME
| ERR_NOTWHILE
);
489 doexit(Char
**v
, struct command
*c
)
493 if (chkstop
== 0 && (intty
|| intact
) && evalvec
== 0)
496 * Don't DEMAND parentheses here either.
500 setv(STRstatus
, putn(expr(&v
)), VAR_READWRITE
);
502 stderror(ERR_NAME
| ERR_EXPRESSION
);
508 /* Always close, why only on ttys? */
514 doforeach(Char
**v
, struct command
*c
)
524 stderror(ERR_NAME
| ERR_VARBEGIN
);
527 } while (alnum(*cp
));
529 stderror(ERR_NAME
| ERR_VARALNUM
);
531 if (v
[0][0] != '(' || v
[blklen(v
) - 1][0] != ')')
532 stderror(ERR_NAME
| ERR_NOPAREN
);
536 v
= globall(v
, gflag
);
537 if (v
== 0 && !noexec
)
538 stderror(ERR_NAME
| ERR_NOMATCH
);
544 nwp
= xcalloc(1, sizeof *nwp
);
545 nwp
->w_fe
= nwp
->w_fe0
= v
;
546 btell(&nwp
->w_start
);
547 nwp
->w_fename
= Strsave(cp
);
548 nwp
->w_next
= whyles
;
549 nwp
->w_end
.type
= TCSH_F_SEEK
;
552 * Pre-read the loop so as to be more comprehensible to a terminal user.
563 dowhile(Char
**v
, struct command
*c
)
566 int again
= whyles
!= 0 &&
567 SEEKEQ(&whyles
->w_start
, &lineloc
) &&
568 whyles
->w_fename
== 0;
573 * Implement prereading here also, taking care not to evaluate the
574 * expression before the loop has been read up from a terminal.
578 else if (intty
&& !again
)
579 status
= !exp0(&v
, 1);
583 stderror(ERR_NAME
| ERR_EXPRESSION
);
585 struct whyle
*nwp
= xcalloc(1, sizeof(*nwp
));
587 nwp
->w_start
= lineloc
;
588 nwp
->w_end
.type
= TCSH_F_SEEK
;
589 nwp
->w_end
.f_seek
= 0;
590 nwp
->w_end
.a_seek
= 0;
591 nwp
->w_next
= whyles
;
604 /* We ain't gonna loop no more, no more! */
611 int old_pintr_disabled
;
613 whyles
->w_end
.type
= TCSH_I_SEEK
;
615 pintr_push_enable(&old_pintr_disabled
);
616 search(TC_BREAK
, 0, NULL
); /* read the expression in */
618 cleanup_until(&old_pintr_disabled
);
619 btell(&whyles
->w_end
);
624 doend(Char
**v
, struct command
*c
)
629 stderror(ERR_NAME
| ERR_NOTWHILE
);
630 btell(&whyles
->w_end
);
637 docontin(Char
**v
, struct command
*c
)
642 stderror(ERR_NAME
| ERR_NOTWHILE
);
650 /* Repeating a while is simple */
651 if (whyles
->w_fename
== 0) {
652 bseek(&whyles
->w_start
);
656 * The foreach variable list actually has a spurious word ")" at the end of
657 * the w_fe list. Thus we are at the of the list if one word beyond this
660 if (!whyles
->w_fe
[1]) {
664 setv(whyles
->w_fename
, quote(Strsave(*whyles
->w_fe
++)), VAR_READWRITE
);
665 bseek(&whyles
->w_start
);
669 dorepeat(Char
**v
, struct command
*kp
)
676 } while (v
[0] != NULL
&& Strcmp(v
[0], STRrepeat
) == 0);
682 cleanup_push(&pintr_disabled
, disabled_cleanup
);
685 if (setintr
&& pintr_disabled
== 1) {
686 cleanup_until(&pintr_disabled
);
688 cleanup_push(&pintr_disabled
, disabled_cleanup
);
693 if (setintr
&& pintr_disabled
== 1)
694 cleanup_until(&pintr_disabled
);
700 doswbrk(Char
**v
, struct command
*c
)
705 search(TC_BRKSW
, 0, NULL
);
711 struct srch
*sp
, *sp1
, *sp2
;
715 * Ignore keywords inside heredocs
721 * Binary search Sp1 is the beginning of the current search range. Sp2 is
724 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
725 sp
= sp1
+ ((sp2
- sp1
) >> 1);
726 if ((i
= *cp
- *sp
->s_name
) == 0 &&
727 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
740 struct srch
*sp
, *sp2
;
742 for (sp
= srchn
, sp2
= srchn
+ nsrchn
; sp
< sp2
; sp
++)
743 if (sp
->s_value
== n
)
753 search(int type
, int level
, Char
*goal
)
755 struct Strbuf word
= Strbuf_INIT
;
759 struct wordent
*histent
= NULL
, *ohistent
= NULL
;
763 if (type
== TC_GOTO
) {
765 a
.type
= TCSH_F_SEEK
;
770 cleanup_push(&word
, Strbuf_cleanup
);
774 histent
= xmalloc(sizeof(*histent
));
775 ohistent
= xmalloc(sizeof(*histent
));
776 ohistent
->word
= STRNULL
;
777 ohistent
->next
= histent
;
778 histent
->prev
= ohistent
;
781 if (intty
&& fseekp
== feobp
&& aret
== TCSH_F_SEEK
)
782 printprompt(1, isrchx(type
== TC_BREAK
? zlast
: type
));
783 /* xprintf("? "), flush(); */
784 (void) getword(&word
);
785 Strbuf_terminate(&word
);
787 if (intty
&& Strlen(word
.s
) > 0) {
788 histent
->word
= Strsave(word
.s
);
789 histent
->next
= xmalloc(sizeof(*histent
));
790 histent
->next
->prev
= histent
;
791 histent
= histent
->next
;
794 switch (srchx(word
.s
)) {
797 if (level
== 0 && type
== TC_IF
)
802 while (getword(&word
))
804 if ((type
== TC_IF
|| type
== TC_ELSE
) &&
810 if (type
== TC_IF
|| type
== TC_ELSE
)
817 if (type
== TC_BREAK
)
822 if (type
== TC_BRKSW
) {
831 if (type
== TC_BREAK
)
837 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
842 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
847 if (type
== TC_GOTO
&& getword(&word
) && eq(word
.s
, goal
))
852 if (type
!= TC_GOTO
&& (type
!= TC_SWITCH
|| level
!= 0))
854 if (word
.len
== 0 || word
.s
[word
.len
- 1] != ':')
856 word
.s
[--word
.len
] = 0;
857 if ((type
== TC_GOTO
&& eq(word
.s
, goal
)) ||
858 (type
== TC_SWITCH
&& eq(word
.s
, STRdefault
)))
863 if (type
!= TC_SWITCH
|| level
!= 0)
865 (void) getword(&word
);
866 if (word
.len
!= 0 && word
.s
[word
.len
- 1] == ':')
867 word
.s
[--word
.len
] = 0;
868 cp
= strip(Dfix1(word
.s
));
869 cleanup_push(cp
, xfree
);
870 if (Gmatch(goal
, cp
))
876 if (type
== TC_SWITCH
&& level
== 0)
881 ohistent
->prev
= histgetword(histent
);
882 ohistent
->prev
->next
= ohistent
;
883 savehist(ohistent
, 0);
887 (void) getword(NULL
);
888 } while (level
>= 0);
890 cleanup_until(&word
);
893 static struct wordent
*
894 histgetword(struct wordent
*histent
)
896 int found
= 0, first
;
900 tmp
= xmalloc(sizeof(*tmp
));
908 Strbuf_terminate (tmp
);
909 while (c
== ' ' || c
== '\t')
914 while (c
!= CHAR_ERR
&& c
!= '\n');
925 if (c
== '\\' && !e
) {
926 if ((c
= readc(1)) == '\n') {
934 if ((c
== '\'' || c
== '"') && !e
) {
943 Strbuf_append1(tmp
, (Char
) c
);
945 if (!first
&& !d
&& c
== '(' && !e
) {
949 } while (d
|| e
|| (c
!= ' ' && c
!= '\t' && c
!= '\n'));
952 Strbuf_terminate(tmp
);
953 histent
->word
= Strsave(tmp
->s
);
954 histent
->next
= xmalloc(sizeof (*histent
));
955 histent
->next
->prev
= histent
;
956 histent
= histent
->next
;
961 Strbuf_append1(tmp
, (Char
) c
);
962 Strbuf_terminate(tmp
);
963 histent
->word
= Strsave(tmp
->s
);
972 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
976 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
981 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
985 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
989 setname(short2str(Sgoal
));
990 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1001 getword(struct Strbuf
*wp
)
1003 int found
= 0, first
;
1011 while (c
== ' ' || c
== '\t')
1016 while (c
!= CHAR_ERR
&& c
!= '\n');
1029 if (c
== '\\' && (c
= readc(1)) == '\n')
1031 if (c
== '\'' || c
== '"') {
1040 Strbuf_append1(wp
, (Char
) c
);
1041 if (!first
&& !d
&& c
== '(') {
1048 } while ((d
|| (c
!= ' ' && c
!= '\t')) && c
!= '\n');
1055 Strbuf_terminate(wp
);
1064 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
1068 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
1073 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
1077 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
1081 setname(short2str(Sgoal
));
1082 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1095 if (whyles
->w_end
.type
== TCSH_F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
1096 search(TC_BREAK
, 0, NULL
);
1097 btell(&whyles
->w_end
);
1098 whyles
->w_end
.f_seek
--;
1101 bseek(&whyles
->w_end
);
1107 wpfree(struct whyle
*wp
)
1111 xfree(wp
->w_fename
);
1121 nwp
= NULL
; /* sun lint is dumb! */
1125 static const char foo
[] = "IAFE";
1131 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
1132 foo
[o
.type
+ 1], o
.a_seek
, o
.f_seek
);
1135 for (; whyles
; whyles
= nwp
) {
1136 struct whyle
*wp
= whyles
;
1140 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1141 foo
[wp
->w_start
.type
+1],
1142 wp
->w_start
.a_seek
, wp
->w_start
.f_seek
);
1143 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1144 foo
[wp
->w_end
.type
+ 1], wp
->w_end
.a_seek
, wp
->w_end
.f_seek
);
1148 * XXX: We free loops that have different seek types.
1150 if (wp
->w_end
.type
!= TCSH_I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
1151 wp
->w_start
.type
== o
.type
) {
1152 if (wp
->w_end
.type
== TCSH_F_SEEK
) {
1153 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
1154 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
1158 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
1159 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
1170 doecho(Char
**v
, struct command
*c
)
1178 doglob(Char
**v
, struct command
*c
)
1186 xecho(int sep
, Char
**v
)
1188 Char
*cp
, **globbed
= NULL
;
1190 int echo_style
= ECHO_STYLE
;
1193 if ((vp
= adrof(STRecho_style
)) != NULL
&& vp
->vec
!= NULL
&&
1194 vp
->vec
[0] != NULL
) {
1195 if (Strcmp(vp
->vec
[0], STRbsd
) == 0)
1196 echo_style
= BSD_ECHO
;
1197 else if (Strcmp(vp
->vec
[0], STRsysv
) == 0)
1198 echo_style
= SYSV_ECHO
;
1199 else if (Strcmp(vp
->vec
[0], STRboth
) == 0)
1200 echo_style
= BOTH_ECHO
;
1201 else if (Strcmp(vp
->vec
[0], STRnone
) == 0)
1202 echo_style
= NONE_ECHO
;
1209 int old_pintr_disabled
;
1210 pintr_push_enable(&old_pintr_disabled
);
1211 v
= glob_all_or_error(v
);
1212 cleanup_until(&old_pintr_disabled
);
1214 v
= glob_all_or_error(v
);
1217 if (globbed
!= NULL
)
1218 cleanup_push(globbed
, blk_cleanup
);
1220 if ((echo_style
& BSD_ECHO
) != 0 && sep
== ' ' && *v
&& eq(*v
, STRmn
))
1223 while ((cp
= *v
++) != 0) {
1227 int old_pintr_disabled
;
1229 pintr_push_enable(&old_pintr_disabled
);
1230 cleanup_until(&old_pintr_disabled
);
1232 while ((c
= *cp
++) != 0) {
1233 if ((echo_style
& SYSV_ECHO
) != 0 && c
== '\\') {
1234 switch (c
= *cp
++) {
1245 #if 0 /* Windows does not understand \e */
1248 c
= CTL_ESC('\033');
1271 if (*cp
>= '0' && *cp
< '8')
1272 c
= c
* 8 + *cp
++ - '0';
1273 if (*cp
>= '0' && *cp
< '8')
1274 c
= c
* 8 + *cp
++ - '0';
1275 if (*cp
>= '0' && *cp
< '8')
1276 c
= c
* 8 + *cp
++ - '0';
1283 xputchar('\\' | QUOTE
);
1287 xputwchar(c
| QUOTE
);
1291 xputchar(sep
| QUOTE
);
1294 if (sep
&& nonl
== 0)
1298 if (globbed
!= NULL
)
1299 cleanup_until(globbed
);
1302 /* check whether an environment variable should invoke 'set_locale()' */
1304 islocale_var(Char
*var
)
1306 static Char
*locale_vars
[] = {
1307 STRLANG
, STRLC_ALL
, STRLC_CTYPE
, STRLC_NUMERIC
,
1308 STRLC_TIME
, STRLC_COLLATE
, STRLC_MESSAGES
, STRLC_MONETARY
, 0
1312 for (v
= locale_vars
; *v
; ++v
)
1319 xlate_cr_cleanup(void *dummy
)
1327 doprintenv(Char
**v
, struct command
*c
)
1337 cleanup_push(&xlate_cr
, xlate_cr_cleanup
);
1338 for (ep
= STR_environ
; *ep
; ep
++) {
1340 int old_pintr_disabled
;
1342 pintr_push_enable(&old_pintr_disabled
);
1343 cleanup_until(&old_pintr_disabled
);
1345 xprintf("%S\n", *ep
);
1347 cleanup_until(&xlate_cr
);
1349 else if ((e
= tgetenv(*v
)) != NULL
) {
1352 old_output_raw
= output_raw
;
1354 cleanup_push(&old_output_raw
, output_raw_restore
);
1356 cleanup_until(&old_output_raw
);
1359 setcopy(STRstatus
, STR1
, VAR_READWRITE
);
1362 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1363 (and anything else with a modern compiler) */
1367 dosetenv(Char
**v
, struct command
*c
)
1381 stderror(ERR_NAME
| ERR_VARBEGIN
);
1384 } while (alnum(*lp
));
1386 stderror(ERR_NAME
| ERR_VARALNUM
);
1388 if ((lp
= *v
++) == 0)
1391 lp
= globone(lp
, G_APPEND
);
1392 cleanup_push(lp
, xfree
);
1394 if (eq(vp
, STRKPATH
)) {
1402 if (eq(vp
, STRSYSTYPE
)) {
1409 /* dspkanji/dspmbyte autosetting */
1410 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1411 #if defined(DSPMBYTE)
1412 if(eq(vp
, STRLANG
) && !adrof(CHECK_MBYTEVAR
)) {
1413 autoset_dspmbyte(lp
);
1417 if (islocale_var(vp
)) {
1421 # ifdef SETLOCALEBUG
1423 # endif /* SETLOCALEBUG */
1424 (void) setlocale(LC_ALL
, "");
1426 (void) setlocale(LC_COLLATE
, "");
1429 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1430 # endif /* LC_CTYPE */
1431 # if defined(AUTOSET_KANJI)
1433 # endif /* AUTOSET_KANJI */
1434 # ifdef NLS_CATALOGS
1436 (void) setlocale(LC_MESSAGES
, "");
1437 # endif /* LC_MESSAGES */
1440 # endif /* NLS_CATALOGS */
1441 # ifdef SETLOCALEBUG
1443 # endif /* SETLOCALEBUG */
1446 # endif /* STRCOLLBUG */
1447 tw_cmd_free(); /* since the collation sequence has changed */
1448 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1450 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1454 NLSMapsAreInited
= 0;
1456 if (MapsAreInited
&& !NLSMapsAreInited
)
1463 if (eq(vp
, STRNLSPATH
)) {
1469 if (eq(vp
, STRNOREBIND
)) {
1472 NLSMapsAreInited
= 0;
1478 if (eq(vp
, STRtcshlang
)) {
1483 #endif /* WINNT_NATIVE */
1484 if (eq(vp
, STRKTERM
)) {
1487 setv(STRterm
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1491 if (noediting
&& strcmp(t
, "unknown") != 0 && strcmp(t
,"dumb") != 0) {
1501 if (eq(vp
, STRKHOME
)) {
1504 * convert to canonical pathname (possibly resolving symlinks)
1506 canon
= dcanon(lp
, lp
);
1509 cleanup_push(canon
, xfree
);
1510 setv(STRhome
, quote(canon
), VAR_READWRITE
); /* lp memory used here */
1511 cleanup_ignore(canon
);
1512 cleanup_until(canon
);
1514 /* fix directory stack for new tilde home */
1519 if (eq(vp
, STRKSHLVL
)) {
1520 setv(STRshlvl
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1526 if (eq(vp
, STRKUSER
)) {
1527 setv(STRuser
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1533 if (eq(vp
, STRKGROUP
)) {
1534 setv(STRgroup
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1541 if (eq(vp
, STRLS_COLORS
)) {
1546 #endif /* COLOR_LS_F */
1550 * Load/Update $LINES $COLUMNS
1552 if ((eq(lp
, STRNULL
) && (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
))) ||
1553 eq(vp
, STRTERMCAP
)) {
1555 check_window_size(1);
1560 * Change the size to the one directed by $LINES and $COLUMNS
1562 if (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
)) {
1570 #endif /* SIG_WINDOW */
1576 dounsetenv(Char
**v
, struct command
*c
)
1578 Char
**ep
, *p
, *n
, *name
;
1583 * Find the longest environment variable
1585 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1586 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
1592 name
= xmalloc((maxi
+ 1) * sizeof(Char
));
1593 cleanup_push(name
, xfree
);
1596 for (maxi
= 1; maxi
;)
1597 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1598 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
1601 if (!Gmatch(name
, *v
))
1605 /* Unset the name. This wasn't being done until
1606 * later but most of the stuff following won't
1607 * work (particularly the setlocale() and getenv()
1608 * stuff) as intended until the name is actually
1613 if (eq(name
, STRNOREBIND
)) {
1616 NLSMapsAreInited
= 0;
1620 else if (eq(name
, STRSYSTYPE
))
1623 else if (islocale_var(name
)) {
1627 # ifdef SETLOCALEBUG
1629 # endif /* SETLOCALEBUG */
1630 (void) setlocale(LC_ALL
, "");
1632 (void) setlocale(LC_COLLATE
, "");
1635 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1636 # endif /* LC_CTYPE */
1637 # ifdef NLS_CATALOGS
1639 (void) setlocale(LC_MESSAGES
, "");
1640 # endif /* LC_MESSAGES */
1643 # endif /* NLS_CATALOGS */
1644 # ifdef SETLOCALEBUG
1646 # endif /* SETLOCALEBUG */
1649 # endif /* STRCOLLBUG */
1650 tw_cmd_free();/* since the collation sequence has changed */
1651 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1653 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1655 AsciiOnly
= getenv("LANG") == NULL
&&
1656 getenv("LC_CTYPE") == NULL
;
1658 NLSMapsAreInited
= 0;
1660 if (MapsAreInited
&& !NLSMapsAreInited
)
1665 else if (eq(name
,(STRtcshlang
))) {
1669 #endif /* WINNT_NATIVE */
1671 else if (eq(name
, STRLS_COLORS
))
1673 #endif /* COLOR_LS_F */
1675 else if (eq(name
, STRNLSPATH
)) {
1681 * start again cause the environment changes
1685 cleanup_until(name
);
1689 tsetenv(const Char
*name
, const Char
*val
)
1691 #ifdef SETENV_IN_LIB
1693 * XXX: This does not work right, since tcsh cannot track changes to
1694 * the environment this way. (the builtin setenv without arguments does
1695 * not print the right stuff neither does unsetenv). This was for Mach,
1696 * it is not needed anymore.
1703 cname
= strsave(short2str(name
));
1704 setenv(cname
, short2str(val
), 1);
1706 #else /* !SETENV_IN_LIB */
1707 Char
**ep
= STR_environ
;
1714 nt_set_env(name
,val
);
1715 #endif /* WINNT_NATIVE */
1718 for (ccp
= name
, dp
= *ep
; *ccp
&& Tolower(*ccp
& TRIM
) == Tolower(*dp
);
1721 for (ccp
= name
, dp
= *ep
; *ccp
&& (*ccp
& TRIM
) == *dp
; ccp
++, dp
++)
1722 #endif /* WINNT_NATIVE */
1724 if (*ccp
!= 0 || *dp
!= '=')
1726 cp
= Strspl(STRequal
, val
);
1728 *ep
= strip(Strspl(name
, cp
));
1730 blkfree((Char
**) environ
);
1731 environ
= short2blk(STR_environ
);
1734 cp
= Strspl(name
, STRequal
);
1735 blk
[0] = strip(Strspl(cp
, val
));
1738 STR_environ
= blkspl(STR_environ
, blk
);
1739 blkfree((Char
**) environ
);
1740 environ
= short2blk(STR_environ
);
1742 #endif /* SETENV_IN_LIB */
1746 Unsetenv(Char
*name
)
1748 Char
**ep
= STR_environ
;
1753 nt_set_env(name
,NULL
);
1754 #endif /*WINNT_NATIVE */
1756 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1758 if (*cp
!= 0 || *dp
!= '=')
1762 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1763 blkfree((Char
**) environ
);
1764 environ
= short2blk(STR_environ
);
1774 doumask(Char
**v
, struct command
*c
)
1787 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1788 i
= i
* 8 + *cp
++ - '0';
1789 if (*cp
|| i
< 0 || i
> 0777)
1790 stderror(ERR_NAME
| ERR_MASK
);
1796 typedef long RLIM_TYPE
;
1797 # ifdef _OSD_POSIX /* BS2000 */
1798 # include <ulimit.h>
1800 # ifndef RLIM_INFINITY
1801 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1802 extern RLIM_TYPE
ulimit();
1803 # endif /* ! _MINIX && !__clipper__ */
1804 # define RLIM_INFINITY 0x003fffff
1805 # define RLIMIT_FSIZE 1
1806 # endif /* RLIM_INFINITY */
1808 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1809 # define RLIMIT_DATA 3
1810 # define RLIMIT_STACK 1005
1812 # define toset(a) ((a) + 1)
1814 # else /* BSDLIMIT */
1815 # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
1816 typedef rlim_t RLIM_TYPE
;
1818 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1819 typedef rlim_t RLIM_TYPE
;
1822 typedef long long RLIM_TYPE
;
1824 typedef unsigned long RLIM_TYPE
;
1826 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1827 # endif /* BSD4_4 && !__386BSD__ */
1828 # endif /* BSDLIMIT */
1830 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
1831 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1832 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1834 # define RLIMIT_CPU 0
1835 # define RLIMIT_FSIZE 1
1836 # define RLIMIT_DATA 2
1837 # define RLIMIT_STACK 3
1838 # define RLIMIT_CORE 4
1839 # define RLIMIT_RSS 5
1840 # define RLIMIT_NOFILE 6
1841 # endif /* RLIMIT_CPU */
1842 # ifndef RLIM_INFINITY
1843 # define RLIM_INFINITY 0x7fffffff
1844 # endif /* RLIM_INFINITY */
1846 * old versions of HP/UX counted limits in 512 bytes
1849 # define FILESIZE512
1850 # endif /* SIGRTMIN */
1851 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
1853 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1854 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1855 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1856 /* than include both and get warnings, we define the extra SVR4 limits here. */
1857 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1858 /* RLIMIT_VMEM based on it? */
1859 # ifndef RLIMIT_VMEM
1860 # define RLIMIT_VMEM 6
1863 # define RLIMIT_AS RLIMIT_VMEM
1865 # endif /* SYSVREL > 3 && BSDLIMIT */
1867 # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__))
1868 # if defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1869 # define RLIMIT_VMEM RLIMIT_AS
1872 * Oh well, <asm-generic/resource.h> has it, but <bits/resource.h> does not
1873 * Linux headers: When the left hand does not know what the right hand does.
1875 # if defined(RLIMIT_RTPRIO) && !defined(RLIMIT_RTTIME)
1876 # define RLIMIT_RTTIME (RLIMIT_RTPRIO + 1)
1880 struct limits limits
[] =
1883 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1884 # endif /* RLIMIT_CPU */
1886 # ifdef RLIMIT_FSIZE
1888 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1890 { RLIMIT_FSIZE
, "filesize", 512, "blocks" },
1892 # endif /* RLIMIT_FSIZE */
1895 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1896 # endif /* RLIMIT_DATA */
1898 # ifdef RLIMIT_STACK
1900 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1902 { RLIMIT_STACK
, "stacksize", 1024 * 1024, "kbytes"},
1904 # endif /* RLIMIT_STACK */
1907 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1908 # endif /* RLIMIT_CORE */
1911 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1912 # endif /* RLIMIT_RSS */
1915 { RLIMIT_UMEM
, "memoryuse", 1024, "kbytes" },
1916 # endif /* RLIMIT_UMEM */
1919 { RLIMIT_VMEM
, "vmemoryuse", 1024, "kbytes" },
1920 # endif /* RLIMIT_VMEM */
1922 # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
1923 { RLIMIT_HEAP
, "heapsize", 1024, "kbytes" },
1924 # endif /* RLIMIT_HEAP */
1926 # ifdef RLIMIT_NOFILE
1927 { RLIMIT_NOFILE
, "descriptors", 1, "" },
1928 # endif /* RLIMIT_NOFILE */
1930 # ifdef RLIMIT_CONCUR
1931 { RLIMIT_CONCUR
, "concurrency", 1, "thread(s)" },
1932 # endif /* RLIMIT_CONCUR */
1934 # ifdef RLIMIT_MEMLOCK
1935 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1936 # endif /* RLIMIT_MEMLOCK */
1938 # ifdef RLIMIT_NPROC
1939 { RLIMIT_NPROC
, "maxproc", 1, "" },
1940 # endif /* RLIMIT_NPROC */
1942 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1943 { RLIMIT_OFILE
, "openfiles", 1, "" },
1944 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1946 # ifdef RLIMIT_SBSIZE
1947 { RLIMIT_SBSIZE
, "sbsize", 1, "" },
1948 # endif /* RLIMIT_SBSIZE */
1950 #ifdef RLIMIT_POSIXLOCKS
1951 { RLIMIT_POSIXLOCKS
, "posixlocks", 1, "" },
1952 #endif /* RLIMIT_POSIXLOCKS */
1955 { RLIMIT_SWAP
, "swapsize", 1024, "kbytes" },
1956 # endif /* RLIMIT_SWAP */
1958 # ifdef RLIMIT_LOCKS
1959 { RLIMIT_LOCKS
, "maxlocks", 1, "" },
1960 # endif /* RLIMIT_LOCKS */
1962 # ifdef RLIMIT_SIGPENDING
1963 { RLIMIT_SIGPENDING
,"maxsignal", 1, "" },
1964 # endif /* RLIMIT_SIGPENDING */
1966 # ifdef RLIMIT_MSGQUEUE
1967 { RLIMIT_MSGQUEUE
, "maxmessage", 1, "" },
1968 # endif /* RLIMIT_MSGQUEUE */
1971 { RLIMIT_NICE
, "maxnice", 1, "" },
1972 # endif /* RLIMIT_NICE */
1974 # ifdef RLIMIT_RTPRIO
1975 { RLIMIT_RTPRIO
, "maxrtprio", 1, "" },
1976 # endif /* RLIMIT_RTPRIO */
1978 # ifdef RLIMIT_RTTIME
1979 { RLIMIT_RTTIME
, "maxrttime", 1, "usec" },
1980 # endif /* RLIMIT_RTTIME */
1982 { -1, NULL
, 0, NULL
}
1985 static struct limits
*findlim (Char
*);
1986 static RLIM_TYPE
getval (struct limits
*, Char
**);
1987 static int strtail (Char
*, const char *);
1988 static void limtail (Char
*, const char *);
1989 static void limtail2 (Char
*, const char *, const char *);
1990 static void plim (struct limits
*, int);
1991 static int setlim (struct limits
*, int, RLIM_TYPE
);
1995 restrict_limit(double value
)
1998 * is f too large to cope with? return the maximum or minimum int
2000 if (value
> (double) INT_MAX
)
2001 return (RLIM_TYPE
) INT_MAX
;
2002 else if (value
< (double) INT_MIN
)
2003 return (RLIM_TYPE
) INT_MIN
;
2005 return (RLIM_TYPE
) value
;
2008 # define restrict_limit(x) ((RLIM_TYPE) (x))
2012 static struct limits
*
2015 struct limits
*lp
, *res
;
2018 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2019 if (prefix(cp
, str2short(lp
->limname
))) {
2021 stderror(ERR_NAME
| ERR_AMBIG
);
2026 stderror(ERR_NAME
| ERR_LIMIT
);
2033 dolimit(Char
**v
, struct command
*c
)
2041 if (*v
&& eq(*v
, STRmh
)) {
2046 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2055 limit
= getval(lp
, v
+ 1);
2056 if (setlim(lp
, hard
, limit
) < 0)
2057 stderror(ERR_SILENT
);
2061 getval(struct limits
*lp
, Char
**v
)
2066 f
= atof(short2str(cp
));
2070 * is f too large to cope with. limit f to minint, maxint - X-6768 by
2073 if ((f
< (double) INT_MIN
) || (f
> (double) INT_MAX
)) {
2074 stderror(ERR_NAME
| ERR_TOOLARGE
);
2076 # endif /* convex */
2078 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
2082 return restrict_limit((f
* lp
->limdiv
) + 0.5);
2088 if (lp
->limconst
!= RLIMIT_CPU
)
2090 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
* 60.0 + atof(short2str(cp
+ 1))));
2092 if (lp
->limconst
!= RLIMIT_CPU
)
2094 limtail(cp
, "hours");
2097 # endif /* RLIMIT_CPU */
2100 if (lp
->limconst
== RLIMIT_CPU
) {
2101 limtail(cp
, "minutes");
2105 # endif /* RLIMIT_CPU */
2106 limtail2(cp
, "megabytes", "mbytes");
2107 f
*= 1024.0 * 1024.0;
2111 if (lp
->limconst
!= RLIMIT_CPU
)
2113 limtail(cp
, "seconds");
2115 # endif /* RLIMIT_CPU */
2121 if (lp
->limconst
== RLIMIT_CPU
)
2123 # endif /* RLIMIT_CPU */
2124 limtail2(cp
, "gigabytes", "gbytes");
2125 f
*= 1024.0 * 1024.0 * 1024.0;
2129 if (lp
->limconst
== RLIMIT_CPU
)
2131 # endif /* RLIMIT_CPU */
2133 limtail2(cp
, "megabytes", "mbytes");
2134 f
*= 1024.0 * 1024.0;
2138 if (lp
->limconst
== RLIMIT_CPU
)
2140 # endif /* RLIMIT_CPU */
2141 limtail2(cp
, "kilobytes", "kbytes");
2146 if (lp
->limconst
== RLIMIT_CPU
)
2148 # endif /* RLIMIT_CPU */
2149 limtail(cp
, "blocks");
2153 limtail(cp
, "unlimited");
2154 return ((RLIM_TYPE
) RLIM_INFINITY
);
2158 # endif /* RLIMIT_CPU */
2159 stderror(ERR_NAME
| ERR_SCALEF
);
2162 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
+ 0.5));
2165 if (f
> (float) ((RLIM_TYPE
) RLIM_INFINITY
))
2166 return ((RLIM_TYPE
) RLIM_INFINITY
);
2168 return ((RLIM_TYPE
) f
);
2169 # endif /* convex */
2173 strtail(Char
*cp
, const char *str
)
2175 while (*cp
&& *cp
== (Char
)*str
)
2177 return (*cp
!= '\0');
2181 limtail(Char
*cp
, const char *str
)
2183 if (strtail(cp
, str
))
2184 stderror(ERR_BADSCALE
, str
);
2188 limtail2(Char
*cp
, const char *str1
, const char *str2
)
2190 if (strtail(cp
, str1
) && strtail(cp
, str2
))
2191 stderror(ERR_BADSCALE
, str1
);
2196 plim(struct limits
*lp
, int hard
)
2200 # endif /* BSDLIMIT */
2202 int xdiv
= lp
->limdiv
;
2204 xprintf("%-13.13s", lp
->limname
);
2207 limit
= ulimit(lp
->limconst
, 0);
2209 if (lp
->limconst
== RLIMIT_DATA
)
2210 limit
-= 0x20000000;
2212 # else /* BSDLIMIT */
2213 (void) getrlimit(lp
->limconst
, &rlim
);
2214 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
2215 # endif /* BSDLIMIT */
2217 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2219 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2220 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2222 if (lp
->limconst
== RLIMIT_FSIZE
) {
2223 if (limit
>= (RLIM_INFINITY
/ 512))
2224 limit
= RLIM_INFINITY
;
2226 xdiv
= (xdiv
== 1024 ? 2 : 1);
2228 # endif /* !BSDLIMIT || FILESIZE512 */
2230 if (limit
== RLIM_INFINITY
)
2231 xprintf("unlimited");
2233 # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
2234 if (lp
->limconst
== RLIMIT_CPU
&&
2235 (unsigned long)limit
>= 0x7ffffffdUL
)
2236 xprintf("unlimited");
2240 if (lp
->limconst
== RLIMIT_CPU
)
2243 # endif /* RLIMIT_CPU */
2244 xprintf("%ld %s", (long) (limit
/ xdiv
), lp
->limscale
);
2250 dounlimit(Char
**v
, struct command
*c
)
2258 while (*++v
&& **v
== '-') {
2269 stderror(ERR_ULIMUS
);
2275 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2276 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0)
2279 stderror(ERR_SILENT
);
2284 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0 && !force
)
2285 stderror(ERR_SILENT
);
2290 setlim(struct limits
*lp
, int hard
, RLIM_TYPE limit
)
2295 (void) getrlimit(lp
->limconst
, &rlim
);
2298 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2299 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2301 # endif /* FILESIZE512 */
2303 rlim
.rlim_max
= limit
;
2304 else if (limit
== RLIM_INFINITY
&& euid
!= 0)
2305 rlim
.rlim_cur
= rlim
.rlim_max
;
2307 rlim
.rlim_cur
= limit
;
2309 if (rlim
.rlim_cur
> rlim
.rlim_max
)
2310 rlim
.rlim_max
= rlim
.rlim_cur
;
2312 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
2313 # else /* BSDLIMIT */
2314 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2317 if (lp
->limconst
== RLIMIT_DATA
)
2318 limit
+= 0x20000000;
2320 if (ulimit(toset(lp
->limconst
), limit
) < 0) {
2321 # endif /* BSDLIMIT */
2326 op
= strsave(limit
== RLIM_INFINITY
? CGETS(15, 2, "remove") :
2327 CGETS(15, 3, "set"));
2328 cleanup_push(op
, xfree
);
2329 type
= strsave(hard
? CGETS(15, 4, " hard") : "");
2330 cleanup_push(type
, xfree
);
2331 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname
,
2332 lp
->limname
, op
, type
, strerror(err
));
2339 #endif /* !HAVENOLIMIT */
2343 dosuspend(Char
**v
, struct command
*c
)
2346 struct sigaction old
;
2347 #endif /* BSDJOBS */
2353 stderror(ERR_SUSPLOG
);
2357 sigaction(SIGTSTP
, NULL
, &old
);
2358 signal(SIGTSTP
, SIG_DFL
);
2359 (void) kill(0, SIGTSTP
);
2360 /* the shell stops here */
2361 sigaction(SIGTSTP
, &old
, NULL
);
2362 #else /* !BSDJOBS */
2363 stderror(ERR_JOBCONTROL
);
2364 #endif /* BSDJOBS */
2368 if (grabpgrp(FSHTTY
, opgrp
) == -1)
2369 stderror(ERR_SYSTEM
, "tcgetpgrp", strerror(errno
));
2370 (void) setpgid(0, shpgrp
);
2371 (void) tcsetpgrp(FSHTTY
, shpgrp
);
2373 #endif /* BSDJOBS */
2374 (void) setdisc(FSHTTY
);
2377 /* This is the dreaded EVAL built-in.
2378 * If you don't fiddle with file descriptors, and reset didfds,
2379 * this command will either ignore redirection inside or outside
2380 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2381 * The stuff here seems to work, but I did it by trial and error rather
2382 * than really knowing what was going on. If tpgrp is zero, we are
2383 * probably a background eval, e.g. "eval date &", and we want to
2384 * make sure that any processes we start stay in our pgrp.
2385 * This is also the case for "time eval date" -- stay in same pgrp.
2386 * Otherwise, under stty tostop, processes will stop in the wrong
2387 * pgrp, with no way for the shell to get them going again. -IAN!
2392 Char
**evalvec
, *evalp
;
2394 #ifndef CLOSE_ON_EXEC
2397 int saveIN
, saveOUT
, saveDIAG
;
2398 int SHIN
, SHOUT
, SHDIAG
;
2402 doeval_cleanup(void *xstate
)
2404 struct doeval_state
*state
;
2407 evalvec
= state
->evalvec
;
2408 evalp
= state
->evalp
;
2410 #ifndef CLOSE_ON_EXEC
2411 didcch
= state
->didcch
;
2412 #endif /* CLOSE_ON_EXEC */
2413 didfds
= state
->didfds
;
2417 close_on_exec(SHIN
= dmove(state
->saveIN
, state
->SHIN
), 1);
2418 close_on_exec(SHOUT
= dmove(state
->saveOUT
, state
->SHOUT
), 1);
2419 close_on_exec(SHDIAG
= dmove(state
->saveDIAG
, state
->SHDIAG
), 1);
2425 doeval(Char
**v
, struct command
*c
)
2427 struct doeval_state state
;
2428 int gflag
, my_reenter
;
2438 gv
= v
= globall(v
, gflag
);
2440 stderror(ERR_NOMATCH
);
2441 cleanup_push(gv
, blk_cleanup
);
2451 state
.evalvec
= evalvec
;
2452 state
.evalp
= evalp
;
2453 state
.didfds
= didfds
;
2454 #ifndef CLOSE_ON_EXEC
2455 state
.didcch
= didcch
;
2456 #endif /* CLOSE_ON_EXEC */
2458 state
.SHOUT
= SHOUT
;
2459 state
.SHDIAG
= SHDIAG
;
2461 (void)close_on_exec(state
.saveIN
= dcopy(SHIN
, -1), 1);
2462 (void)close_on_exec(state
.saveOUT
= dcopy(SHOUT
, -1), 1);
2463 (void)close_on_exec(state
.saveDIAG
= dcopy(SHDIAG
, -1), 1);
2465 cleanup_push(&state
, doeval_cleanup
);
2469 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
2471 my_reenter
= 1; /* assume non-zero return val */
2472 if (setexit() == 0) {
2473 my_reenter
= 0; /* Oh well, we were wrong */
2475 if ((my_reenter
= setexit()) == 0) {
2479 (void)close_on_exec(SHIN
= dcopy(0, -1), 1);
2480 (void)close_on_exec(SHOUT
= dcopy(1, -1), 1);
2481 (void)close_on_exec(SHDIAG
= dcopy(2, -1), 1);
2482 #ifndef CLOSE_ON_EXEC
2484 #endif /* CLOSE_ON_EXEC */
2491 if (my_reenter
== 0) {
2492 cleanup_until(&state
);
2499 stderror(ERR_SILENT
);
2502 /*************************************************************************/
2503 /* print list of builtin commands */
2506 lbuffed_cleanup (void *dummy
)
2514 dobuiltins(Char
**v
, struct command
*c
)
2516 /* would use print_by_column() in tw.parse.c but that assumes
2517 * we have an array of Char * to pass.. (sg)
2519 const struct biltins
*b
;
2520 int row
, col
, columns
, rows
;
2521 unsigned int w
, maxwidth
;
2525 lbuffed
= 0; /* turn off line buffering */
2526 cleanup_push(&lbuffed
, lbuffed_cleanup
);
2528 /* find widest string */
2529 for (maxwidth
= 0, b
= bfunc
; b
< &bfunc
[nbfunc
]; ++b
)
2530 maxwidth
= max(maxwidth
, strlen(b
->bname
));
2531 ++maxwidth
; /* for space */
2533 columns
= (TermH
+ 1) / maxwidth
; /* PWP: terminal size change */
2536 rows
= (nbfunc
+ (columns
- 1)) / columns
;
2538 for (b
= bfunc
, row
= 0; row
< rows
; row
++) {
2539 for (col
= 0; col
< columns
; col
++) {
2540 if (b
< &bfunc
[nbfunc
]) {
2541 w
= strlen(b
->bname
);
2542 xprintf("%s", b
->bname
);
2543 if (col
< (columns
- 1)) /* Not last column? */
2544 for (; w
< maxwidth
; w
++)
2549 if (row
< (rows
- 1)) {
2556 nt_print_builtins(maxwidth
);
2561 #endif /* WINNT_NATIVE */
2563 cleanup_until(&lbuffed
); /* turn back on line buffering */
2569 xcatgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2574 while ((res
= catgets(ctd
, set_id
, msg_id
, s
)) == s
&& errno
== EINTR
) {
2575 handle_pending_signals();
2582 # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2584 iconv_catgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2586 static char *buf
= NULL
;
2587 static size_t buf_size
= 0;
2589 char *orig
, *dest
, *p
;
2590 ICONV_CONST
char *src
;
2591 size_t src_size
, dest_size
;
2593 orig
= xcatgets(ctd
, set_id
, msg_id
, s
);
2594 if (catgets_iconv
== (iconv_t
)-1 || orig
== s
)
2597 src_size
= strlen(src
) + 1;
2598 if (buf
== NULL
&& (buf
= xmalloc(buf_size
= src_size
+ 32)) == NULL
)
2601 while (src_size
!= 0) {
2602 dest_size
= buf
+ buf_size
- dest
;
2603 if (iconv(catgets_iconv
, &src
, &src_size
, &dest
, &dest_size
)
2607 if ((p
= xrealloc(buf
, buf_size
* 2)) == NULL
)
2610 dest
= p
+ (dest
- buf
);
2614 case EILSEQ
: case EINVAL
: default:
2621 # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2622 #endif /* NLS_CATALOGS */
2628 static const char default_catalog
[] = "tcsh";
2630 char *catalog
= (char *)(intptr_t)default_catalog
;
2632 if (adrof(STRcatalog
) != NULL
)
2633 catalog
= xasprintf("tcsh.%s", short2str(varval(STRcatalog
)));
2634 #ifdef NL_CAT_LOCALE /* POSIX-compliant. */
2636 * Check if LC_MESSAGES is set in the environment and use it, if so.
2637 * If not, fall back to the setting of LANG.
2639 catd
= catopen(catalog
, tgetenv(STRLC_MESSAGES
) ? NL_CAT_LOCALE
: 0);
2640 #else /* pre-POSIX */
2641 # ifndef MCLoadBySet
2642 # define MCLoadBySet 0
2644 catd
= catopen(catalog
, MCLoadBySet
);
2646 if (catalog
!= default_catalog
)
2648 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2649 /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
2650 catgets_iconv
= iconv_open (nl_langinfo (CODESET
),
2651 xcatgets(catd
, 255, 1, "UTF-8"));
2652 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2653 #endif /* NLS_CATALOGS */
2656 #endif /* WINNT_NATIVE */
2657 errinit(); /* init the errorlist in correct locale */
2658 mesginit(); /* init the messages for signals */
2659 dateinit(); /* init the messages for dates */
2660 editinit(); /* init the editor messages */
2661 terminit(); /* init the termcap messages */
2668 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2669 if (catgets_iconv
!= (iconv_t
)-1) {
2670 iconv_close(catgets_iconv
);
2671 catgets_iconv
= (iconv_t
)-1;
2673 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2674 if (catd
!= (nl_catd
)-1) {
2676 * catclose can call other functions which can call longjmp
2677 * making us re-enter this code. Prevent infinite recursion
2678 * by resetting catd. Problem reported and solved by:
2681 nl_catd oldcatd
= catd
;
2683 while (catclose(oldcatd
) == -1 && errno
== EINTR
)
2684 handle_pending_signals();
2686 #endif /* NLS_CATALOGS */