1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.173 2015/05/04 17:10:45 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.173 2015/05/04 17:10:45 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 histent
->word
= Strsave(word
.s
);
805 histent
->next
= xmalloc(sizeof(*histent
));
806 histent
->next
->prev
= histent
;
807 histent
= histent
->next
;
812 if ((type
== TC_IF
|| type
== TC_ELSE
) &&
818 if (type
== TC_IF
|| type
== TC_ELSE
)
825 if (type
== TC_BREAK
)
830 if (type
== TC_BRKSW
) {
839 if (type
== TC_BREAK
)
845 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
850 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
855 if (type
== TC_GOTO
&& getword(&word
) && eq(word
.s
, goal
))
860 if (type
!= TC_GOTO
&& (type
!= TC_SWITCH
|| level
!= 0))
862 if (word
.len
== 0 || word
.s
[word
.len
- 1] != ':')
864 word
.s
[--word
.len
] = 0;
865 if ((type
== TC_GOTO
&& eq(word
.s
, goal
)) ||
866 (type
== TC_SWITCH
&& eq(word
.s
, STRdefault
)))
871 if (type
!= TC_SWITCH
|| level
!= 0)
873 (void) getword(&word
);
874 if (word
.len
!= 0 && word
.s
[word
.len
- 1] == ':')
875 word
.s
[--word
.len
] = 0;
876 cp
= strip(Dfix1(word
.s
));
877 cleanup_push(cp
, xfree
);
878 if (Gmatch(goal
, cp
))
884 if (type
== TC_SWITCH
&& level
== 0)
889 ohistent
->prev
= histgetword(histent
);
890 ohistent
->prev
->next
= ohistent
;
891 savehist(ohistent
, 0);
895 (void) getword(NULL
);
896 } while (level
>= 0);
898 cleanup_until(&word
);
901 static struct wordent
*
902 histgetword(struct wordent
*histent
)
908 tmp
= xmalloc(sizeof(*tmp
));
916 Strbuf_terminate (tmp
);
917 while (c
== ' ' || c
== '\t')
922 while (c
!= CHAR_ERR
&& c
!= '\n');
932 if (c
== '\\' && !e
) {
933 if ((c
= readc(1)) == '\n') {
941 if ((c
== '\'' || c
== '"') && !e
) {
950 Strbuf_append1(tmp
, (Char
) c
);
952 if (!first
&& !d
&& c
== '(' && !e
) {
956 } while (d
|| e
|| (c
!= ' ' && c
!= '\t' && c
!= '\n'));
959 Strbuf_terminate(tmp
);
960 histent
->word
= Strsave(tmp
->s
);
961 histent
->next
= xmalloc(sizeof (*histent
));
962 histent
->next
->prev
= histent
;
963 histent
= histent
->next
;
968 Strbuf_append1(tmp
, (Char
) c
);
969 Strbuf_terminate(tmp
);
970 histent
->word
= Strsave(tmp
->s
);
979 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
983 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
988 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
992 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
996 setname(short2str(Sgoal
));
997 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1008 getword(struct Strbuf
*wp
)
1010 int found
= 0, first
;
1018 while (c
== ' ' || c
== '\t')
1023 while (c
!= CHAR_ERR
&& c
!= '\n');
1036 if (c
== '\\' && (c
= readc(1)) == '\n')
1038 if (c
== '\'' || c
== '"') {
1047 Strbuf_append1(wp
, (Char
) c
);
1048 if (!first
&& !d
&& c
== '(') {
1055 } while ((d
|| (c
!= ' ' && c
!= '\t')) && c
!= '\n');
1062 Strbuf_terminate(wp
);
1071 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
1075 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
1080 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
1084 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
1088 setname(short2str(Sgoal
));
1089 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1102 if (whyles
->w_end
.type
== TCSH_F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
1103 search(TC_BREAK
, 0, NULL
);
1104 btell(&whyles
->w_end
);
1105 whyles
->w_end
.f_seek
--;
1108 bseek(&whyles
->w_end
);
1114 wpfree(struct whyle
*wp
)
1118 xfree(wp
->w_fename
);
1128 nwp
= NULL
; /* sun lint is dumb! */
1132 static const char foo
[] = "IAFE";
1138 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
1139 foo
[o
.type
+ 1], o
.a_seek
, o
.f_seek
);
1142 for (; whyles
; whyles
= nwp
) {
1143 struct whyle
*wp
= whyles
;
1147 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1148 foo
[wp
->w_start
.type
+1],
1149 wp
->w_start
.a_seek
, wp
->w_start
.f_seek
);
1150 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1151 foo
[wp
->w_end
.type
+ 1], wp
->w_end
.a_seek
, wp
->w_end
.f_seek
);
1155 * XXX: We free loops that have different seek types.
1157 if (wp
->w_end
.type
!= TCSH_I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
1158 wp
->w_start
.type
== o
.type
) {
1159 if (wp
->w_end
.type
== TCSH_F_SEEK
) {
1160 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
1161 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
1165 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
1166 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
1177 doecho(Char
**v
, struct command
*c
)
1185 doglob(Char
**v
, struct command
*c
)
1193 xecho(int sep
, Char
**v
)
1195 Char
*cp
, **globbed
= NULL
;
1197 int echo_style
= ECHO_STYLE
;
1200 if ((vp
= adrof(STRecho_style
)) != NULL
&& vp
->vec
!= NULL
&&
1201 vp
->vec
[0] != NULL
) {
1202 if (Strcmp(vp
->vec
[0], STRbsd
) == 0)
1203 echo_style
= BSD_ECHO
;
1204 else if (Strcmp(vp
->vec
[0], STRsysv
) == 0)
1205 echo_style
= SYSV_ECHO
;
1206 else if (Strcmp(vp
->vec
[0], STRboth
) == 0)
1207 echo_style
= BOTH_ECHO
;
1208 else if (Strcmp(vp
->vec
[0], STRnone
) == 0)
1209 echo_style
= NONE_ECHO
;
1216 int old_pintr_disabled
;
1217 pintr_push_enable(&old_pintr_disabled
);
1218 v
= glob_all_or_error(v
);
1219 cleanup_until(&old_pintr_disabled
);
1221 v
= glob_all_or_error(v
);
1224 if (globbed
!= NULL
)
1225 cleanup_push(globbed
, blk_cleanup
);
1227 if ((echo_style
& BSD_ECHO
) != 0 && sep
== ' ' && *v
&& eq(*v
, STRmn
))
1230 while ((cp
= *v
++) != 0) {
1234 int old_pintr_disabled
;
1236 pintr_push_enable(&old_pintr_disabled
);
1237 cleanup_until(&old_pintr_disabled
);
1239 while ((c
= *cp
++) != 0) {
1240 if ((echo_style
& SYSV_ECHO
) != 0 && c
== '\\') {
1241 switch (c
= *cp
++) {
1252 #if 0 /* Windows does not understand \e */
1255 c
= CTL_ESC('\033');
1278 if (*cp
>= '0' && *cp
< '8')
1279 c
= c
* 8 + *cp
++ - '0';
1280 if (*cp
>= '0' && *cp
< '8')
1281 c
= c
* 8 + *cp
++ - '0';
1282 if (*cp
>= '0' && *cp
< '8')
1283 c
= c
* 8 + *cp
++ - '0';
1290 xputchar('\\' | QUOTE
);
1294 xputwchar(c
| QUOTE
);
1298 xputchar(sep
| QUOTE
);
1301 if (sep
&& nonl
== 0)
1305 if (globbed
!= NULL
)
1306 cleanup_until(globbed
);
1309 /* check whether an environment variable should invoke 'set_locale()' */
1311 islocale_var(Char
*var
)
1313 static Char
*locale_vars
[] = {
1314 STRLANG
, STRLC_ALL
, STRLC_CTYPE
, STRLC_NUMERIC
,
1315 STRLC_TIME
, STRLC_COLLATE
, STRLC_MESSAGES
, STRLC_MONETARY
, 0
1319 for (v
= locale_vars
; *v
; ++v
)
1326 xlate_cr_cleanup(void *dummy
)
1334 doprintenv(Char
**v
, struct command
*c
)
1344 cleanup_push(&xlate_cr
, xlate_cr_cleanup
);
1345 for (ep
= STR_environ
; *ep
; ep
++) {
1347 int old_pintr_disabled
;
1349 pintr_push_enable(&old_pintr_disabled
);
1350 cleanup_until(&old_pintr_disabled
);
1352 xprintf("%S\n", *ep
);
1354 cleanup_until(&xlate_cr
);
1356 else if ((e
= tgetenv(*v
)) != NULL
) {
1359 old_output_raw
= output_raw
;
1361 cleanup_push(&old_output_raw
, output_raw_restore
);
1363 cleanup_until(&old_output_raw
);
1366 setcopy(STRstatus
, STR1
, VAR_READWRITE
);
1369 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1370 (and anything else with a modern compiler) */
1374 dosetenv(Char
**v
, struct command
*c
)
1388 stderror(ERR_NAME
| ERR_VARBEGIN
);
1391 } while (alnum(*lp
) || *lp
== '.');
1393 stderror(ERR_NAME
| ERR_VARALNUM
);
1395 if ((lp
= *v
++) == 0)
1398 lp
= globone(lp
, G_APPEND
);
1399 cleanup_push(lp
, xfree
);
1401 if (eq(vp
, STRKPATH
)) {
1409 if (eq(vp
, STRSYSTYPE
)) {
1416 /* dspkanji/dspmbyte autosetting */
1417 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1418 #if defined(DSPMBYTE)
1419 if(eq(vp
, STRLANG
) && !adrof(CHECK_MBYTEVAR
)) {
1420 autoset_dspmbyte(lp
);
1424 if (islocale_var(vp
)) {
1428 # ifdef SETLOCALEBUG
1430 # endif /* SETLOCALEBUG */
1431 (void) setlocale(LC_ALL
, "");
1433 (void) setlocale(LC_COLLATE
, "");
1436 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1437 # endif /* LC_CTYPE */
1438 # if defined(AUTOSET_KANJI)
1440 # endif /* AUTOSET_KANJI */
1441 # ifdef NLS_CATALOGS
1443 (void) setlocale(LC_MESSAGES
, "");
1444 # endif /* LC_MESSAGES */
1447 # endif /* NLS_CATALOGS */
1448 # ifdef SETLOCALEBUG
1450 # endif /* SETLOCALEBUG */
1453 # endif /* STRCOLLBUG */
1454 tw_cmd_free(); /* since the collation sequence has changed */
1455 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1457 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1461 NLSMapsAreInited
= 0;
1463 if (MapsAreInited
&& !NLSMapsAreInited
)
1470 if (eq(vp
, STRNLSPATH
)) {
1476 if (eq(vp
, STRNOREBIND
)) {
1479 NLSMapsAreInited
= 0;
1485 if (eq(vp
, STRtcshlang
)) {
1490 #endif /* WINNT_NATIVE */
1491 if (eq(vp
, STRKTERM
)) {
1494 setv(STRterm
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1498 if (noediting
&& strcmp(t
, "unknown") != 0 && strcmp(t
,"dumb") != 0) {
1508 if (eq(vp
, STRKHOME
)) {
1511 * convert to canonical pathname (possibly resolving symlinks)
1513 canon
= dcanon(lp
, lp
);
1516 cleanup_push(canon
, xfree
);
1517 setv(STRhome
, quote(canon
), VAR_READWRITE
); /* lp memory used here */
1518 cleanup_ignore(canon
);
1519 cleanup_until(canon
);
1521 /* fix directory stack for new tilde home */
1526 if (eq(vp
, STRKSHLVL
)) {
1527 setv(STRshlvl
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1533 if (eq(vp
, STRKUSER
)) {
1534 setv(STRuser
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1540 if (eq(vp
, STRKGROUP
)) {
1541 setv(STRgroup
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1548 if (eq(vp
, STRLS_COLORS
)) {
1553 if (eq(vp
, STRLSCOLORS
)) {
1558 #endif /* COLOR_LS_F */
1562 * Load/Update $LINES $COLUMNS
1564 if ((eq(lp
, STRNULL
) && (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
))) ||
1565 eq(vp
, STRTERMCAP
)) {
1567 check_window_size(1);
1572 * Change the size to the one directed by $LINES and $COLUMNS
1574 if (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
)) {
1582 #endif /* SIG_WINDOW */
1588 dounsetenv(Char
**v
, struct command
*c
)
1590 Char
**ep
, *p
, *n
, *name
;
1595 * Find the longest environment variable
1597 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1598 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
1604 name
= xmalloc((maxi
+ 1) * sizeof(Char
));
1605 cleanup_push(name
, xfree
);
1608 for (maxi
= 1; maxi
;)
1609 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1610 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
1613 if (!Gmatch(name
, *v
))
1617 /* Unset the name. This wasn't being done until
1618 * later but most of the stuff following won't
1619 * work (particularly the setlocale() and getenv()
1620 * stuff) as intended until the name is actually
1625 if (eq(name
, STRNOREBIND
)) {
1628 NLSMapsAreInited
= 0;
1632 else if (eq(name
, STRSYSTYPE
))
1635 else if (islocale_var(name
)) {
1639 # ifdef SETLOCALEBUG
1641 # endif /* SETLOCALEBUG */
1642 (void) setlocale(LC_ALL
, "");
1644 (void) setlocale(LC_COLLATE
, "");
1647 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1648 # endif /* LC_CTYPE */
1649 # ifdef NLS_CATALOGS
1651 (void) setlocale(LC_MESSAGES
, "");
1652 # endif /* LC_MESSAGES */
1655 # endif /* NLS_CATALOGS */
1656 # ifdef SETLOCALEBUG
1658 # endif /* SETLOCALEBUG */
1661 # endif /* STRCOLLBUG */
1662 tw_cmd_free();/* since the collation sequence has changed */
1663 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1665 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1667 AsciiOnly
= getenv("LANG") == NULL
&&
1668 getenv("LC_CTYPE") == NULL
;
1670 NLSMapsAreInited
= 0;
1672 if (MapsAreInited
&& !NLSMapsAreInited
)
1677 else if (eq(name
,(STRtcshlang
))) {
1681 #endif /* WINNT_NATIVE */
1683 else if (eq(name
, STRLS_COLORS
))
1685 else if (eq(name
, STRLSCOLORS
))
1687 #endif /* COLOR_LS_F */
1689 else if (eq(name
, STRNLSPATH
)) {
1695 * start again cause the environment changes
1699 cleanup_until(name
);
1703 tsetenv(const Char
*name
, const Char
*val
)
1705 #ifdef SETENV_IN_LIB
1707 * XXX: This does not work right, since tcsh cannot track changes to
1708 * the environment this way. (the builtin setenv without arguments does
1709 * not print the right stuff neither does unsetenv). This was for Mach,
1710 * it is not needed anymore.
1717 cname
= strsave(short2str(name
));
1718 setenv(cname
, short2str(val
), 1);
1720 #else /* !SETENV_IN_LIB */
1721 Char
**ep
= STR_environ
;
1728 nt_set_env(name
,val
);
1729 #endif /* WINNT_NATIVE */
1732 for (ccp
= name
, dp
= *ep
; *ccp
&& Tolower(*ccp
& TRIM
) == Tolower(*dp
);
1735 for (ccp
= name
, dp
= *ep
; *ccp
&& (*ccp
& TRIM
) == *dp
; ccp
++, dp
++)
1736 #endif /* WINNT_NATIVE */
1738 if (*ccp
!= 0 || *dp
!= '=')
1740 cp
= Strspl(STRequal
, val
);
1742 *ep
= strip(Strspl(name
, cp
));
1744 blkfree((Char
**) environ
);
1745 environ
= short2blk(STR_environ
);
1748 cp
= Strspl(name
, STRequal
);
1749 blk
[0] = strip(Strspl(cp
, val
));
1752 STR_environ
= blkspl(STR_environ
, blk
);
1753 blkfree((Char
**) environ
);
1754 environ
= short2blk(STR_environ
);
1756 #endif /* SETENV_IN_LIB */
1760 Unsetenv(Char
*name
)
1762 Char
**ep
= STR_environ
;
1767 nt_set_env(name
,NULL
);
1768 #endif /*WINNT_NATIVE */
1770 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1772 if (*cp
!= 0 || *dp
!= '=')
1776 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1777 blkfree((Char
**) environ
);
1778 environ
= short2blk(STR_environ
);
1788 doumask(Char
**v
, struct command
*c
)
1801 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1802 i
= i
* 8 + *cp
++ - '0';
1803 if (*cp
|| i
< 0 || i
> 0777)
1804 stderror(ERR_NAME
| ERR_MASK
);
1810 typedef long RLIM_TYPE
;
1811 # ifdef _OSD_POSIX /* BS2000 */
1812 # include <ulimit.h>
1814 # ifndef RLIM_INFINITY
1815 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1816 extern RLIM_TYPE
ulimit();
1817 # endif /* ! _MINIX && !__clipper__ */
1818 # define RLIM_INFINITY 0x003fffff
1819 # define RLIMIT_FSIZE 1
1820 # endif /* RLIM_INFINITY */
1822 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1823 # define RLIMIT_DATA 3
1824 # define RLIMIT_STACK 1005
1826 # define toset(a) ((a) + 1)
1828 # else /* BSDLIMIT */
1829 # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
1830 typedef rlim_t RLIM_TYPE
;
1832 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1833 typedef rlim_t RLIM_TYPE
;
1836 typedef long long RLIM_TYPE
;
1838 typedef unsigned long RLIM_TYPE
;
1840 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1841 # endif /* BSD4_4 && !__386BSD__ */
1842 # endif /* BSDLIMIT */
1844 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
1845 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1846 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1848 # define RLIMIT_CPU 0
1849 # define RLIMIT_FSIZE 1
1850 # define RLIMIT_DATA 2
1851 # define RLIMIT_STACK 3
1852 # define RLIMIT_CORE 4
1853 # define RLIMIT_RSS 5
1854 # define RLIMIT_NOFILE 6
1855 # endif /* RLIMIT_CPU */
1856 # ifndef RLIM_INFINITY
1857 # define RLIM_INFINITY 0x7fffffff
1858 # endif /* RLIM_INFINITY */
1860 * old versions of HP/UX counted limits in 512 bytes
1863 # define FILESIZE512
1864 # endif /* SIGRTMIN */
1865 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
1867 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1868 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1869 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1870 /* than include both and get warnings, we define the extra SVR4 limits here. */
1871 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1872 /* RLIMIT_VMEM based on it? */
1873 # ifndef RLIMIT_VMEM
1874 # define RLIMIT_VMEM 6
1877 # define RLIMIT_AS RLIMIT_VMEM
1879 # endif /* SYSVREL > 3 && BSDLIMIT */
1881 # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__))
1882 # if defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1883 # define RLIMIT_VMEM RLIMIT_AS
1886 * Oh well, <asm-generic/resource.h> has it, but <bits/resource.h> does not
1887 * Linux headers: When the left hand does not know what the right hand does.
1889 # if defined(RLIMIT_RTPRIO) && !defined(RLIMIT_RTTIME)
1890 # define RLIMIT_RTTIME (RLIMIT_RTPRIO + 1)
1894 struct limits limits
[] =
1897 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1898 # endif /* RLIMIT_CPU */
1900 # ifdef RLIMIT_FSIZE
1902 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1904 { RLIMIT_FSIZE
, "filesize", 512, "blocks" },
1906 # endif /* RLIMIT_FSIZE */
1909 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1910 # endif /* RLIMIT_DATA */
1912 # ifdef RLIMIT_STACK
1914 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1916 { RLIMIT_STACK
, "stacksize", 1024 * 1024, "kbytes"},
1918 # endif /* RLIMIT_STACK */
1921 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1922 # endif /* RLIMIT_CORE */
1925 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1926 # endif /* RLIMIT_RSS */
1929 { RLIMIT_UMEM
, "memoryuse", 1024, "kbytes" },
1930 # endif /* RLIMIT_UMEM */
1933 { RLIMIT_VMEM
, "vmemoryuse", 1024, "kbytes" },
1934 # endif /* RLIMIT_VMEM */
1936 # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
1937 { RLIMIT_HEAP
, "heapsize", 1024, "kbytes" },
1938 # endif /* RLIMIT_HEAP */
1940 # ifdef RLIMIT_NOFILE
1941 { RLIMIT_NOFILE
, "descriptors", 1, "" },
1942 # endif /* RLIMIT_NOFILE */
1945 { RLIMIT_NPTS
, "pseudoterminals", 1, "" },
1946 # endif /* RLIMIT_NPTS */
1948 # ifdef RLIMIT_KQUEUES
1949 { RLIMIT_KQUEUES
, "kqueues", 1, "" },
1950 # endif /* RLIMIT_KQUEUES */
1952 # ifdef RLIMIT_CONCUR
1953 { RLIMIT_CONCUR
, "concurrency", 1, "thread(s)" },
1954 # endif /* RLIMIT_CONCUR */
1956 # ifdef RLIMIT_MEMLOCK
1957 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1958 # endif /* RLIMIT_MEMLOCK */
1960 # ifdef RLIMIT_NPROC
1961 { RLIMIT_NPROC
, "maxproc", 1, "" },
1962 # endif /* RLIMIT_NPROC */
1965 { RLIMIT_NTHR
, "maxthread", 1, "" },
1966 # endif /* RLIMIT_NTHR */
1968 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1969 { RLIMIT_OFILE
, "openfiles", 1, "" },
1970 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1972 # ifdef RLIMIT_SBSIZE
1973 { RLIMIT_SBSIZE
, "sbsize", 1, "" },
1974 # endif /* RLIMIT_SBSIZE */
1976 #ifdef RLIMIT_POSIXLOCKS
1977 { RLIMIT_POSIXLOCKS
, "posixlocks", 1, "" },
1978 #endif /* RLIMIT_POSIXLOCKS */
1981 { RLIMIT_SWAP
, "swapsize", 1024, "kbytes" },
1982 # endif /* RLIMIT_SWAP */
1984 # ifdef RLIMIT_LOCKS
1985 { RLIMIT_LOCKS
, "maxlocks", 1, "" },
1986 # endif /* RLIMIT_LOCKS */
1988 # ifdef RLIMIT_POSIXLOCKS
1989 { RLIMIT_POSIXLOCKS
,"posixlocks", 1, "" },
1990 # endif /* RLIMIT_POSIXLOCKS */
1992 # ifdef RLIMIT_SIGPENDING
1993 { RLIMIT_SIGPENDING
,"maxsignal", 1, "" },
1994 # endif /* RLIMIT_SIGPENDING */
1996 # ifdef RLIMIT_MSGQUEUE
1997 { RLIMIT_MSGQUEUE
, "maxmessage", 1, "" },
1998 # endif /* RLIMIT_MSGQUEUE */
2001 { RLIMIT_NICE
, "maxnice", 1, "" },
2002 # endif /* RLIMIT_NICE */
2004 # ifdef RLIMIT_RTPRIO
2005 { RLIMIT_RTPRIO
, "maxrtprio", 1, "" },
2006 # endif /* RLIMIT_RTPRIO */
2008 # ifdef RLIMIT_RTTIME
2009 { RLIMIT_RTTIME
, "maxrttime", 1, "usec" },
2010 # endif /* RLIMIT_RTTIME */
2012 { -1, NULL
, 0, NULL
}
2015 static struct limits
*findlim (Char
*);
2016 static RLIM_TYPE
getval (struct limits
*, Char
**);
2017 static int strtail (Char
*, const char *);
2018 static void limtail (Char
*, const char *);
2019 static void limtail2 (Char
*, const char *, const char *);
2020 static void plim (struct limits
*, int);
2021 static int setlim (struct limits
*, int, RLIM_TYPE
);
2025 restrict_limit(double value
)
2028 * is f too large to cope with? return the maximum or minimum int
2030 if (value
> (double) INT_MAX
)
2031 return (RLIM_TYPE
) INT_MAX
;
2032 else if (value
< (double) INT_MIN
)
2033 return (RLIM_TYPE
) INT_MIN
;
2035 return (RLIM_TYPE
) value
;
2038 # define restrict_limit(x) ((RLIM_TYPE) (x))
2042 static struct limits
*
2045 struct limits
*lp
, *res
;
2048 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2049 if (prefix(cp
, str2short(lp
->limname
))) {
2051 stderror(ERR_NAME
| ERR_AMBIG
);
2056 stderror(ERR_NAME
| ERR_LIMIT
);
2063 dolimit(Char
**v
, struct command
*c
)
2071 if (*v
&& eq(*v
, STRmh
)) {
2076 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2085 limit
= getval(lp
, v
+ 1);
2086 if (setlim(lp
, hard
, limit
) < 0)
2087 stderror(ERR_SILENT
);
2091 getval(struct limits
*lp
, Char
**v
)
2096 f
= atof(short2str(cp
));
2100 * is f too large to cope with. limit f to minint, maxint - X-6768 by
2103 if ((f
< (double) INT_MIN
) || (f
> (double) INT_MAX
)) {
2104 stderror(ERR_NAME
| ERR_TOOLARGE
);
2106 # endif /* convex */
2108 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
2112 return restrict_limit((f
* lp
->limdiv
) + 0.5);
2118 if (lp
->limconst
!= RLIMIT_CPU
)
2120 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
* 60.0 + atof(short2str(cp
+ 1))));
2122 if (lp
->limconst
!= RLIMIT_CPU
)
2124 limtail(cp
, "hours");
2127 # endif /* RLIMIT_CPU */
2130 if (lp
->limconst
== RLIMIT_CPU
) {
2131 limtail(cp
, "minutes");
2135 # endif /* RLIMIT_CPU */
2136 limtail2(cp
, "megabytes", "mbytes");
2137 f
*= 1024.0 * 1024.0;
2141 if (lp
->limconst
!= RLIMIT_CPU
)
2143 limtail(cp
, "seconds");
2145 # endif /* RLIMIT_CPU */
2151 if (lp
->limconst
== RLIMIT_CPU
)
2153 # endif /* RLIMIT_CPU */
2154 limtail2(cp
, "gigabytes", "gbytes");
2155 f
*= 1024.0 * 1024.0 * 1024.0;
2159 if (lp
->limconst
== RLIMIT_CPU
)
2161 # endif /* RLIMIT_CPU */
2163 limtail2(cp
, "megabytes", "mbytes");
2164 f
*= 1024.0 * 1024.0;
2168 if (lp
->limconst
== RLIMIT_CPU
)
2170 # endif /* RLIMIT_CPU */
2171 limtail2(cp
, "kilobytes", "kbytes");
2176 if (lp
->limconst
== RLIMIT_CPU
)
2178 # endif /* RLIMIT_CPU */
2179 limtail(cp
, "blocks");
2183 limtail(cp
, "unlimited");
2184 return ((RLIM_TYPE
) RLIM_INFINITY
);
2188 # endif /* RLIMIT_CPU */
2189 stderror(ERR_NAME
| ERR_SCALEF
);
2192 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
+ 0.5));
2195 if (f
> (float) ((RLIM_TYPE
) RLIM_INFINITY
))
2196 return ((RLIM_TYPE
) RLIM_INFINITY
);
2198 return ((RLIM_TYPE
) f
);
2199 # endif /* convex */
2203 strtail(Char
*cp
, const char *str
)
2205 while (*cp
&& *cp
== (Char
)*str
)
2207 return (*cp
!= '\0');
2211 limtail(Char
*cp
, const char *str
)
2213 if (strtail(cp
, str
))
2214 stderror(ERR_BADSCALE
, str
);
2218 limtail2(Char
*cp
, const char *str1
, const char *str2
)
2220 if (strtail(cp
, str1
) && strtail(cp
, str2
))
2221 stderror(ERR_BADSCALE
, str1
);
2226 plim(struct limits
*lp
, int hard
)
2230 # endif /* BSDLIMIT */
2232 int xdiv
= lp
->limdiv
;
2234 xprintf("%-13.13s", lp
->limname
);
2237 limit
= ulimit(lp
->limconst
, 0);
2239 if (lp
->limconst
== RLIMIT_DATA
)
2240 limit
-= 0x20000000;
2242 # else /* BSDLIMIT */
2243 (void) getrlimit(lp
->limconst
, &rlim
);
2244 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
2245 # endif /* BSDLIMIT */
2247 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2249 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2250 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2252 if (lp
->limconst
== RLIMIT_FSIZE
) {
2253 if (limit
>= (RLIM_INFINITY
/ 512))
2254 limit
= RLIM_INFINITY
;
2256 xdiv
= (xdiv
== 1024 ? 2 : 1);
2258 # endif /* !BSDLIMIT || FILESIZE512 */
2260 if (limit
== RLIM_INFINITY
)
2261 xprintf("unlimited");
2263 # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
2264 if (lp
->limconst
== RLIMIT_CPU
&&
2265 (unsigned long)limit
>= 0x7ffffffdUL
)
2266 xprintf("unlimited");
2270 if (lp
->limconst
== RLIMIT_CPU
)
2273 # endif /* RLIMIT_CPU */
2274 xprintf("%ld %s", (long) (limit
/ xdiv
), lp
->limscale
);
2280 dounlimit(Char
**v
, struct command
*c
)
2288 while (*++v
&& **v
== '-') {
2299 stderror(ERR_ULIMUS
);
2305 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2306 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0)
2309 stderror(ERR_SILENT
);
2314 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0 && !force
)
2315 stderror(ERR_SILENT
);
2320 setlim(struct limits
*lp
, int hard
, RLIM_TYPE limit
)
2325 (void) getrlimit(lp
->limconst
, &rlim
);
2328 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2329 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2331 # endif /* FILESIZE512 */
2333 rlim
.rlim_max
= limit
;
2334 else if (limit
== RLIM_INFINITY
&& euid
!= 0)
2335 rlim
.rlim_cur
= rlim
.rlim_max
;
2337 rlim
.rlim_cur
= limit
;
2339 if (rlim
.rlim_cur
> rlim
.rlim_max
)
2340 rlim
.rlim_max
= rlim
.rlim_cur
;
2342 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
2343 # else /* BSDLIMIT */
2344 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2347 if (lp
->limconst
== RLIMIT_DATA
)
2348 limit
+= 0x20000000;
2350 if (ulimit(toset(lp
->limconst
), limit
) < 0) {
2351 # endif /* BSDLIMIT */
2356 op
= strsave(limit
== RLIM_INFINITY
? CGETS(15, 2, "remove") :
2357 CGETS(15, 3, "set"));
2358 cleanup_push(op
, xfree
);
2359 type
= strsave(hard
? CGETS(15, 4, " hard") : "");
2360 cleanup_push(type
, xfree
);
2361 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname
,
2362 lp
->limname
, op
, type
, strerror(err
));
2369 #endif /* !HAVENOLIMIT */
2373 dosuspend(Char
**v
, struct command
*c
)
2376 struct sigaction old
;
2377 #endif /* BSDJOBS */
2383 stderror(ERR_SUSPLOG
);
2387 sigaction(SIGTSTP
, NULL
, &old
);
2388 signal(SIGTSTP
, SIG_DFL
);
2389 (void) kill(0, SIGTSTP
);
2390 /* the shell stops here */
2391 sigaction(SIGTSTP
, &old
, NULL
);
2392 #else /* !BSDJOBS */
2393 stderror(ERR_JOBCONTROL
);
2394 #endif /* BSDJOBS */
2398 if (grabpgrp(FSHTTY
, opgrp
) == -1)
2399 stderror(ERR_SYSTEM
, "tcgetpgrp", strerror(errno
));
2400 (void) setpgid(0, shpgrp
);
2401 (void) tcsetpgrp(FSHTTY
, shpgrp
);
2403 #endif /* BSDJOBS */
2404 (void) setdisc(FSHTTY
);
2407 /* This is the dreaded EVAL built-in.
2408 * If you don't fiddle with file descriptors, and reset didfds,
2409 * this command will either ignore redirection inside or outside
2410 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2411 * The stuff here seems to work, but I did it by trial and error rather
2412 * than really knowing what was going on. If tpgrp is zero, we are
2413 * probably a background eval, e.g. "eval date &", and we want to
2414 * make sure that any processes we start stay in our pgrp.
2415 * This is also the case for "time eval date" -- stay in same pgrp.
2416 * Otherwise, under stty tostop, processes will stop in the wrong
2417 * pgrp, with no way for the shell to get them going again. -IAN!
2422 Char
**evalvec
, *evalp
;
2424 #ifndef CLOSE_ON_EXEC
2427 int saveIN
, saveOUT
, saveDIAG
;
2428 int SHIN
, SHOUT
, SHDIAG
;
2432 doeval_cleanup(void *xstate
)
2434 struct doeval_state
*state
;
2437 evalvec
= state
->evalvec
;
2438 evalp
= state
->evalp
;
2440 #ifndef CLOSE_ON_EXEC
2441 didcch
= state
->didcch
;
2442 #endif /* CLOSE_ON_EXEC */
2443 didfds
= state
->didfds
;
2447 close_on_exec(SHIN
= dmove(state
->saveIN
, state
->SHIN
), 1);
2448 close_on_exec(SHOUT
= dmove(state
->saveOUT
, state
->SHOUT
), 1);
2449 close_on_exec(SHDIAG
= dmove(state
->saveDIAG
, state
->SHDIAG
), 1);
2455 doeval(Char
**v
, struct command
*c
)
2457 struct doeval_state state
;
2458 int gflag
, my_reenter
;
2468 gv
= v
= globall(v
, gflag
);
2470 stderror(ERR_NOMATCH
);
2471 cleanup_push(gv
, blk_cleanup
);
2481 state
.evalvec
= evalvec
;
2482 state
.evalp
= evalp
;
2483 state
.didfds
= didfds
;
2484 #ifndef CLOSE_ON_EXEC
2485 state
.didcch
= didcch
;
2486 #endif /* CLOSE_ON_EXEC */
2488 state
.SHOUT
= SHOUT
;
2489 state
.SHDIAG
= SHDIAG
;
2491 (void)close_on_exec(state
.saveIN
= dcopy(SHIN
, -1), 1);
2492 (void)close_on_exec(state
.saveOUT
= dcopy(SHOUT
, -1), 1);
2493 (void)close_on_exec(state
.saveDIAG
= dcopy(SHDIAG
, -1), 1);
2495 cleanup_push(&state
, doeval_cleanup
);
2499 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
2501 my_reenter
= 1; /* assume non-zero return val */
2502 if (setexit() == 0) {
2503 my_reenter
= 0; /* Oh well, we were wrong */
2505 if ((my_reenter
= setexit()) == 0) {
2509 (void)close_on_exec(SHIN
= dcopy(0, -1), 1);
2510 (void)close_on_exec(SHOUT
= dcopy(1, -1), 1);
2511 (void)close_on_exec(SHDIAG
= dcopy(2, -1), 1);
2512 #ifndef CLOSE_ON_EXEC
2514 #endif /* CLOSE_ON_EXEC */
2521 if (my_reenter
== 0) {
2522 cleanup_until(&state
);
2529 stderror(ERR_SILENT
);
2532 /*************************************************************************/
2533 /* print list of builtin commands */
2536 lbuffed_cleanup (void *dummy
)
2544 dobuiltins(Char
**v
, struct command
*c
)
2546 /* would use print_by_column() in tw.parse.c but that assumes
2547 * we have an array of Char * to pass.. (sg)
2549 const struct biltins
*b
;
2550 int row
, col
, columns
, rows
;
2551 unsigned int w
, maxwidth
;
2555 lbuffed
= 0; /* turn off line buffering */
2556 cleanup_push(&lbuffed
, lbuffed_cleanup
);
2558 /* find widest string */
2559 for (maxwidth
= 0, b
= bfunc
; b
< &bfunc
[nbfunc
]; ++b
)
2560 maxwidth
= max(maxwidth
, strlen(b
->bname
));
2561 ++maxwidth
; /* for space */
2563 columns
= (TermH
+ 1) / maxwidth
; /* PWP: terminal size change */
2566 rows
= (nbfunc
+ (columns
- 1)) / columns
;
2568 for (b
= bfunc
, row
= 0; row
< rows
; row
++) {
2569 for (col
= 0; col
< columns
; col
++) {
2570 if (b
< &bfunc
[nbfunc
]) {
2571 w
= strlen(b
->bname
);
2572 xprintf("%s", b
->bname
);
2573 if (col
< (columns
- 1)) /* Not last column? */
2574 for (; w
< maxwidth
; w
++)
2579 if (row
< (rows
- 1)) {
2586 nt_print_builtins(maxwidth
);
2591 #endif /* WINNT_NATIVE */
2593 cleanup_until(&lbuffed
); /* turn back on line buffering */
2599 xcatgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2604 while ((res
= catgets(ctd
, set_id
, msg_id
, s
)) == s
&& errno
== EINTR
) {
2605 handle_pending_signals();
2612 # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2614 iconv_catgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2616 static char *buf
= NULL
;
2617 static size_t buf_size
= 0;
2619 char *orig
, *dest
, *p
;
2620 ICONV_CONST
char *src
;
2621 size_t src_size
, dest_size
;
2623 orig
= xcatgets(ctd
, set_id
, msg_id
, s
);
2624 if (catgets_iconv
== (iconv_t
)-1 || orig
== s
)
2627 src_size
= strlen(src
) + 1;
2628 if (buf
== NULL
&& (buf
= xmalloc(buf_size
= src_size
+ 32)) == NULL
)
2631 while (src_size
!= 0) {
2632 dest_size
= buf
+ buf_size
- dest
;
2633 if (iconv(catgets_iconv
, &src
, &src_size
, &dest
, &dest_size
)
2637 if ((p
= xrealloc(buf
, buf_size
* 2)) == NULL
)
2640 dest
= p
+ (dest
- buf
);
2644 case EILSEQ
: case EINVAL
: default:
2651 # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2652 #endif /* NLS_CATALOGS */
2658 static const char default_catalog
[] = "tcsh";
2660 char *catalog
= (char *)(intptr_t)default_catalog
;
2662 if (adrof(STRcatalog
) != NULL
)
2663 catalog
= xasprintf("tcsh.%s", short2str(varval(STRcatalog
)));
2664 #ifdef NL_CAT_LOCALE /* POSIX-compliant. */
2666 * Check if LC_MESSAGES is set in the environment and use it, if so.
2667 * If not, fall back to the setting of LANG.
2669 catd
= catopen(catalog
, tgetenv(STRLC_MESSAGES
) ? NL_CAT_LOCALE
: 0);
2670 #else /* pre-POSIX */
2671 # ifndef MCLoadBySet
2672 # define MCLoadBySet 0
2674 catd
= catopen(catalog
, MCLoadBySet
);
2676 if (catalog
!= default_catalog
)
2678 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2679 /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
2680 catgets_iconv
= iconv_open (nl_langinfo (CODESET
),
2681 xcatgets(catd
, 255, 1, "UTF-8"));
2682 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2683 #endif /* NLS_CATALOGS */
2686 #endif /* WINNT_NATIVE */
2687 errinit(); /* init the errorlist in correct locale */
2688 mesginit(); /* init the messages for signals */
2689 dateinit(); /* init the messages for dates */
2690 editinit(); /* init the editor messages */
2691 terminit(); /* init the termcap messages */
2698 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2699 if (catgets_iconv
!= (iconv_t
)-1) {
2700 iconv_close(catgets_iconv
);
2701 catgets_iconv
= (iconv_t
)-1;
2703 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2704 if (catd
!= (nl_catd
)-1) {
2706 * catclose can call other functions which can call longjmp
2707 * making us re-enter this code. Prevent infinite recursion
2708 * by resetting catd. Problem reported and solved by:
2711 nl_catd oldcatd
= catd
;
2713 while (catclose(oldcatd
) == -1 && errno
== EINTR
)
2714 handle_pending_signals();
2716 #endif /* NLS_CATALOGS */