2 * sh.func.c: csh builtin functions
5 * Copyright (c) 1980, 1991 The Regents of the University of California.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #endif /* WINNT_NATIVE */
40 #if defined (NLS_CATALOGS) && defined(HAVE_ICONV)
41 static iconv_t catgets_iconv
; /* Or (iconv_t)-1 */
48 extern int MapsAreInited
;
49 extern int NLSMapsAreInited
;
50 extern int GotTermCaps
;
52 static int zlast
= -1;
54 static void islogin (void);
55 static void preread (void);
56 static void doagain (void);
57 static const char *isrchx (int);
58 static void search (int, int, Char
*);
59 static int getword (struct Strbuf
*);
60 static struct wordent
*histgetword (struct wordent
*);
61 static void toend (void);
62 static void xecho (int, Char
**);
63 static int islocale_var (Char
*);
64 static void wpfree (struct whyle
*);
66 const struct biltins
*
67 isbfunc(struct command
*t
)
69 Char
*cp
= t
->t_dcom
[0];
70 const struct biltins
*bp
, *bp1
, *bp2
;
71 static struct biltins label
= {"", dozip
, 0, 0};
72 static struct biltins foregnd
= {"%job", dofg1
, 0, 0};
73 static struct biltins backgnd
= {"%job &", dobg1
, 0, 0};
76 * We never match a builtin that has quoted the first
77 * character; this has been the traditional way to escape
83 if (*cp
!= ':' && 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
);
98 * This is a perhaps kludgy way to determine if the warp builtin is to be
99 * acknowledged or not. If checkwarp() fails, then we are to assume that
100 * the warp command is invalid, and carry on as we would handle any other
101 * non-builtin command. -- JDK 2/4/88
103 if (eq(STRwarp
, cp
) && !checkwarp()) {
104 return (0); /* this builtin disabled */
108 * Binary search Bp1 is the beginning of the current search range. Bp2 is
111 for (bp1
= bfunc
, bp2
= bfunc
+ nbfunc
; bp1
< bp2
;) {
114 bp
= bp1
+ ((bp2
- bp1
) >> 1);
115 if ((i
= ((char) *cp
) - *bp
->bname
) == 0 &&
116 (i
= StrQcmp(cp
, str2short(bp
->bname
))) == 0)
124 return nt_check_additional_builtins(cp
);
125 #endif /*WINNT_NATIVE*/
130 func(struct command
*t
, const struct biltins
*bp
)
136 i
= blklen(t
->t_dcom
) - 1;
138 stderror(ERR_NAME
| ERR_TOOFEW
);
140 stderror(ERR_NAME
| ERR_TOOMANY
);
141 (*bp
->bfunct
) (t
->t_dcom
, t
);
146 doonintr(Char
**v
, struct command
*c
)
152 if (parintr
.sa_handler
== SIG_IGN
)
154 if (setintr
&& intty
)
155 stderror(ERR_NAME
| ERR_TERMINAL
);
161 sigset_interrupting(SIGINT
, queue_pintr
);
163 (void) signal(SIGINT
, SIG_DFL
);
166 else if (eq((vv
= strip(vv
)), STRminus
)) {
167 (void) signal(SIGINT
, SIG_IGN
);
168 gointr
= Strsave(STRminus
);
171 gointr
= Strsave(vv
);
172 sigset_interrupting(SIGINT
, queue_pintr
);
178 donohup(Char
**v
, struct command
*c
)
183 stderror(ERR_NAME
| ERR_TERMINAL
);
185 (void) signal(SIGHUP
, SIG_IGN
);
195 dohup(Char
**v
, struct command
*c
)
200 stderror(ERR_NAME
| ERR_TERMINAL
);
202 sigset_interrupting(SIGHUP
, SIG_DFL
);
208 dozip(Char
**v
, struct command
*c
)
216 dofiletest(Char
**v
, struct command
*c
)
218 Char
**globbed
, **fileptr
, *ftest
, *res
;
221 if (*(ftest
= *++v
) != '-')
222 stderror(ERR_NAME
| ERR_FILEINQ
);
225 v
= glob_all_or_error(v
);
227 cleanup_push(globbed
, blk_cleanup
);
229 while (*(fileptr
= v
++) != NULL
) {
230 res
= filetest(ftest
, &fileptr
, TEXP_NOGLOB
);
231 cleanup_push(res
, xfree
);
232 xprintf("%" TCSH_S
, res
);
239 cleanup_until(globbed
);
245 plist(&shvhed
, VAR_ALL
);
250 doalias(Char
**v
, struct command
*c
)
259 plist(&aliases
, VAR_ALL
);
261 vp
= adrof1(strip(p
), &aliases
);
263 blkpr(vp
->vec
), xputchar('\n');
266 if (eq(p
, STRalias
) || eq(p
, STRunalias
)) {
267 setname(short2str(p
));
268 stderror(ERR_NAME
| ERR_DANGER
);
270 set1(strip(p
), saveblk(v
), &aliases
, VAR_READWRITE
);
277 unalias(Char
**v
, struct command
*c
)
286 dologout(Char
**v
, struct command
*c
)
296 dologin(Char
**v
, struct command
*c
)
301 #else /* !WINNT_NATIVE */
302 char **p
= short2blk(v
);
305 cleanup_push((Char
**)p
, blk_cleanup
);
307 rechist(NULL
, adrof(STRsavehist
) != NULL
);
308 sigaction(SIGTERM
, &parterm
, NULL
);
309 (void) execv(_PATH_BIN_LOGIN
, p
);
310 (void) execv(_PATH_USRBIN_LOGIN
, p
);
311 cleanup_until((Char
**)p
);
314 #endif /* !WINNT_NATIVE */
321 donewgrp(Char
**v
, struct command
*c
)
324 if (chkstop
== 0 && setintr
)
326 sigaction(SIGTERM
, &parterm
, NULL
);
329 * From Beto Appleton (beto@aixwiz.austin.ibm.com)
330 * Newgrp can take 2 arguments...
332 (void) execv(_PATH_BIN_NEWGRP
, p
);
333 (void) execv(_PATH_USRBIN_NEWGRP
, p
);
334 blkfree((Char
**) p
);
343 if (chkstop
== 0 && setintr
)
347 stderror(ERR_NOTLOGIN
);
351 doif(Char
**v
, struct command
*kp
)
357 i
= noexec
? 1 : expr(&v
);
360 stderror(ERR_NAME
| ERR_EMPTYIF
);
361 if (eq(*vv
, STRthen
)) {
363 stderror(ERR_NAME
| ERR_IMPRTHEN
);
364 setname(short2str(STRthen
));
366 * If expression was zero, then scan to else , otherwise just fall into
370 search(TC_IF
, 0, NULL
);
374 * Simple command attached to this if. Left shift the node in this tree,
375 * munging it so we can reexecute it.
378 lshift(kp
->t_dcom
, vv
- kp
->t_dcom
);
385 * Reexecute a command, being careful not
386 * to redo i/o redirection, which is already set up.
389 reexecute(struct command
*kp
)
391 kp
->t_dflg
&= F_SAVE
;
392 kp
->t_dflg
|= F_REPEAT
;
394 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
395 * pgrp's as the jobs would then have no way to get the tty (we can't give
396 * it to them, and our parent wouldn't know their pgrp, etc.
398 execute(kp
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
, TRUE
);
403 doelse (Char
**v
, struct command
*c
)
408 search(TC_ELSE
, 0, NULL
);
413 dogoto(Char
**v
, struct command
*c
)
418 lp
= globone(v
[1], G_ERROR
);
419 cleanup_push(lp
, xfree
);
430 * While we still can, locate any unknown ends of existing loops. This
431 * obscure code is the WORST result of the fact that we don't really parse.
434 for (wp
= whyles
; wp
; wp
= wp
->w_next
)
435 if (wp
->w_end
.type
== TCSH_F_SEEK
&& wp
->w_end
.f_seek
== 0) {
436 search(TC_BREAK
, 0, NULL
);
442 search(TC_GOTO
, 0, lab
);
444 * Eliminate loops which were exited.
451 doswitch(Char
**v
, struct command
*c
)
457 if (!*v
|| *(*v
++) != '(')
458 stderror(ERR_SYNTAX
);
459 cp
= **v
== ')' ? STRNULL
: *v
++;
463 stderror(ERR_SYNTAX
);
464 lp
= globone(cp
, G_ERROR
);
465 cleanup_push(lp
, xfree
);
467 search(TC_SWITCH
, 0, lp
);
473 dobreak(Char
**v
, struct command
*c
)
478 stderror(ERR_NAME
| ERR_NOTWHILE
);
485 doexit(Char
**v
, struct command
*c
)
489 if (chkstop
== 0 && (intty
|| intact
) && evalvec
== 0)
492 * Don't DEMAND parentheses here either.
496 setstrstatus(putn(expr(&v
)));
498 stderror(ERR_NAME
| ERR_EXPRESSION
);
504 /* Always close, why only on ttys? */
510 doforeach(Char
**v
, struct command
*c
)
520 stderror(ERR_NAME
| ERR_VARBEGIN
);
523 } while (alnum(*cp
));
525 stderror(ERR_NAME
| ERR_VARALNUM
);
527 if (v
[0][0] != '(' || v
[blklen(v
) - 1][0] != ')')
528 stderror(ERR_NAME
| ERR_NOPAREN
);
532 v
= globall(v
, gflag
);
533 if (v
== 0 && !noexec
)
534 stderror(ERR_NAME
| ERR_NOMATCH
);
540 nwp
= xcalloc(1, sizeof *nwp
);
541 nwp
->w_fe
= nwp
->w_fe0
= v
;
542 btell(&nwp
->w_start
);
543 nwp
->w_fename
= Strsave(cp
);
544 nwp
->w_next
= whyles
;
545 nwp
->w_end
.type
= TCSH_F_SEEK
;
548 * Pre-read the loop so as to be more comprehensible to a terminal user.
559 dowhile(Char
**v
, struct command
*c
)
562 int again
= whyles
!= 0 &&
563 SEEKEQ(&whyles
->w_start
, &lineloc
) &&
564 whyles
->w_fename
== 0;
569 * Implement prereading here also, taking care not to evaluate the
570 * expression before the loop has been read up from a terminal.
574 else if (intty
&& !again
)
575 status
= !exp0(&v
, 1);
579 stderror(ERR_NAME
| ERR_EXPRESSION
);
581 struct whyle
*nwp
= xcalloc(1, sizeof(*nwp
));
583 nwp
->w_start
= lineloc
;
584 nwp
->w_end
.type
= TCSH_F_SEEK
;
585 nwp
->w_end
.f_seek
= 0;
586 nwp
->w_end
.a_seek
= 0;
587 nwp
->w_next
= whyles
;
600 /* We ain't gonna loop no more, no more! */
607 int old_pintr_disabled
;
609 whyles
->w_end
.type
= TCSH_I_SEEK
;
611 pintr_push_enable(&old_pintr_disabled
);
612 search(TC_BREAK
, 0, NULL
); /* read the expression in */
614 cleanup_until(&old_pintr_disabled
);
615 btell(&whyles
->w_end
);
620 doend(Char
**v
, struct command
*c
)
625 stderror(ERR_NAME
| ERR_NOTWHILE
);
626 btell(&whyles
->w_end
);
633 docontin(Char
**v
, struct command
*c
)
638 stderror(ERR_NAME
| ERR_NOTWHILE
);
646 /* Repeating a while is simple */
647 if (whyles
->w_fename
== 0) {
648 bseek(&whyles
->w_start
);
652 * The foreach variable list actually has a spurious word ")" at the end of
653 * the w_fe list. Thus we are at the of the list if one word beyond this
656 if (!whyles
->w_fe
[1]) {
660 setv(whyles
->w_fename
, quote(Strsave(*whyles
->w_fe
++)), VAR_READWRITE
);
661 bseek(&whyles
->w_start
);
665 dorepeat(Char
**v
, struct command
*kp
)
672 } while (v
[0] != NULL
&& Strcmp(v
[0], STRrepeat
) == 0);
678 cleanup_push(&pintr_disabled
, disabled_cleanup
);
681 if (setintr
&& pintr_disabled
== 1) {
682 cleanup_until(&pintr_disabled
);
684 cleanup_push(&pintr_disabled
, disabled_cleanup
);
689 if (setintr
&& pintr_disabled
== 1)
690 cleanup_until(&pintr_disabled
);
696 doswbrk(Char
**v
, struct command
*c
)
701 search(TC_BRKSW
, 0, NULL
);
707 struct srch
*sp
, *sp1
, *sp2
;
711 * Ignore keywords inside heredocs
717 * Binary search Sp1 is the beginning of the current search range. Sp2 is
720 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
721 sp
= sp1
+ ((sp2
- sp1
) >> 1);
722 if ((i
= *cp
- *sp
->s_name
) == 0 &&
723 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
736 struct srch
*sp
, *sp2
;
738 for (sp
= srchn
, sp2
= srchn
+ nsrchn
; sp
< sp2
; sp
++)
739 if (sp
->s_value
== n
)
749 search(int type
, int level
, Char
*goal
)
751 struct Strbuf word
= Strbuf_INIT
;
755 struct wordent
*histent
= NULL
, *ohistent
= NULL
;
759 if (type
== TC_GOTO
) {
761 a
.type
= TCSH_F_SEEK
;
766 cleanup_push(&word
, Strbuf_cleanup
);
770 histent
= xmalloc(sizeof(*histent
));
771 ohistent
= xmalloc(sizeof(*histent
));
772 ohistent
->word
= STRNULL
;
773 ohistent
->next
= histent
;
774 histent
->prev
= ohistent
;
777 if (intty
&& fseekp
== feobp
&& aret
== TCSH_F_SEEK
)
778 printprompt(1, isrchx(type
== TC_BREAK
? zlast
: type
));
779 /* xprintf("? "), flush(); */
780 (void) getword(&word
);
781 Strbuf_terminate(&word
);
783 if (intty
&& Strlen(word
.s
) > 0) {
784 histent
->word
= Strsave(word
.s
);
785 histent
->next
= xmalloc(sizeof(*histent
));
786 histent
->next
->prev
= histent
;
787 histent
= histent
->next
;
790 switch (srchx(word
.s
)) {
793 if (level
== 0 && type
== TC_IF
)
798 while (getword(&word
)) {
800 histent
->word
= Strsave(word
.s
);
801 histent
->next
= xmalloc(sizeof(*histent
));
802 histent
->next
->prev
= histent
;
803 histent
= histent
->next
;
808 if ((type
== TC_IF
|| type
== TC_ELSE
) &&
814 if (type
== TC_IF
|| type
== TC_ELSE
)
821 if (type
== TC_BREAK
)
826 if (type
== TC_BRKSW
) {
835 if (type
== TC_BREAK
)
841 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
846 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
851 if (type
== TC_GOTO
&& getword(&word
) && eq(word
.s
, goal
))
856 if (type
!= TC_GOTO
&& (type
!= TC_SWITCH
|| level
!= 0))
858 if (word
.len
== 0 || word
.s
[word
.len
- 1] != ':')
860 word
.s
[--word
.len
] = 0;
861 if ((type
== TC_GOTO
&& eq(word
.s
, goal
)) ||
862 (type
== TC_SWITCH
&& eq(word
.s
, STRdefault
)))
867 if (type
!= TC_SWITCH
|| level
!= 0)
869 (void) getword(&word
);
870 if (word
.len
!= 0 && word
.s
[word
.len
- 1] == ':')
871 word
.s
[--word
.len
] = 0;
872 cp
= strip(Dfix1(word
.s
));
873 cleanup_push(cp
, xfree
);
874 if (Gmatch(goal
, cp
))
880 if (type
== TC_SWITCH
&& level
== 0)
885 ohistent
->prev
= histgetword(histent
);
886 ohistent
->prev
->next
= ohistent
;
887 savehist(ohistent
, 0);
891 (void) getword(NULL
);
892 } while (level
>= 0);
894 cleanup_until(&word
);
897 static struct wordent
*
898 histgetword(struct wordent
*histent
)
904 tmp
= xmalloc(sizeof(*tmp
));
912 Strbuf_terminate (tmp
);
913 while (c
== ' ' || c
== '\t')
918 while (c
!= CHAR_ERR
&& c
!= '\n');
928 if (c
== '\\' && !e
) {
929 if ((c
= readc(1)) == '\n') {
937 if ((c
== '\'' || c
== '"') && !e
) {
946 Strbuf_append1(tmp
, (Char
) c
);
948 if (!first
&& !d
&& c
== '(' && !e
) {
952 } while (d
|| e
|| (c
!= ' ' && c
!= '\t' && c
!= '\n'));
955 Strbuf_terminate(tmp
);
956 histent
->word
= Strsave(tmp
->s
);
957 histent
->next
= xmalloc(sizeof (*histent
));
958 histent
->next
->prev
= histent
;
959 histent
= histent
->next
;
964 Strbuf_append1(tmp
, (Char
) c
);
965 Strbuf_terminate(tmp
);
966 histent
->word
= Strsave(tmp
->s
);
975 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
979 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
984 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
988 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
992 setname(short2str(Sgoal
));
993 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1004 getword(struct Strbuf
*wp
)
1006 int found
= 0, first
;
1014 while (c
== ' ' || c
== '\t')
1019 while (c
!= CHAR_ERR
&& c
!= '\n');
1032 if (c
== '\\' && (c
= readc(1)) == '\n')
1034 if (c
== '\'' || c
== '"') {
1043 Strbuf_append1(wp
, (Char
) c
);
1044 if (!d
&& c
== ')') {
1050 Strbuf_terminate(wp
);
1055 if (!first
&& !d
&& c
== '(') {
1062 } while ((d
|| (c
!= ' ' && c
!= '\t')) && c
!= '\n');
1069 Strbuf_terminate(wp
);
1078 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
1082 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
1087 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
1091 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
1095 setname(short2str(Sgoal
));
1096 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1109 if (whyles
->w_end
.type
== TCSH_F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
1110 search(TC_BREAK
, 0, NULL
);
1111 btell(&whyles
->w_end
);
1112 whyles
->w_end
.f_seek
--;
1115 bseek(&whyles
->w_end
);
1121 wpfree(struct whyle
*wp
)
1125 xfree(wp
->w_fename
);
1135 nwp
= NULL
; /* sun lint is dumb! */
1139 static const char foo
[] = "IAFE";
1145 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
1146 foo
[o
.type
+ 1], o
.a_seek
, o
.f_seek
);
1149 for (; whyles
; whyles
= nwp
) {
1150 struct whyle
*wp
= whyles
;
1154 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1155 foo
[wp
->w_start
.type
+1],
1156 wp
->w_start
.a_seek
, wp
->w_start
.f_seek
);
1157 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1158 foo
[wp
->w_end
.type
+ 1], wp
->w_end
.a_seek
, wp
->w_end
.f_seek
);
1162 * XXX: We free loops that have different seek types.
1164 if (wp
->w_end
.type
!= TCSH_I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
1165 wp
->w_start
.type
== o
.type
) {
1166 if (wp
->w_end
.type
== TCSH_F_SEEK
) {
1167 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
1168 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
1172 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
1173 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
1184 doecho(Char
**v
, struct command
*c
)
1192 doglob(Char
**v
, struct command
*c
)
1200 xecho(int sep
, Char
**v
)
1202 Char
**globbed
= NULL
;
1205 int echo_style
= ECHO_STYLE
;
1208 if ((vp
= adrof(STRecho_style
)) != NULL
&& vp
->vec
!= NULL
&&
1209 vp
->vec
[0] != NULL
) {
1210 if (Strcmp(vp
->vec
[0], STRbsd
) == 0)
1211 echo_style
= BSD_ECHO
;
1212 else if (Strcmp(vp
->vec
[0], STRsysv
) == 0)
1213 echo_style
= SYSV_ECHO
;
1214 else if (Strcmp(vp
->vec
[0], STRboth
) == 0)
1215 echo_style
= BOTH_ECHO
;
1216 else if (Strcmp(vp
->vec
[0], STRnone
) == 0)
1217 echo_style
= NONE_ECHO
;
1224 int old_pintr_disabled
;
1225 pintr_push_enable(&old_pintr_disabled
);
1226 v
= glob_all_or_error(v
);
1227 cleanup_until(&old_pintr_disabled
);
1229 v
= glob_all_or_error(v
);
1232 if (globbed
!= NULL
)
1233 cleanup_push(globbed
, blk_cleanup
);
1235 if ((echo_style
& BSD_ECHO
) != 0 && sep
== ' ' && *v
&& eq(*v
, STRmn
))
1238 while ((cp
= *v
++) != 0) {
1242 int old_pintr_disabled
;
1244 pintr_push_enable(&old_pintr_disabled
);
1245 cleanup_until(&old_pintr_disabled
);
1247 for (; (c
= *cp
) != 0; cp
++) {
1248 if ((echo_style
& SYSV_ECHO
) != 0 && c
== '\\') {
1249 if ((c
= parseescape(&cp
, FALSE
)) == CHAR_ERR
)
1252 xputwchar(c
| QUOTE
);
1255 xputchar(sep
| QUOTE
);
1258 if (sep
&& nonl
== 0)
1262 if (globbed
!= NULL
)
1263 cleanup_until(globbed
);
1266 /* check whether an environment variable should invoke 'set_locale()' */
1268 islocale_var(Char
*var
)
1270 static Char
*locale_vars
[] = {
1271 STRLANG
, STRLC_ALL
, STRLC_CTYPE
, STRLC_NUMERIC
,
1272 STRLC_TIME
, STRLC_COLLATE
, STRLC_MESSAGES
, STRLC_MONETARY
, 0
1276 for (v
= locale_vars
; *v
; ++v
)
1283 xlate_cr_cleanup(void *dummy
)
1291 doprintenv(Char
**v
, struct command
*c
)
1301 cleanup_push(&xlate_cr
, xlate_cr_cleanup
);
1302 for (ep
= STR_environ
; *ep
; ep
++) {
1304 int old_pintr_disabled
;
1306 pintr_push_enable(&old_pintr_disabled
);
1307 cleanup_until(&old_pintr_disabled
);
1309 xprintf("%" TCSH_S
"\n", *ep
);
1311 cleanup_until(&xlate_cr
);
1313 else if ((e
= tgetenv(*v
)) != NULL
) {
1316 old_output_raw
= output_raw
;
1318 cleanup_push(&old_output_raw
, output_raw_restore
);
1319 xprintf("%" TCSH_S
"\n", e
);
1320 cleanup_until(&old_output_raw
);
1326 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1327 (and anything else with a modern compiler) */
1331 dosetenv(Char
**v
, struct command
*c
)
1345 stderror(ERR_NAME
| ERR_VARBEGIN
);
1348 } while (alnum(*lp
) || *lp
== '.');
1350 stderror(ERR_NAME
| ERR_VARALNUM
);
1352 if ((lp
= *v
++) == 0)
1355 lp
= globone(lp
, G_APPEND
);
1356 cleanup_push(lp
, xfree
);
1358 if (eq(vp
, STRKPATH
)) {
1366 if (eq(vp
, STRSYSTYPE
)) {
1373 /* dspkanji/dspmbyte autosetting */
1374 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1375 #if defined(DSPMBYTE)
1376 if (eq(vp
, STRLANG
) && !adrof(CHECK_MBYTEVAR
)) {
1377 autoset_dspmbyte(lp
);
1381 if (islocale_var(vp
)) {
1385 # ifdef SETLOCALEBUG
1387 # endif /* SETLOCALEBUG */
1388 (void) setlocale(LC_ALL
, "");
1390 (void) setlocale(LC_COLLATE
, "");
1393 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1394 # endif /* LC_CTYPE */
1395 # if defined(AUTOSET_KANJI)
1397 # endif /* AUTOSET_KANJI */
1398 # ifdef NLS_CATALOGS
1400 (void) setlocale(LC_MESSAGES
, "");
1401 # endif /* LC_MESSAGES */
1404 # endif /* NLS_CATALOGS */
1405 # ifdef SETLOCALEBUG
1407 # endif /* SETLOCALEBUG */
1410 # endif /* STRCOLLBUG */
1411 tw_cmd_free(); /* since the collation sequence has changed */
1412 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1414 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1418 NLSMapsAreInited
= 0;
1420 if (MapsAreInited
&& !NLSMapsAreInited
)
1427 if (eq(vp
, STRNLSPATH
)) {
1433 if (eq(vp
, STRNOREBIND
)) {
1436 NLSMapsAreInited
= 0;
1442 if (eq(vp
, STRtcshlang
)) {
1447 #endif /* WINNT_NATIVE */
1448 if (eq(vp
, STRKTERM
)) {
1451 setv(STRterm
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1455 if (noediting
&& strcmp(t
, "unknown") != 0 && strcmp(t
,"dumb") != 0) {
1465 if (eq(vp
, STRKHOME
)) {
1468 * convert to canonical pathname (possibly resolving symlinks)
1471 canon
= dcanon(lp
, lp
);
1472 cleanup_push(canon
, xfree
);
1473 setv(STRhome
, quote(canon
), VAR_READWRITE
); /* lp memory used here */
1474 cleanup_ignore(canon
);
1475 cleanup_until(canon
);
1477 /* fix directory stack for new tilde home */
1482 if (eq(vp
, STRKSHLVL
)) {
1483 setv(STRshlvl
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1489 if (eq(vp
, STRKUSER
)) {
1490 setv(STRuser
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1496 if (eq(vp
, STRKGROUP
)) {
1497 setv(STRgroup
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1504 if (eq(vp
, STRLS_COLORS
)) {
1509 if (eq(vp
, STRLSCOLORS
)) {
1514 #endif /* COLOR_LS_F */
1518 * Load/Update $LINES $COLUMNS
1520 if ((eq(lp
, STRNULL
) && (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
))) ||
1521 eq(vp
, STRTERMCAP
)) {
1523 check_window_size(1);
1528 * Change the size to the one directed by $LINES and $COLUMNS
1530 if (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
)) {
1538 #endif /* SIG_WINDOW */
1544 dounsetenv(Char
**v
, struct command
*c
)
1546 Char
**ep
, *p
, *n
, *name
;
1551 * Find the longest environment variable
1553 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1554 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
1560 name
= xmalloc((maxi
+ 1) * sizeof(Char
));
1561 cleanup_push(name
, xfree
);
1564 for (maxi
= 1; maxi
;)
1565 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1566 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
1569 if (!Gmatch(name
, *v
))
1573 /* Unset the name. This wasn't being done until
1574 * later but most of the stuff following won't
1575 * work (particularly the setlocale() and getenv()
1576 * stuff) as intended until the name is actually
1581 if (eq(name
, STRNOREBIND
)) {
1584 NLSMapsAreInited
= 0;
1588 else if (eq(name
, STRSYSTYPE
))
1591 else if (islocale_var(name
)) {
1595 # ifdef SETLOCALEBUG
1597 # endif /* SETLOCALEBUG */
1598 (void) setlocale(LC_ALL
, "");
1600 (void) setlocale(LC_COLLATE
, "");
1603 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1604 # endif /* LC_CTYPE */
1605 # ifdef NLS_CATALOGS
1607 (void) setlocale(LC_MESSAGES
, "");
1608 # endif /* LC_MESSAGES */
1611 # endif /* NLS_CATALOGS */
1612 # ifdef SETLOCALEBUG
1614 # endif /* SETLOCALEBUG */
1617 # endif /* STRCOLLBUG */
1618 tw_cmd_free();/* since the collation sequence has changed */
1619 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1621 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1623 AsciiOnly
= getenv("LANG") == NULL
&&
1624 getenv("LC_CTYPE") == NULL
;
1626 NLSMapsAreInited
= 0;
1628 if (MapsAreInited
&& !NLSMapsAreInited
)
1633 else if (eq(name
,(STRtcshlang
))) {
1637 #endif /* WINNT_NATIVE */
1639 else if (eq(name
, STRLS_COLORS
))
1641 else if (eq(name
, STRLSCOLORS
))
1643 #endif /* COLOR_LS_F */
1645 else if (eq(name
, STRNLSPATH
)) {
1651 * start again cause the environment changes
1655 cleanup_until(name
);
1659 tsetenv(const Char
*name
, const Char
*val
)
1661 #ifdef SETENV_IN_LIB
1663 * XXX: This does not work right, since tcsh cannot track changes to
1664 * the environment this way. (the builtin setenv without arguments does
1665 * not print the right stuff neither does unsetenv). This was for Mach,
1666 * it is not needed anymore.
1673 cname
= strsave(short2str(name
));
1674 setenv(cname
, short2str(val
), 1);
1676 #else /* !SETENV_IN_LIB */
1677 Char
**ep
= STR_environ
;
1684 nt_set_env(name
,val
);
1685 #endif /* WINNT_NATIVE */
1688 for (ccp
= name
, dp
= *ep
; *ccp
&& Tolower(*ccp
& TRIM
) == Tolower(*dp
);
1691 for (ccp
= name
, dp
= *ep
; *ccp
&& (*ccp
& TRIM
) == *dp
; ccp
++, dp
++)
1692 #endif /* WINNT_NATIVE */
1694 if (*ccp
!= 0 || *dp
!= '=')
1696 cp
= Strspl(STRequal
, val
);
1698 *ep
= strip(Strspl(name
, cp
));
1700 blkfree((Char
**) environ
);
1701 environ
= short2blk(STR_environ
);
1704 cp
= Strspl(name
, STRequal
);
1705 blk
[0] = strip(Strspl(cp
, val
));
1708 STR_environ
= blkspl(STR_environ
, blk
);
1709 blkfree((Char
**) environ
);
1710 environ
= short2blk(STR_environ
);
1712 #endif /* SETENV_IN_LIB */
1716 Unsetenv(Char
*name
)
1718 Char
**ep
= STR_environ
;
1723 nt_set_env(name
,NULL
);
1724 #endif /*WINNT_NATIVE */
1726 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1728 if (*cp
!= 0 || *dp
!= '=')
1732 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1733 blkfree((Char
**) environ
);
1734 environ
= short2blk(STR_environ
);
1744 doumask(Char
**v
, struct command
*c
)
1757 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1758 i
= i
* 8 + *cp
++ - '0';
1759 if (*cp
|| i
< 0 || i
> 0777)
1760 stderror(ERR_NAME
| ERR_MASK
);
1766 typedef long RLIM_TYPE
;
1767 # ifdef _OSD_POSIX /* BS2000 */
1768 # include <ulimit.h>
1770 # ifndef RLIM_INFINITY
1771 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1772 extern RLIM_TYPE
ulimit();
1773 # endif /* ! _MINIX && !__clipper__ */
1774 # define RLIM_INFINITY 0x003fffff
1775 # define RLIMIT_FSIZE 1
1776 # endif /* RLIM_INFINITY */
1778 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1779 # define RLIMIT_DATA 3
1780 # define RLIMIT_STACK 1005
1782 # define toset(a) ((a) + 1)
1784 # else /* BSDLIMIT */
1785 # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
1786 typedef rlim_t RLIM_TYPE
;
1788 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1789 typedef rlim_t RLIM_TYPE
;
1792 typedef long long RLIM_TYPE
;
1794 typedef unsigned long RLIM_TYPE
;
1796 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1797 # endif /* BSD4_4 && !__386BSD__ */
1798 # endif /* BSDLIMIT */
1800 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
1801 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1802 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1804 # define RLIMIT_CPU 0
1805 # define RLIMIT_FSIZE 1
1806 # define RLIMIT_DATA 2
1807 # define RLIMIT_STACK 3
1808 # define RLIMIT_CORE 4
1809 # define RLIMIT_RSS 5
1810 # define RLIMIT_NOFILE 6
1811 # endif /* RLIMIT_CPU */
1812 # ifndef RLIM_INFINITY
1813 # define RLIM_INFINITY 0x7fffffff
1814 # endif /* RLIM_INFINITY */
1816 * old versions of HP/UX counted limits in 512 bytes
1819 # define FILESIZE512
1820 # endif /* SIGRTMIN */
1821 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
1823 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1824 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1825 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1826 /* than include both and get warnings, we define the extra SVR4 limits here. */
1827 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1828 /* RLIMIT_VMEM based on it? */
1829 # ifndef RLIMIT_VMEM
1830 # define RLIMIT_VMEM 6
1833 # define RLIMIT_AS RLIMIT_VMEM
1835 # endif /* SYSVREL > 3 && BSDLIMIT */
1837 # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__))
1838 # if defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1839 # define RLIMIT_VMEM RLIMIT_AS
1842 * Oh well, <asm-generic/resource.h> has it, but <bits/resource.h> does not
1843 * Linux headers: When the left hand does not know what the right hand does.
1845 # if defined(RLIMIT_RTPRIO) && !defined(RLIMIT_RTTIME)
1846 # define RLIMIT_RTTIME (RLIMIT_RTPRIO + 1)
1850 struct limits limits
[] =
1853 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1854 # endif /* RLIMIT_CPU */
1856 # ifdef RLIMIT_FSIZE
1858 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1860 { RLIMIT_FSIZE
, "filesize", 512, "blocks" },
1862 # endif /* RLIMIT_FSIZE */
1865 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1866 # endif /* RLIMIT_DATA */
1868 # ifdef RLIMIT_STACK
1870 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1872 { RLIMIT_STACK
, "stacksize", 1024 * 1024, "kbytes"},
1874 # endif /* RLIMIT_STACK */
1877 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1878 # endif /* RLIMIT_CORE */
1881 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1882 # endif /* RLIMIT_RSS */
1885 { RLIMIT_UMEM
, "memoryuse", 1024, "kbytes" },
1886 # endif /* RLIMIT_UMEM */
1889 { RLIMIT_VMEM
, "vmemoryuse", 1024, "kbytes" },
1890 # endif /* RLIMIT_VMEM */
1892 # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
1893 { RLIMIT_HEAP
, "heapsize", 1024, "kbytes" },
1894 # endif /* RLIMIT_HEAP */
1896 # ifdef RLIMIT_NOFILE
1897 { RLIMIT_NOFILE
, "descriptors", 1, "" },
1898 # endif /* RLIMIT_NOFILE */
1901 { RLIMIT_NPTS
, "pseudoterminals", 1, "" },
1902 # endif /* RLIMIT_NPTS */
1904 # ifdef RLIMIT_KQUEUES
1905 { RLIMIT_KQUEUES
, "kqueues", 1, "" },
1906 # endif /* RLIMIT_KQUEUES */
1908 # ifdef RLIMIT_CONCUR
1909 { RLIMIT_CONCUR
, "concurrency", 1, "thread(s)" },
1910 # endif /* RLIMIT_CONCUR */
1912 # ifdef RLIMIT_MEMLOCK
1913 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1914 # endif /* RLIMIT_MEMLOCK */
1916 # ifdef RLIMIT_NPROC
1917 { RLIMIT_NPROC
, "maxproc", 1, "" },
1918 # endif /* RLIMIT_NPROC */
1921 { RLIMIT_NTHR
, "maxthread", 1, "" },
1922 # endif /* RLIMIT_NTHR */
1924 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1925 { RLIMIT_OFILE
, "openfiles", 1, "" },
1926 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1928 # ifdef RLIMIT_SBSIZE
1929 { RLIMIT_SBSIZE
, "sbsize", 1, "" },
1930 # endif /* RLIMIT_SBSIZE */
1933 { RLIMIT_SWAP
, "swapsize", 1024, "kbytes" },
1934 # endif /* RLIMIT_SWAP */
1936 # ifdef RLIMIT_LOCKS
1937 { RLIMIT_LOCKS
, "maxlocks", 1, "" },
1938 # endif /* RLIMIT_LOCKS */
1940 # ifdef RLIMIT_POSIXLOCKS
1941 { RLIMIT_POSIXLOCKS
,"posixlocks", 1, "" },
1942 # endif /* RLIMIT_POSIXLOCKS */
1944 # ifdef RLIMIT_SIGPENDING
1945 { RLIMIT_SIGPENDING
,"maxsignal", 1, "" },
1946 # endif /* RLIMIT_SIGPENDING */
1948 # ifdef RLIMIT_MSGQUEUE
1949 { RLIMIT_MSGQUEUE
, "maxmessage", 1, "" },
1950 # endif /* RLIMIT_MSGQUEUE */
1953 { RLIMIT_NICE
, "maxnice", 1, "" },
1954 # endif /* RLIMIT_NICE */
1956 # ifdef RLIMIT_RTPRIO
1957 { RLIMIT_RTPRIO
, "maxrtprio", 1, "" },
1958 # endif /* RLIMIT_RTPRIO */
1960 # ifdef RLIMIT_RTTIME
1961 { RLIMIT_RTTIME
, "maxrttime", 1, "usec" },
1962 # endif /* RLIMIT_RTTIME */
1964 { -1, NULL
, 0, NULL
}
1967 static struct limits
*findlim (Char
*);
1968 static RLIM_TYPE
getval (struct limits
*, Char
**);
1969 static int strtail (Char
*, const char *);
1970 static void limtail (Char
*, const char *);
1971 static void limtail2 (Char
*, const char *, const char *);
1972 static void plim (struct limits
*, int);
1973 static int setlim (struct limits
*, int, RLIM_TYPE
);
1977 restrict_limit(double value
)
1980 * is f too large to cope with? return the maximum or minimum int
1982 if (value
> (double) INT_MAX
)
1983 return (RLIM_TYPE
) INT_MAX
;
1984 else if (value
< (double) INT_MIN
)
1985 return (RLIM_TYPE
) INT_MIN
;
1987 return (RLIM_TYPE
) value
;
1990 # define restrict_limit(x) ((RLIM_TYPE) (x))
1994 static struct limits
*
1997 struct limits
*lp
, *res
;
2000 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2001 if (prefix(cp
, str2short(lp
->limname
))) {
2003 stderror(ERR_NAME
| ERR_AMBIG
);
2008 stderror(ERR_NAME
| ERR_LIMIT
);
2015 dolimit(Char
**v
, struct command
*c
)
2023 if (*v
&& eq(*v
, STRmh
)) {
2028 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2037 limit
= getval(lp
, v
+ 1);
2038 if (setlim(lp
, hard
, limit
) < 0)
2039 stderror(ERR_SILENT
);
2043 getval(struct limits
*lp
, Char
**v
)
2048 f
= atof(short2str(cp
));
2052 * is f too large to cope with. limit f to minint, maxint - X-6768 by
2055 if ((f
< (double) INT_MIN
) || (f
> (double) INT_MAX
)) {
2056 stderror(ERR_NAME
| ERR_TOOLARGE
);
2058 # endif /* convex */
2060 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
2064 return restrict_limit((f
* lp
->limdiv
) + 0.5);
2070 if (lp
->limconst
!= RLIMIT_CPU
)
2072 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
* 60.0 + atof(short2str(cp
+ 1))));
2074 if (lp
->limconst
!= RLIMIT_CPU
)
2076 limtail(cp
, "hours");
2079 # endif /* RLIMIT_CPU */
2082 if (lp
->limconst
== RLIMIT_CPU
) {
2083 limtail(cp
, "minutes");
2087 # endif /* RLIMIT_CPU */
2088 limtail2(cp
, "megabytes", "mbytes");
2089 f
*= 1024.0 * 1024.0;
2093 if (lp
->limconst
!= RLIMIT_CPU
)
2095 limtail(cp
, "seconds");
2097 # endif /* RLIMIT_CPU */
2103 if (lp
->limconst
== RLIMIT_CPU
)
2105 # endif /* RLIMIT_CPU */
2106 limtail2(cp
, "gigabytes", "gbytes");
2107 f
*= 1024.0 * 1024.0 * 1024.0;
2111 if (lp
->limconst
== RLIMIT_CPU
)
2113 # endif /* RLIMIT_CPU */
2115 limtail2(cp
, "megabytes", "mbytes");
2116 f
*= 1024.0 * 1024.0;
2120 if (lp
->limconst
== RLIMIT_CPU
)
2122 # endif /* RLIMIT_CPU */
2123 limtail2(cp
, "kilobytes", "kbytes");
2128 if (lp
->limconst
== RLIMIT_CPU
)
2130 # endif /* RLIMIT_CPU */
2131 limtail(cp
, "blocks");
2135 limtail(cp
, "unlimited");
2136 return ((RLIM_TYPE
) RLIM_INFINITY
);
2140 # endif /* RLIMIT_CPU */
2141 stderror(ERR_NAME
| ERR_SCALEF
);
2144 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
+ 0.5));
2147 if (f
> (float) ((RLIM_TYPE
) RLIM_INFINITY
))
2148 return ((RLIM_TYPE
) RLIM_INFINITY
);
2150 return ((RLIM_TYPE
) f
);
2151 # endif /* convex */
2155 strtail(Char
*cp
, const char *str
)
2157 while (*cp
&& *cp
== (Char
)*str
)
2159 return (*cp
!= '\0');
2163 limtail(Char
*cp
, const char *str
)
2165 if (strtail(cp
, str
))
2166 stderror(ERR_BADSCALE
, str
);
2170 limtail2(Char
*cp
, const char *str1
, const char *str2
)
2172 if (strtail(cp
, str1
) && strtail(cp
, str2
))
2173 stderror(ERR_BADSCALE
, str1
);
2178 plim(struct limits
*lp
, int hard
)
2182 # endif /* BSDLIMIT */
2184 int xdiv
= lp
->limdiv
;
2186 xprintf("%-13.13s", lp
->limname
);
2189 limit
= ulimit(lp
->limconst
, 0);
2191 if (lp
->limconst
== RLIMIT_DATA
)
2192 limit
-= 0x20000000;
2194 # else /* BSDLIMIT */
2195 (void) getrlimit(lp
->limconst
, &rlim
);
2196 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
2197 # endif /* BSDLIMIT */
2199 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2201 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2202 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2204 if (lp
->limconst
== RLIMIT_FSIZE
) {
2205 if (limit
>= (RLIM_INFINITY
/ 512))
2206 limit
= RLIM_INFINITY
;
2208 xdiv
= (xdiv
== 1024 ? 2 : 1);
2210 # endif /* !BSDLIMIT || FILESIZE512 */
2212 if (limit
== RLIM_INFINITY
)
2213 xprintf("unlimited");
2215 # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
2216 if (lp
->limconst
== RLIMIT_CPU
&&
2217 (unsigned long)limit
>= 0x7ffffffdUL
)
2218 xprintf("unlimited");
2222 if (lp
->limconst
== RLIMIT_CPU
)
2225 # endif /* RLIMIT_CPU */
2226 xprintf("%ld %s", (long) (limit
/ xdiv
), lp
->limscale
);
2232 dounlimit(Char
**v
, struct command
*c
)
2240 while (*++v
&& **v
== '-') {
2251 stderror(ERR_ULIMUS
);
2257 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2258 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0)
2261 stderror(ERR_SILENT
);
2266 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0 && !force
)
2267 stderror(ERR_SILENT
);
2272 setlim(struct limits
*lp
, int hard
, RLIM_TYPE limit
)
2277 (void) getrlimit(lp
->limconst
, &rlim
);
2280 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2281 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2283 # endif /* FILESIZE512 */
2285 rlim
.rlim_max
= limit
;
2286 else if (limit
== RLIM_INFINITY
&& euid
!= 0)
2287 rlim
.rlim_cur
= rlim
.rlim_max
;
2289 rlim
.rlim_cur
= limit
;
2291 if (rlim
.rlim_cur
> rlim
.rlim_max
)
2292 rlim
.rlim_max
= rlim
.rlim_cur
;
2294 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
2295 # else /* BSDLIMIT */
2296 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2299 if (lp
->limconst
== RLIMIT_DATA
)
2300 limit
+= 0x20000000;
2302 if (ulimit(toset(lp
->limconst
), limit
) < 0) {
2303 # endif /* BSDLIMIT */
2308 op
= strsave(limit
== RLIM_INFINITY
? CGETS(15, 2, "remove") :
2309 CGETS(15, 3, "set"));
2310 cleanup_push(op
, xfree
);
2311 type
= strsave(hard
? CGETS(15, 4, " hard") : "");
2312 cleanup_push(type
, xfree
);
2313 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname
,
2314 lp
->limname
, op
, type
, strerror(err
));
2321 #endif /* !HAVENOLIMIT */
2325 dosuspend(Char
**v
, struct command
*c
)
2328 struct sigaction old
;
2329 #endif /* BSDJOBS */
2335 stderror(ERR_SUSPLOG
);
2339 sigaction(SIGTSTP
, NULL
, &old
);
2340 signal(SIGTSTP
, SIG_DFL
);
2341 (void) kill(0, SIGTSTP
);
2342 /* the shell stops here */
2343 sigaction(SIGTSTP
, &old
, NULL
);
2344 #else /* !BSDJOBS */
2345 stderror(ERR_JOBCONTROL
);
2346 #endif /* BSDJOBS */
2350 if (grabpgrp(FSHTTY
, opgrp
) == -1)
2351 stderror(ERR_SYSTEM
, "tcgetpgrp", strerror(errno
));
2352 (void) setpgid(0, shpgrp
);
2353 (void) tcsetpgrp(FSHTTY
, shpgrp
);
2355 #endif /* BSDJOBS */
2356 (void) setdisc(FSHTTY
);
2359 /* This is the dreaded EVAL built-in.
2360 * If you don't fiddle with file descriptors, and reset didfds,
2361 * this command will either ignore redirection inside or outside
2362 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2363 * The stuff here seems to work, but I did it by trial and error rather
2364 * than really knowing what was going on. If tpgrp is zero, we are
2365 * probably a background eval, e.g. "eval date &", and we want to
2366 * make sure that any processes we start stay in our pgrp.
2367 * This is also the case for "time eval date" -- stay in same pgrp.
2368 * Otherwise, under stty tostop, processes will stop in the wrong
2369 * pgrp, with no way for the shell to get them going again. -IAN!
2374 Char
**evalvec
, *evalp
;
2376 #ifndef CLOSE_ON_EXEC
2379 int saveIN
, saveOUT
, saveDIAG
;
2380 int SHIN
, SHOUT
, SHDIAG
;
2384 doeval_cleanup(void *xstate
)
2386 struct doeval_state
*state
;
2389 evalvec
= state
->evalvec
;
2390 evalp
= state
->evalp
;
2392 #ifndef CLOSE_ON_EXEC
2393 didcch
= state
->didcch
;
2394 #endif /* CLOSE_ON_EXEC */
2395 didfds
= state
->didfds
;
2396 if (state
->saveIN
!= SHIN
)
2398 if (state
->saveOUT
!= SHOUT
)
2400 if (state
->saveDIAG
!= SHDIAG
)
2402 close_on_exec(SHIN
= dmove(state
->saveIN
, state
->SHIN
), 1);
2403 close_on_exec(SHOUT
= dmove(state
->saveOUT
, state
->SHOUT
), 1);
2404 close_on_exec(SHDIAG
= dmove(state
->saveDIAG
, state
->SHDIAG
), 1);
2406 close_on_exec(dcopy(SHIN
, 0), 1);
2407 close_on_exec(dcopy(SHOUT
, 1), 1);
2408 close_on_exec(dcopy(SHDIAG
, 2), 1);
2415 doeval(Char
**v
, struct command
*c
)
2417 struct doeval_state state
;
2418 int gflag
, my_reenter
;
2428 gv
= v
= globall(v
, gflag
);
2430 stderror(ERR_NOMATCH
);
2431 cleanup_push(gv
, blk_cleanup
);
2441 state
.evalvec
= evalvec
;
2442 state
.evalp
= evalp
;
2443 state
.didfds
= didfds
;
2444 #ifndef CLOSE_ON_EXEC
2445 state
.didcch
= didcch
;
2446 #endif /* CLOSE_ON_EXEC */
2448 state
.SHOUT
= SHOUT
;
2449 state
.SHDIAG
= SHDIAG
;
2451 (void)close_on_exec(state
.saveIN
= dcopy(SHIN
, -1), 1);
2452 (void)close_on_exec(state
.saveOUT
= dcopy(SHOUT
, -1), 1);
2453 (void)close_on_exec(state
.saveDIAG
= dcopy(SHDIAG
, -1), 1);
2455 cleanup_push(&state
, doeval_cleanup
);
2459 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
2461 my_reenter
= 1; /* assume non-zero return val */
2462 if (setexit() == 0) {
2463 my_reenter
= 0; /* Oh well, we were wrong */
2465 if ((my_reenter
= setexit()) == 0) {
2469 (void)close_on_exec(SHIN
= dcopy(0, -1), 1);
2470 (void)close_on_exec(SHOUT
= dcopy(1, -1), 1);
2471 (void)close_on_exec(SHDIAG
= dcopy(2, -1), 1);
2472 #ifndef CLOSE_ON_EXEC
2474 #endif /* CLOSE_ON_EXEC */
2481 if (my_reenter
== 0) {
2482 cleanup_until(&state
);
2489 stderror(ERR_SILENT
);
2492 /*************************************************************************/
2493 /* print list of builtin commands */
2496 lbuffed_cleanup (void *dummy
)
2504 dobuiltins(Char
**v
, struct command
*c
)
2506 /* would use print_by_column() in tw.parse.c but that assumes
2507 * we have an array of Char * to pass.. (sg)
2509 const struct biltins
*b
;
2510 int row
, col
, columns
, rows
;
2511 unsigned int w
, maxwidth
;
2515 lbuffed
= 0; /* turn off line buffering */
2516 cleanup_push(&lbuffed
, lbuffed_cleanup
);
2518 /* find widest string */
2519 for (maxwidth
= 0, b
= bfunc
; b
< &bfunc
[nbfunc
]; ++b
)
2520 maxwidth
= max(maxwidth
, strlen(b
->bname
));
2521 ++maxwidth
; /* for space */
2523 columns
= (TermH
+ 1) / maxwidth
; /* PWP: terminal size change */
2526 rows
= (nbfunc
+ (columns
- 1)) / columns
;
2528 for (b
= bfunc
, row
= 0; row
< rows
; row
++) {
2529 for (col
= 0; col
< columns
; col
++) {
2530 if (b
< &bfunc
[nbfunc
]) {
2531 w
= strlen(b
->bname
);
2532 xprintf("%s", b
->bname
);
2533 if (col
< (columns
- 1)) /* Not last column? */
2534 for (; w
< maxwidth
; w
++)
2539 if (row
< (rows
- 1)) {
2546 nt_print_builtins(maxwidth
);
2551 #endif /* WINNT_NATIVE */
2553 cleanup_until(&lbuffed
); /* turn back on line buffering */
2559 xcatgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2564 while ((res
= catgets(ctd
, set_id
, msg_id
, s
)) == s
&& errno
== EINTR
) {
2565 handle_pending_signals();
2572 # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2574 iconv_catgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2576 static char *buf
= NULL
;
2577 static size_t buf_size
= 0;
2579 char *orig
, *dest
, *p
;
2580 ICONV_CONST
char *src
;
2581 size_t src_size
, dest_size
;
2583 orig
= xcatgets(ctd
, set_id
, msg_id
, s
);
2584 if (catgets_iconv
== (iconv_t
)-1 || orig
== s
)
2587 src_size
= strlen(src
) + 1;
2588 if (buf
== NULL
&& (buf
= xmalloc(buf_size
= src_size
+ 32)) == NULL
)
2591 while (src_size
!= 0) {
2592 dest_size
= buf
+ buf_size
- dest
;
2593 if (iconv(catgets_iconv
, &src
, &src_size
, &dest
, &dest_size
)
2597 if ((p
= xrealloc(buf
, buf_size
* 2)) == NULL
)
2600 dest
= p
+ (dest
- buf
);
2604 case EILSEQ
: case EINVAL
: default:
2611 # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2612 #endif /* NLS_CATALOGS */
2618 static const char default_catalog
[] = "tcsh";
2620 char *catalog
= (char *)(intptr_t)default_catalog
;
2622 if (adrof(STRcatalog
) != NULL
)
2623 catalog
= xasprintf("tcsh.%s", short2str(varval(STRcatalog
)));
2624 #ifdef NL_CAT_LOCALE /* POSIX-compliant. */
2626 * Check if LC_MESSAGES is set in the environment and use it, if so.
2627 * If not, fall back to the setting of LANG.
2629 catd
= catopen(catalog
, tgetenv(STRLC_MESSAGES
) ? NL_CAT_LOCALE
: 0);
2630 #else /* pre-POSIX */
2631 # ifndef MCLoadBySet
2632 # define MCLoadBySet 0
2634 catd
= catopen(catalog
, MCLoadBySet
);
2636 if (catalog
!= default_catalog
)
2638 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2639 /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
2640 catgets_iconv
= iconv_open (nl_langinfo (CODESET
),
2641 xcatgets(catd
, 255, 1, "UTF-8"));
2642 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2643 #endif /* NLS_CATALOGS */
2646 #endif /* WINNT_NATIVE */
2647 errinit(); /* init the errorlist in correct locale */
2648 mesginit(); /* init the messages for signals */
2649 dateinit(); /* init the messages for dates */
2650 editinit(); /* init the editor messages */
2651 terminit(); /* init the termcap messages */
2658 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2659 if (catgets_iconv
!= (iconv_t
)-1) {
2660 iconv_close(catgets_iconv
);
2661 catgets_iconv
= (iconv_t
)-1;
2663 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2664 if (catd
!= (nl_catd
)-1) {
2666 * catclose can call other functions which can call longjmp
2667 * making us re-enter this code. Prevent infinite recursion
2668 * by resetting catd. Problem reported and solved by:
2671 nl_catd oldcatd
= catd
;
2673 while (catclose(oldcatd
) == -1 && errno
== EINTR
)
2674 handle_pending_signals();
2676 #endif /* NLS_CATALOGS */
2680 getYN(const char *prompt
)
2685 xprintf("%s", prompt
);
2687 (void) force_read(SHIN
, &c
, sizeof(c
));
2689 * Perhaps we should use the yesexpr from the
2692 doit
= (strchr(CGETS(22, 14, "Yy"), c
) != NULL
);
2693 while (c
!= '\n' && force_read(SHIN
, &c
, sizeof(c
)) == sizeof(c
))