1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.153 2009/06/25 21:15:37 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.153 2009/06/25 21:15:37 christos Exp $")
42 #endif /* WINNT_NATIVE */
44 #if defined (NLS_CATALOGS) && defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
46 static iconv_t catgets_iconv
; /* Or (iconv_t)-1 */
53 extern int MapsAreInited
;
54 extern int NLSMapsAreInited
;
55 extern int GotTermCaps
;
57 static int zlast
= -1;
59 static void islogin (void);
60 static void preread (void);
61 static void doagain (void);
62 static const char *isrchx (int);
63 static void search (int, int, Char
*);
64 static int getword (struct Strbuf
*);
65 static struct wordent
*histgetword (struct wordent
*);
66 static void toend (void);
67 static void xecho (int, Char
**);
68 static int islocale_var (Char
*);
69 static void wpfree (struct whyle
*);
71 const struct biltins
*
72 isbfunc(struct command
*t
)
74 Char
*cp
= t
->t_dcom
[0];
75 const struct biltins
*bp
, *bp1
, *bp2
;
76 static struct biltins label
= {"", dozip
, 0, 0};
77 static struct biltins foregnd
= {"%job", dofg1
, 0, 0};
78 static struct biltins backgnd
= {"%job &", dobg1
, 0, 0};
81 * We never match a builtin that has quoted the first
82 * character; this has been the traditional way to escape
88 if (*cp
!= ':' && lastchr(cp
) == ':') {
89 label
.bname
= short2str(cp
);
93 if (t
->t_dflg
& F_AMPERSAND
) {
94 t
->t_dflg
&= ~F_AMPERSAND
;
95 backgnd
.bname
= short2str(cp
);
98 foregnd
.bname
= short2str(cp
);
103 * This is a perhaps kludgy way to determine if the warp builtin is to be
104 * acknowledged or not. If checkwarp() fails, then we are to assume that
105 * the warp command is invalid, and carry on as we would handle any other
106 * non-builtin command. -- JDK 2/4/88
108 if (eq(STRwarp
, cp
) && !checkwarp()) {
109 return (0); /* this builtin disabled */
113 * Binary search Bp1 is the beginning of the current search range. Bp2 is
116 for (bp1
= bfunc
, bp2
= bfunc
+ nbfunc
; bp1
< bp2
;) {
119 bp
= bp1
+ ((bp2
- bp1
) >> 1);
120 if ((i
= ((char) *cp
) - *bp
->bname
) == 0 &&
121 (i
= StrQcmp(cp
, str2short(bp
->bname
))) == 0)
129 return nt_check_additional_builtins(cp
);
130 #endif /*WINNT_NATIVE*/
135 func(struct command
*t
, const struct biltins
*bp
)
141 i
= blklen(t
->t_dcom
) - 1;
143 stderror(ERR_NAME
| ERR_TOOFEW
);
145 stderror(ERR_NAME
| ERR_TOOMANY
);
146 (*bp
->bfunct
) (t
->t_dcom
, t
);
151 doonintr(Char
**v
, struct command
*c
)
157 if (parintr
.sa_handler
== SIG_IGN
)
159 if (setintr
&& intty
)
160 stderror(ERR_NAME
| ERR_TERMINAL
);
166 sigset_interrupting(SIGINT
, queue_pintr
);
168 (void) signal(SIGINT
, SIG_DFL
);
171 else if (eq((vv
= strip(vv
)), STRminus
)) {
172 (void) signal(SIGINT
, SIG_IGN
);
173 gointr
= Strsave(STRminus
);
176 gointr
= Strsave(vv
);
177 sigset_interrupting(SIGINT
, queue_pintr
);
183 donohup(Char
**v
, struct command
*c
)
188 stderror(ERR_NAME
| ERR_TERMINAL
);
190 (void) signal(SIGHUP
, SIG_IGN
);
200 dohup(Char
**v
, struct command
*c
)
205 stderror(ERR_NAME
| ERR_TERMINAL
);
207 (void) signal(SIGHUP
, SIG_DFL
);
213 dozip(Char
**v
, struct command
*c
)
221 dofiletest(Char
**v
, struct command
*c
)
223 Char
**globbed
, **fileptr
, *ftest
, *res
;
226 if (*(ftest
= *++v
) != '-')
227 stderror(ERR_NAME
| ERR_FILEINQ
);
230 v
= glob_all_or_error(v
);
232 cleanup_push(globbed
, blk_cleanup
);
234 while (*(fileptr
= v
++) != '\0') {
235 res
= filetest(ftest
, &fileptr
, 0);
236 cleanup_push(res
, xfree
);
244 cleanup_until(globbed
);
250 plist(&shvhed
, VAR_ALL
);
255 doalias(Char
**v
, struct command
*c
)
264 plist(&aliases
, VAR_ALL
);
266 vp
= adrof1(strip(p
), &aliases
);
268 blkpr(vp
->vec
), xputchar('\n');
271 if (eq(p
, STRalias
) || eq(p
, STRunalias
)) {
272 setname(short2str(p
));
273 stderror(ERR_NAME
| ERR_DANGER
);
275 set1(strip(p
), saveblk(v
), &aliases
, VAR_READWRITE
);
282 unalias(Char
**v
, struct command
*c
)
291 dologout(Char
**v
, struct command
*c
)
301 dologin(Char
**v
, struct command
*c
)
306 #else /* !WINNT_NATIVE */
307 char **p
= short2blk(v
);
310 cleanup_push((Char
**)p
, blk_cleanup
);
312 rechist(NULL
, adrof(STRsavehist
) != NULL
);
313 sigaction(SIGTERM
, &parterm
, NULL
);
314 (void) execv(_PATH_BIN_LOGIN
, p
);
315 (void) execv(_PATH_USRBIN_LOGIN
, p
);
316 cleanup_until((Char
**)p
);
319 #endif /* !WINNT_NATIVE */
326 donewgrp(Char
**v
, struct command
*c
)
329 if (chkstop
== 0 && setintr
)
331 sigaction(SIGTERM
, &parterm
, NULL
);
334 * From Beto Appleton (beto@aixwiz.austin.ibm.com)
335 * Newgrp can take 2 arguments...
337 (void) execv(_PATH_BIN_NEWGRP
, p
);
338 (void) execv(_PATH_USRBIN_NEWGRP
, p
);
339 blkfree((Char
**) p
);
348 if (chkstop
== 0 && setintr
)
352 stderror(ERR_NOTLOGIN
);
356 doif(Char
**v
, struct command
*kp
)
362 i
= noexec
? 1 : expr(&v
);
365 stderror(ERR_NAME
| ERR_EMPTYIF
);
366 if (eq(*vv
, STRthen
)) {
368 stderror(ERR_NAME
| ERR_IMPRTHEN
);
369 setname(short2str(STRthen
));
371 * If expression was zero, then scan to else , otherwise just fall into
375 search(TC_IF
, 0, NULL
);
379 * Simple command attached to this if. Left shift the node in this tree,
380 * munging it so we can reexecute it.
383 lshift(kp
->t_dcom
, vv
- kp
->t_dcom
);
390 * Reexecute a command, being careful not
391 * to redo i/o redirection, which is already set up.
394 reexecute(struct command
*kp
)
396 kp
->t_dflg
&= F_SAVE
;
397 kp
->t_dflg
|= F_REPEAT
;
399 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
400 * pgrp's as the jobs would then have no way to get the tty (we can't give
401 * it to them, and our parent wouldn't know their pgrp, etc.
403 execute(kp
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
, TRUE
);
408 doelse (Char
**v
, struct command
*c
)
413 search(TC_ELSE
, 0, NULL
);
418 dogoto(Char
**v
, struct command
*c
)
423 lp
= globone(v
[1], G_ERROR
);
424 cleanup_push(lp
, xfree
);
435 * While we still can, locate any unknown ends of existing loops. This
436 * obscure code is the WORST result of the fact that we don't really parse.
439 for (wp
= whyles
; wp
; wp
= wp
->w_next
)
440 if (wp
->w_end
.type
== TCSH_F_SEEK
&& wp
->w_end
.f_seek
== 0) {
441 search(TC_BREAK
, 0, NULL
);
447 search(TC_GOTO
, 0, lab
);
449 * Eliminate loops which were exited.
456 doswitch(Char
**v
, struct command
*c
)
462 if (!*v
|| *(*v
++) != '(')
463 stderror(ERR_SYNTAX
);
464 cp
= **v
== ')' ? STRNULL
: *v
++;
468 stderror(ERR_SYNTAX
);
469 lp
= globone(cp
, G_ERROR
);
470 cleanup_push(lp
, xfree
);
472 search(TC_SWITCH
, 0, lp
);
478 dobreak(Char
**v
, struct command
*c
)
483 stderror(ERR_NAME
| ERR_NOTWHILE
);
490 doexit(Char
**v
, struct command
*c
)
494 if (chkstop
== 0 && (intty
|| intact
) && evalvec
== 0)
497 * Don't DEMAND parentheses here either.
501 setv(STRstatus
, putn(expr(&v
)), VAR_READWRITE
);
503 stderror(ERR_NAME
| ERR_EXPRESSION
);
509 /* Always close, why only on ttys? */
515 doforeach(Char
**v
, struct command
*c
)
525 stderror(ERR_NAME
| ERR_VARBEGIN
);
526 while (*cp
&& 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_next
= whyles
;
603 /* We ain't gonna loop no more, no more! */
610 int old_pintr_disabled
;
612 whyles
->w_end
.type
= TCSH_I_SEEK
;
614 pintr_push_enable(&old_pintr_disabled
);
615 search(TC_BREAK
, 0, NULL
); /* read the expression in */
617 cleanup_until(&old_pintr_disabled
);
618 btell(&whyles
->w_end
);
623 doend(Char
**v
, struct command
*c
)
628 stderror(ERR_NAME
| ERR_NOTWHILE
);
629 btell(&whyles
->w_end
);
636 docontin(Char
**v
, struct command
*c
)
641 stderror(ERR_NAME
| ERR_NOTWHILE
);
649 /* Repeating a while is simple */
650 if (whyles
->w_fename
== 0) {
651 bseek(&whyles
->w_start
);
655 * The foreach variable list actually has a spurious word ")" at the end of
656 * the w_fe list. Thus we are at the of the list if one word beyond this
659 if (!whyles
->w_fe
[1]) {
663 setv(whyles
->w_fename
, quote(Strsave(*whyles
->w_fe
++)), VAR_READWRITE
);
664 bseek(&whyles
->w_start
);
668 dorepeat(Char
**v
, struct command
*kp
)
675 } while (v
[0] != NULL
&& Strcmp(v
[0], STRrepeat
) == 0);
681 cleanup_push(&pintr_disabled
, disabled_cleanup
);
684 if (setintr
&& pintr_disabled
== 1) {
685 cleanup_until(&pintr_disabled
);
687 cleanup_push(&pintr_disabled
, disabled_cleanup
);
692 if (setintr
&& pintr_disabled
== 1)
693 cleanup_until(&pintr_disabled
);
699 doswbrk(Char
**v
, struct command
*c
)
704 search(TC_BRKSW
, 0, NULL
);
710 struct srch
*sp
, *sp1
, *sp2
;
714 * Ignore keywords inside heredocs
720 * Binary search Sp1 is the beginning of the current search range. Sp2 is
723 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
724 sp
= sp1
+ ((sp2
- sp1
) >> 1);
725 if ((i
= *cp
- *sp
->s_name
) == 0 &&
726 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
739 struct srch
*sp
, *sp2
;
741 for (sp
= srchn
, sp2
= srchn
+ nsrchn
; sp
< sp2
; sp
++)
742 if (sp
->s_value
== n
)
752 search(int type
, int level
, Char
*goal
)
754 struct Strbuf word
= Strbuf_INIT
;
758 struct wordent
*histent
= NULL
, *ohistent
= NULL
;
762 if (type
== TC_GOTO
) {
764 a
.type
= TCSH_F_SEEK
;
768 cleanup_push(&word
, Strbuf_cleanup
);
772 histent
= xmalloc(sizeof(*histent
));
773 ohistent
= xmalloc(sizeof(*histent
));
774 ohistent
->word
= STRNULL
;
775 ohistent
->next
= histent
;
776 histent
->prev
= ohistent
;
779 if (intty
&& fseekp
== feobp
&& aret
== TCSH_F_SEEK
)
780 printprompt(1, isrchx(type
== TC_BREAK
? zlast
: type
));
781 /* xprintf("? "), flush(); */
782 (void) getword(&word
);
783 Strbuf_terminate(&word
);
785 if (intty
&& Strlen(word
.s
) > 0) {
786 histent
->word
= Strsave(word
.s
);
787 histent
->next
= xmalloc(sizeof(*histent
));
788 histent
->next
->prev
= histent
;
789 histent
= histent
->next
;
792 switch (srchx(word
.s
)) {
795 if (level
== 0 && type
== TC_IF
)
800 while (getword(&word
))
802 if ((type
== TC_IF
|| type
== TC_ELSE
) &&
808 if (type
== TC_IF
|| type
== TC_ELSE
)
815 if (type
== TC_BREAK
)
820 if (type
== TC_BRKSW
) {
829 if (type
== TC_BREAK
)
835 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
840 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
845 if (type
== TC_GOTO
&& getword(&word
) && eq(word
.s
, goal
))
850 if (type
!= TC_GOTO
&& (type
!= TC_SWITCH
|| level
!= 0))
852 if (word
.len
== 0 || word
.s
[word
.len
- 1] != ':')
854 word
.s
[--word
.len
] = 0;
855 if ((type
== TC_GOTO
&& eq(word
.s
, goal
)) ||
856 (type
== TC_SWITCH
&& eq(word
.s
, STRdefault
)))
861 if (type
!= TC_SWITCH
|| level
!= 0)
863 (void) getword(&word
);
864 if (word
.len
!= 0 && word
.s
[word
.len
- 1] == ':')
865 word
.s
[--word
.len
] = 0;
866 cp
= strip(Dfix1(word
.s
));
867 cleanup_push(cp
, xfree
);
868 if (Gmatch(goal
, cp
))
874 if (type
== TC_SWITCH
&& level
== 0)
879 ohistent
->prev
= histgetword(histent
);
880 ohistent
->prev
->next
= ohistent
;
881 savehist(ohistent
, 0);
885 (void) getword(NULL
);
886 } while (level
>= 0);
888 cleanup_until(&word
);
891 static struct wordent
*
892 histgetword(struct wordent
*histent
)
894 int found
= 0, first
;
898 tmp
= xmalloc(sizeof(*tmp
));
906 Strbuf_terminate (tmp
);
907 while (c
== ' ' || c
== '\t')
912 while (c
!= CHAR_ERR
&& c
!= '\n');
923 if (c
== '\\' && !e
) {
924 if ((c
= readc(1)) == '\n') {
932 if ((c
== '\'' || c
== '"') && !e
) {
941 Strbuf_append1(tmp
, (Char
) c
);
943 if (!first
&& !d
&& c
== '(' && !e
) {
947 } while (d
|| e
|| (c
!= ' ' && c
!= '\t' && c
!= '\n'));
950 Strbuf_terminate(tmp
);
951 histent
->word
= Strsave(tmp
->s
);
952 histent
->next
= xmalloc(sizeof (*histent
));
953 histent
->next
->prev
= histent
;
954 histent
= histent
->next
;
959 Strbuf_append1(tmp
, (Char
) c
);
960 Strbuf_terminate(tmp
);
961 histent
->word
= Strsave(tmp
->s
);
973 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
977 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
982 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
986 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
990 setname(short2str(Sgoal
));
991 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1002 getword(struct Strbuf
*wp
)
1004 int found
= 0, first
;
1012 while (c
== ' ' || c
== '\t')
1017 while (c
!= CHAR_ERR
&& c
!= '\n');
1030 if (c
== '\\' && (c
= readc(1)) == '\n')
1032 if (c
== '\'' || c
== '"') {
1041 Strbuf_append1(wp
, (Char
) c
);
1042 if (!first
&& !d
&& c
== '(') {
1049 } while ((d
|| (c
!= ' ' && c
!= '\t')) && c
!= '\n');
1056 Strbuf_terminate(wp
);
1065 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
1069 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
1074 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
1078 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
1082 setname(short2str(Sgoal
));
1083 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
1096 if (whyles
->w_end
.type
== TCSH_F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
1097 search(TC_BREAK
, 0, NULL
);
1098 btell(&whyles
->w_end
);
1099 whyles
->w_end
.f_seek
--;
1102 bseek(&whyles
->w_end
);
1108 wpfree(struct whyle
*wp
)
1112 xfree(wp
->w_fename
);
1122 nwp
= NULL
; /* sun lint is dumb! */
1126 static const char foo
[] = "IAFE";
1132 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
1133 foo
[o
.type
+ 1], o
.a_seek
, o
.f_seek
);
1136 for (; whyles
; whyles
= nwp
) {
1137 struct whyle
*wp
= whyles
;
1141 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1142 foo
[wp
->w_start
.type
+1],
1143 wp
->w_start
.a_seek
, wp
->w_start
.f_seek
);
1144 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1145 foo
[wp
->w_end
.type
+ 1], wp
->w_end
.a_seek
, wp
->w_end
.f_seek
);
1149 * XXX: We free loops that have different seek types.
1151 if (wp
->w_end
.type
!= TCSH_I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
1152 wp
->w_start
.type
== o
.type
) {
1153 if (wp
->w_end
.type
== TCSH_F_SEEK
) {
1154 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
1155 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
1159 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
1160 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
1171 doecho(Char
**v
, struct command
*c
)
1179 doglob(Char
**v
, struct command
*c
)
1187 xecho(int sep
, Char
**v
)
1189 Char
*cp
, **globbed
= NULL
;
1191 int echo_style
= ECHO_STYLE
;
1194 if ((vp
= adrof(STRecho_style
)) != NULL
&& vp
->vec
!= NULL
&&
1195 vp
->vec
[0] != NULL
) {
1196 if (Strcmp(vp
->vec
[0], STRbsd
) == 0)
1197 echo_style
= BSD_ECHO
;
1198 else if (Strcmp(vp
->vec
[0], STRsysv
) == 0)
1199 echo_style
= SYSV_ECHO
;
1200 else if (Strcmp(vp
->vec
[0], STRboth
) == 0)
1201 echo_style
= BOTH_ECHO
;
1202 else if (Strcmp(vp
->vec
[0], STRnone
) == 0)
1203 echo_style
= NONE_ECHO
;
1210 int old_pintr_disabled
;
1211 pintr_push_enable(&old_pintr_disabled
);
1212 v
= glob_all_or_error(v
);
1213 cleanup_until(&old_pintr_disabled
);
1215 v
= glob_all_or_error(v
);
1218 if (globbed
!= NULL
)
1219 cleanup_push(globbed
, blk_cleanup
);
1221 if ((echo_style
& BSD_ECHO
) != 0 && sep
== ' ' && *v
&& eq(*v
, STRmn
))
1224 while ((cp
= *v
++) != 0) {
1228 int old_pintr_disabled
;
1230 pintr_push_enable(&old_pintr_disabled
);
1231 cleanup_until(&old_pintr_disabled
);
1233 while ((c
= *cp
++) != 0) {
1234 if ((echo_style
& SYSV_ECHO
) != 0 && c
== '\\') {
1235 switch (c
= *cp
++) {
1246 #if 0 /* Windows does not understand \e */
1249 c
= CTL_ESC('\033');
1272 if (*cp
>= '0' && *cp
< '8')
1273 c
= c
* 8 + *cp
++ - '0';
1274 if (*cp
>= '0' && *cp
< '8')
1275 c
= c
* 8 + *cp
++ - '0';
1276 if (*cp
>= '0' && *cp
< '8')
1277 c
= c
* 8 + *cp
++ - '0';
1284 xputchar('\\' | QUOTE
);
1288 xputwchar(c
| QUOTE
);
1292 xputchar(sep
| QUOTE
);
1295 if (sep
&& nonl
== 0)
1299 if (globbed
!= NULL
)
1300 cleanup_until(globbed
);
1303 /* check whether an environment variable should invoke 'set_locale()' */
1305 islocale_var(Char
*var
)
1307 static Char
*locale_vars
[] = {
1308 STRLANG
, STRLC_ALL
, STRLC_CTYPE
, STRLC_NUMERIC
,
1309 STRLC_TIME
, STRLC_COLLATE
, STRLC_MESSAGES
, STRLC_MONETARY
, 0
1313 for (v
= locale_vars
; *v
; ++v
)
1320 xlate_cr_cleanup(void *dummy
)
1328 doprintenv(Char
**v
, struct command
*c
)
1338 cleanup_push(&xlate_cr
, xlate_cr_cleanup
);
1339 for (ep
= STR_environ
; *ep
; ep
++) {
1341 int old_pintr_disabled
;
1343 pintr_push_enable(&old_pintr_disabled
);
1344 cleanup_until(&old_pintr_disabled
);
1346 xprintf("%S\n", *ep
);
1348 cleanup_until(&xlate_cr
);
1350 else if ((e
= tgetenv(*v
)) != NULL
) {
1353 old_output_raw
= output_raw
;
1355 cleanup_push(&old_output_raw
, output_raw_restore
);
1357 cleanup_until(&old_output_raw
);
1360 setcopy(STRstatus
, STR1
, VAR_READWRITE
);
1363 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1364 (and anything else with a modern compiler) */
1368 dosetenv(Char
**v
, struct command
*c
)
1382 for (; *lp
!= '\0' ; lp
++) {
1384 stderror(ERR_NAME
| ERR_SYNTAX
);
1386 if ((lp
= *v
++) == 0)
1389 lp
= globone(lp
, G_APPEND
);
1390 cleanup_push(lp
, xfree
);
1392 if (eq(vp
, STRKPATH
)) {
1400 if (eq(vp
, STRSYSTYPE
)) {
1407 /* dspkanji/dspmbyte autosetting */
1408 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1409 #if defined(DSPMBYTE)
1410 if(eq(vp
, STRLANG
) && !adrof(CHECK_MBYTEVAR
)) {
1411 autoset_dspmbyte(lp
);
1415 if (islocale_var(vp
)) {
1419 # ifdef SETLOCALEBUG
1421 # endif /* SETLOCALEBUG */
1422 (void) setlocale(LC_ALL
, "");
1424 (void) setlocale(LC_COLLATE
, "");
1427 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1428 # endif /* LC_CTYPE */
1429 # ifdef NLS_CATALOGS
1431 (void) setlocale(LC_MESSAGES
, "");
1432 # endif /* LC_MESSAGES */
1435 # endif /* NLS_CATALOGS */
1436 # ifdef SETLOCALEBUG
1438 # endif /* SETLOCALEBUG */
1441 # endif /* STRCOLLBUG */
1442 tw_cmd_free(); /* since the collation sequence has changed */
1443 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1445 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1449 NLSMapsAreInited
= 0;
1451 if (MapsAreInited
&& !NLSMapsAreInited
)
1458 if (eq(vp
, STRNLSPATH
)) {
1464 if (eq(vp
, STRNOREBIND
)) {
1467 NLSMapsAreInited
= 0;
1473 if (eq(vp
, STRtcshlang
)) {
1478 #endif /* WINNT_NATIVE */
1479 if (eq(vp
, STRKTERM
)) {
1482 setv(STRterm
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1486 if (noediting
&& strcmp(t
, "unknown") != 0 && strcmp(t
,"dumb") != 0) {
1496 if (eq(vp
, STRKHOME
)) {
1499 * convert to canonical pathname (possibly resolving symlinks)
1501 canon
= dcanon(lp
, lp
);
1504 cleanup_push(canon
, xfree
);
1505 setv(STRhome
, quote(canon
), VAR_READWRITE
); /* lp memory used here */
1506 cleanup_ignore(canon
);
1507 cleanup_until(canon
);
1509 /* fix directory stack for new tilde home */
1514 if (eq(vp
, STRKSHLVL
)) {
1515 setv(STRshlvl
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1521 if (eq(vp
, STRKUSER
)) {
1522 setv(STRuser
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1528 if (eq(vp
, STRKGROUP
)) {
1529 setv(STRgroup
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1536 if (eq(vp
, STRLS_COLORS
)) {
1541 #endif /* COLOR_LS_F */
1545 * Load/Update $LINES $COLUMNS
1547 if ((eq(lp
, STRNULL
) && (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
))) ||
1548 eq(vp
, STRTERMCAP
)) {
1550 check_window_size(1);
1555 * Change the size to the one directed by $LINES and $COLUMNS
1557 if (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
)) {
1565 #endif /* SIG_WINDOW */
1571 dounsetenv(Char
**v
, struct command
*c
)
1573 Char
**ep
, *p
, *n
, *name
;
1578 * Find the longest environment variable
1580 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1581 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
1587 name
= xmalloc((maxi
+ 1) * sizeof(Char
));
1588 cleanup_push(name
, xfree
);
1591 for (maxi
= 1; maxi
;)
1592 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1593 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
1596 if (!Gmatch(name
, *v
))
1600 /* Unset the name. This wasn't being done until
1601 * later but most of the stuff following won't
1602 * work (particularly the setlocale() and getenv()
1603 * stuff) as intended until the name is actually
1608 if (eq(name
, STRNOREBIND
)) {
1611 NLSMapsAreInited
= 0;
1615 else if (eq(name
, STRSYSTYPE
))
1618 else if (islocale_var(name
)) {
1622 # ifdef SETLOCALEBUG
1624 # endif /* SETLOCALEBUG */
1625 (void) setlocale(LC_ALL
, "");
1627 (void) setlocale(LC_COLLATE
, "");
1630 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1631 # endif /* LC_CTYPE */
1632 # ifdef NLS_CATALOGS
1634 (void) setlocale(LC_MESSAGES
, "");
1635 # endif /* LC_MESSAGES */
1638 # endif /* NLS_CATALOGS */
1639 # ifdef SETLOCALEBUG
1641 # endif /* SETLOCALEBUG */
1644 # endif /* STRCOLLBUG */
1645 tw_cmd_free();/* since the collation sequence has changed */
1646 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1648 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1650 AsciiOnly
= getenv("LANG") == NULL
&&
1651 getenv("LC_CTYPE") == NULL
;
1653 NLSMapsAreInited
= 0;
1655 if (MapsAreInited
&& !NLSMapsAreInited
)
1660 else if (eq(name
,(STRtcshlang
))) {
1664 #endif /* WINNT_NATIVE */
1666 else if (eq(name
, STRLS_COLORS
))
1668 #endif /* COLOR_LS_F */
1670 else if (eq(name
, STRNLSPATH
)) {
1676 * start again cause the environment changes
1680 cleanup_until(name
);
1684 tsetenv(const Char
*name
, const Char
*val
)
1686 #ifdef SETENV_IN_LIB
1688 * XXX: This does not work right, since tcsh cannot track changes to
1689 * the environment this way. (the builtin setenv without arguments does
1690 * not print the right stuff neither does unsetenv). This was for Mach,
1691 * it is not needed anymore.
1698 cname
= strsave(short2str(name
));
1699 setenv(cname
, short2str(val
), 1);
1701 #else /* !SETENV_IN_LIB */
1702 Char
**ep
= STR_environ
;
1709 nt_set_env(name
,val
);
1710 #endif /* WINNT_NATIVE */
1713 for (ccp
= name
, dp
= *ep
; *ccp
&& Tolower(*ccp
& TRIM
) == Tolower(*dp
);
1716 for (ccp
= name
, dp
= *ep
; *ccp
&& (*ccp
& TRIM
) == *dp
; ccp
++, dp
++)
1717 #endif /* WINNT_NATIVE */
1719 if (*ccp
!= 0 || *dp
!= '=')
1721 cp
= Strspl(STRequal
, val
);
1723 *ep
= strip(Strspl(name
, cp
));
1725 blkfree((Char
**) environ
);
1726 environ
= short2blk(STR_environ
);
1729 cp
= Strspl(name
, STRequal
);
1730 blk
[0] = strip(Strspl(cp
, val
));
1733 STR_environ
= blkspl(STR_environ
, blk
);
1734 blkfree((Char
**) environ
);
1735 environ
= short2blk(STR_environ
);
1737 #endif /* SETENV_IN_LIB */
1741 Unsetenv(Char
*name
)
1743 Char
**ep
= STR_environ
;
1748 nt_set_env(name
,NULL
);
1749 #endif /*WINNT_NATIVE */
1751 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1753 if (*cp
!= 0 || *dp
!= '=')
1757 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1758 blkfree((Char
**) environ
);
1759 environ
= short2blk(STR_environ
);
1769 doumask(Char
**v
, struct command
*c
)
1782 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1783 i
= i
* 8 + *cp
++ - '0';
1784 if (*cp
|| i
< 0 || i
> 0777)
1785 stderror(ERR_NAME
| ERR_MASK
);
1791 typedef long RLIM_TYPE
;
1792 # ifdef _OSD_POSIX /* BS2000 */
1793 # include <ulimit.h>
1795 # ifndef RLIM_INFINITY
1796 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1797 extern RLIM_TYPE
ulimit();
1798 # endif /* ! _MINIX && !__clipper__ */
1799 # define RLIM_INFINITY 0x003fffff
1800 # define RLIMIT_FSIZE 1
1801 # endif /* RLIM_INFINITY */
1803 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1804 # define RLIMIT_DATA 3
1805 # define RLIMIT_STACK 1005
1807 # define toset(a) ((a) + 1)
1809 # else /* BSDLIMIT */
1810 # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
1811 typedef rlim_t RLIM_TYPE
;
1813 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1814 typedef rlim_t RLIM_TYPE
;
1817 typedef long long RLIM_TYPE
;
1819 typedef unsigned long RLIM_TYPE
;
1821 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1822 # endif /* BSD4_4 && !__386BSD__ */
1823 # endif /* BSDLIMIT */
1825 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
1826 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1827 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1829 # define RLIMIT_CPU 0
1830 # define RLIMIT_FSIZE 1
1831 # define RLIMIT_DATA 2
1832 # define RLIMIT_STACK 3
1833 # define RLIMIT_CORE 4
1834 # define RLIMIT_RSS 5
1835 # define RLIMIT_NOFILE 6
1836 # endif /* RLIMIT_CPU */
1837 # ifndef RLIM_INFINITY
1838 # define RLIM_INFINITY 0x7fffffff
1839 # endif /* RLIM_INFINITY */
1841 * old versions of HP/UX counted limits in 512 bytes
1844 # define FILESIZE512
1845 # endif /* SIGRTMIN */
1846 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
1848 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1849 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1850 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1851 /* than include both and get warnings, we define the extra SVR4 limits here. */
1852 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1853 /* RLIMIT_VMEM based on it? */
1854 # ifndef RLIMIT_VMEM
1855 # define RLIMIT_VMEM 6
1858 # define RLIMIT_AS RLIMIT_VMEM
1860 # endif /* SYSVREL > 3 && BSDLIMIT */
1862 # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1863 # define RLIMIT_VMEM RLIMIT_AS
1866 struct limits limits
[] =
1869 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1870 # endif /* RLIMIT_CPU */
1872 # ifdef RLIMIT_FSIZE
1874 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1876 { RLIMIT_FSIZE
, "filesize", 512, "blocks" },
1878 # endif /* RLIMIT_FSIZE */
1881 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1882 # endif /* RLIMIT_DATA */
1884 # ifdef RLIMIT_STACK
1886 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1888 { RLIMIT_STACK
, "stacksize", 1024 * 1024, "kbytes"},
1890 # endif /* RLIMIT_STACK */
1893 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1894 # endif /* RLIMIT_CORE */
1897 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1898 # endif /* RLIMIT_RSS */
1901 { RLIMIT_UMEM
, "memoryuse", 1024, "kbytes" },
1902 # endif /* RLIMIT_UMEM */
1905 { RLIMIT_VMEM
, "vmemoryuse", 1024, "kbytes" },
1906 # endif /* RLIMIT_VMEM */
1908 # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
1909 { RLIMIT_HEAP
, "heapsize", 1024, "kbytes" },
1910 # endif /* RLIMIT_HEAP */
1912 # ifdef RLIMIT_NOFILE
1913 { RLIMIT_NOFILE
, "descriptors", 1, "" },
1914 # endif /* RLIMIT_NOFILE */
1916 # ifdef RLIMIT_CONCUR
1917 { RLIMIT_CONCUR
, "concurrency", 1, "thread(s)" },
1918 # endif /* RLIMIT_CONCUR */
1920 # ifdef RLIMIT_MEMLOCK
1921 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1922 # endif /* RLIMIT_MEMLOCK */
1924 # ifdef RLIMIT_NPROC
1925 { RLIMIT_NPROC
, "maxproc", 1, "" },
1926 # endif /* RLIMIT_NPROC */
1928 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1929 { RLIMIT_OFILE
, "openfiles", 1, "" },
1930 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1932 # ifdef RLIMIT_SBSIZE
1933 { RLIMIT_SBSIZE
, "sbsize", 1, "" },
1934 # endif /* RLIMIT_SBSIZE */
1936 #ifdef RLIMIT_POSIXLOCKS
1937 { RLIMIT_POSIXLOCKS
, "posixlocks", 1, "" },
1938 #endif /* RLIMIT_POSIXLOCKS */
1941 { RLIMIT_SWAP
, "swapsize", 1024, "kbytes" },
1942 # endif /* RLIMIT_SWAP */
1944 { -1, NULL
, 0, NULL
}
1947 static struct limits
*findlim (Char
*);
1948 static RLIM_TYPE
getval (struct limits
*, Char
**);
1949 static void limtail (Char
*, const char *);
1950 static void plim (struct limits
*, int);
1951 static int setlim (struct limits
*, int, RLIM_TYPE
);
1955 restrict_limit(double value
)
1958 * is f too large to cope with? return the maximum or minimum int
1960 if (value
> (double) INT_MAX
)
1961 return (RLIM_TYPE
) INT_MAX
;
1962 else if (value
< (double) INT_MIN
)
1963 return (RLIM_TYPE
) INT_MIN
;
1965 return (RLIM_TYPE
) value
;
1968 # define restrict_limit(x) ((RLIM_TYPE) (x))
1972 static struct limits
*
1975 struct limits
*lp
, *res
;
1978 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1979 if (prefix(cp
, str2short(lp
->limname
))) {
1981 stderror(ERR_NAME
| ERR_AMBIG
);
1986 stderror(ERR_NAME
| ERR_LIMIT
);
1993 dolimit(Char
**v
, struct command
*c
)
2001 if (*v
&& eq(*v
, STRmh
)) {
2006 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2015 limit
= getval(lp
, v
+ 1);
2016 if (setlim(lp
, hard
, limit
) < 0)
2017 stderror(ERR_SILENT
);
2021 getval(struct limits
*lp
, Char
**v
)
2026 f
= atof(short2str(cp
));
2030 * is f too large to cope with. limit f to minint, maxint - X-6768 by
2033 if ((f
< (double) INT_MIN
) || (f
> (double) INT_MAX
)) {
2034 stderror(ERR_NAME
| ERR_TOOLARGE
);
2036 # endif /* convex */
2038 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
2042 return restrict_limit((f
* lp
->limdiv
) + 0.5);
2048 if (lp
->limconst
!= RLIMIT_CPU
)
2050 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
* 60.0 + atof(short2str(cp
+ 1))));
2052 if (lp
->limconst
!= RLIMIT_CPU
)
2054 limtail(cp
, "hours");
2058 if (lp
->limconst
== RLIMIT_CPU
) {
2059 limtail(cp
, "minutes");
2064 limtail(cp
, "megabytes");
2065 f
*= 1024.0 * 1024.0;
2068 if (lp
->limconst
!= RLIMIT_CPU
)
2070 limtail(cp
, "seconds");
2072 # endif /* RLIMIT_CPU */
2075 if (lp
->limconst
== RLIMIT_CPU
)
2077 # endif /* RLIMIT_CPU */
2079 limtail(cp
, "megabytes");
2080 f
*= 1024.0 * 1024.0;
2084 if (lp
->limconst
== RLIMIT_CPU
)
2086 # endif /* RLIMIT_CPU */
2087 limtail(cp
, "kbytes");
2092 if (lp
->limconst
== RLIMIT_CPU
)
2094 # endif /* RLIMIT_CPU */
2095 limtail(cp
, "blocks");
2099 limtail(cp
, "unlimited");
2100 return ((RLIM_TYPE
) RLIM_INFINITY
);
2104 # endif /* RLIMIT_CPU */
2105 stderror(ERR_NAME
| ERR_SCALEF
);
2108 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
+ 0.5));
2111 if (f
> (float) RLIM_INFINITY
)
2112 return ((RLIM_TYPE
) RLIM_INFINITY
);
2114 return ((RLIM_TYPE
) f
);
2115 # endif /* convex */
2119 limtail(Char
*cp
, const char *str
)
2124 while (*cp
&& *cp
== (Char
)*str
)
2127 stderror(ERR_BADSCALE
, sp
);
2133 plim(struct limits
*lp
, int hard
)
2137 # endif /* BSDLIMIT */
2139 int xdiv
= lp
->limdiv
;
2141 xprintf("%-13.13s", lp
->limname
);
2144 limit
= ulimit(lp
->limconst
, 0);
2146 if (lp
->limconst
== RLIMIT_DATA
)
2147 limit
-= 0x20000000;
2149 # else /* BSDLIMIT */
2150 (void) getrlimit(lp
->limconst
, &rlim
);
2151 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
2152 # endif /* BSDLIMIT */
2154 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2156 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2157 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2159 if (lp
->limconst
== RLIMIT_FSIZE
) {
2160 if (limit
>= (RLIM_INFINITY
/ 512))
2161 limit
= RLIM_INFINITY
;
2163 xdiv
= (xdiv
== 1024 ? 2 : 1);
2165 # endif /* !BSDLIMIT || FILESIZE512 */
2167 if (limit
== RLIM_INFINITY
)
2168 xprintf("unlimited");
2170 # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
2171 if (lp
->limconst
== RLIMIT_CPU
&&
2172 (unsigned long)limit
>= 0x7ffffffdUL
)
2173 xprintf("unlimited");
2177 if (lp
->limconst
== RLIMIT_CPU
)
2180 # endif /* RLIMIT_CPU */
2181 xprintf("%ld %s", (long) (limit
/ xdiv
), lp
->limscale
);
2187 dounlimit(Char
**v
, struct command
*c
)
2195 while (*++v
&& **v
== '-') {
2206 stderror(ERR_ULIMUS
);
2212 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2213 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0)
2216 stderror(ERR_SILENT
);
2221 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0 && !force
)
2222 stderror(ERR_SILENT
);
2227 setlim(struct limits
*lp
, int hard
, RLIM_TYPE limit
)
2232 (void) getrlimit(lp
->limconst
, &rlim
);
2235 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2236 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2238 # endif /* FILESIZE512 */
2240 rlim
.rlim_max
= limit
;
2241 else if (limit
== RLIM_INFINITY
&& euid
!= 0)
2242 rlim
.rlim_cur
= rlim
.rlim_max
;
2244 rlim
.rlim_cur
= limit
;
2246 if (rlim
.rlim_cur
> rlim
.rlim_max
)
2247 rlim
.rlim_max
= rlim
.rlim_cur
;
2249 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
2250 # else /* BSDLIMIT */
2251 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2254 if (lp
->limconst
== RLIMIT_DATA
)
2255 limit
+= 0x20000000;
2257 if (ulimit(toset(lp
->limconst
), limit
) < 0) {
2258 # endif /* BSDLIMIT */
2263 op
= strsave(limit
== RLIM_INFINITY
? CGETS(15, 2, "remove") :
2264 CGETS(15, 3, "set"));
2265 cleanup_push(op
, xfree
);
2266 type
= strsave(hard
? CGETS(15, 4, " hard") : "");
2267 cleanup_push(type
, xfree
);
2268 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname
,
2269 lp
->limname
, op
, type
, strerror(err
));
2276 #endif /* !HAVENOLIMIT */
2280 dosuspend(Char
**v
, struct command
*c
)
2283 struct sigaction old
;
2284 #endif /* BSDJOBS */
2290 stderror(ERR_SUSPLOG
);
2294 sigaction(SIGTSTP
, NULL
, &old
);
2295 signal(SIGTSTP
, SIG_DFL
);
2296 (void) kill(0, SIGTSTP
);
2297 /* the shell stops here */
2298 sigaction(SIGTSTP
, &old
, NULL
);
2299 #else /* !BSDJOBS */
2300 stderror(ERR_JOBCONTROL
);
2301 #endif /* BSDJOBS */
2305 if (grabpgrp(FSHTTY
, opgrp
) == -1)
2306 stderror(ERR_SYSTEM
, "tcgetpgrp", strerror(errno
));
2307 (void) setpgid(0, shpgrp
);
2308 (void) tcsetpgrp(FSHTTY
, shpgrp
);
2310 #endif /* BSDJOBS */
2311 (void) setdisc(FSHTTY
);
2314 /* This is the dreaded EVAL built-in.
2315 * If you don't fiddle with file descriptors, and reset didfds,
2316 * this command will either ignore redirection inside or outside
2317 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2318 * The stuff here seems to work, but I did it by trial and error rather
2319 * than really knowing what was going on. If tpgrp is zero, we are
2320 * probably a background eval, e.g. "eval date &", and we want to
2321 * make sure that any processes we start stay in our pgrp.
2322 * This is also the case for "time eval date" -- stay in same pgrp.
2323 * Otherwise, under stty tostop, processes will stop in the wrong
2324 * pgrp, with no way for the shell to get them going again. -IAN!
2329 Char
**evalvec
, *evalp
;
2331 #ifndef CLOSE_ON_EXEC
2334 int saveIN
, saveOUT
, saveDIAG
;
2335 int SHIN
, SHOUT
, SHDIAG
;
2339 doeval_cleanup(void *xstate
)
2341 struct doeval_state
*state
;
2344 evalvec
= state
->evalvec
;
2345 evalp
= state
->evalp
;
2347 #ifndef CLOSE_ON_EXEC
2348 didcch
= state
->didcch
;
2349 #endif /* CLOSE_ON_EXEC */
2350 didfds
= state
->didfds
;
2354 close_on_exec(SHIN
= dmove(state
->saveIN
, state
->SHIN
), 1);
2355 close_on_exec(SHOUT
= dmove(state
->saveOUT
, state
->SHOUT
), 1);
2356 close_on_exec(SHDIAG
= dmove(state
->saveDIAG
, state
->SHDIAG
), 1);
2362 doeval(Char
**v
, struct command
*c
)
2364 struct doeval_state state
;
2365 int gflag
, my_reenter
;
2375 gv
= v
= globall(v
, gflag
);
2377 stderror(ERR_NOMATCH
);
2378 cleanup_push(gv
, blk_cleanup
);
2388 state
.evalvec
= evalvec
;
2389 state
.evalp
= evalp
;
2390 state
.didfds
= didfds
;
2391 #ifndef CLOSE_ON_EXEC
2392 state
.didcch
= didcch
;
2393 #endif /* CLOSE_ON_EXEC */
2395 state
.SHOUT
= SHOUT
;
2396 state
.SHDIAG
= SHDIAG
;
2398 (void)close_on_exec(state
.saveIN
= dcopy(SHIN
, -1), 1);
2399 (void)close_on_exec(state
.saveOUT
= dcopy(SHOUT
, -1), 1);
2400 (void)close_on_exec(state
.saveDIAG
= dcopy(SHDIAG
, -1), 1);
2402 cleanup_push(&state
, doeval_cleanup
);
2406 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
2408 my_reenter
= 1; /* assume non-zero return val */
2409 if (setexit() == 0) {
2410 my_reenter
= 0; /* Oh well, we were wrong */
2412 if ((my_reenter
= setexit()) == 0) {
2416 (void)close_on_exec(SHIN
= dcopy(0, -1), 1);
2417 (void)close_on_exec(SHOUT
= dcopy(1, -1), 1);
2418 (void)close_on_exec(SHDIAG
= dcopy(2, -1), 1);
2419 #ifndef CLOSE_ON_EXEC
2421 #endif /* CLOSE_ON_EXEC */
2428 if (my_reenter
== 0) {
2429 cleanup_until(&state
);
2436 stderror(ERR_SILENT
);
2439 /*************************************************************************/
2440 /* print list of builtin commands */
2443 lbuffed_cleanup (void *dummy
)
2451 dobuiltins(Char
**v
, struct command
*c
)
2453 /* would use print_by_column() in tw.parse.c but that assumes
2454 * we have an array of Char * to pass.. (sg)
2456 const struct biltins
*b
;
2457 int row
, col
, columns
, rows
;
2458 unsigned int w
, maxwidth
;
2462 lbuffed
= 0; /* turn off line buffering */
2463 cleanup_push(&lbuffed
, lbuffed_cleanup
);
2465 /* find widest string */
2466 for (maxwidth
= 0, b
= bfunc
; b
< &bfunc
[nbfunc
]; ++b
)
2467 maxwidth
= max(maxwidth
, strlen(b
->bname
));
2468 ++maxwidth
; /* for space */
2470 columns
= (TermH
+ 1) / maxwidth
; /* PWP: terminal size change */
2473 rows
= (nbfunc
+ (columns
- 1)) / columns
;
2475 for (b
= bfunc
, row
= 0; row
< rows
; row
++) {
2476 for (col
= 0; col
< columns
; col
++) {
2477 if (b
< &bfunc
[nbfunc
]) {
2478 w
= strlen(b
->bname
);
2479 xprintf("%s", b
->bname
);
2480 if (col
< (columns
- 1)) /* Not last column? */
2481 for (; w
< maxwidth
; w
++)
2486 if (row
< (rows
- 1)) {
2493 nt_print_builtins(maxwidth
);
2498 #endif /* WINNT_NATIVE */
2500 cleanup_until(&lbuffed
); /* turn back on line buffering */
2506 xcatgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2511 while ((res
= catgets(ctd
, set_id
, msg_id
, s
)) == s
&& errno
== EINTR
) {
2512 handle_pending_signals();
2519 # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2521 iconv_catgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2523 static char *buf
= NULL
;
2524 static size_t buf_size
= 0;
2526 char *orig
, *dest
, *p
;
2527 ICONV_CONST
char *src
;
2528 size_t src_size
, dest_size
;
2530 orig
= xcatgets(ctd
, set_id
, msg_id
, s
);
2531 if (catgets_iconv
== (iconv_t
)-1 || orig
== s
)
2534 src_size
= strlen(src
) + 1;
2535 if (buf
== NULL
&& (buf
= xmalloc(buf_size
= src_size
+ 32)) == NULL
)
2538 while (src_size
!= 0) {
2539 dest_size
= buf
+ buf_size
- dest
;
2540 if (iconv(catgets_iconv
, &src
, &src_size
, &dest
, &dest_size
)
2544 if ((p
= xrealloc(buf
, buf_size
* 2)) == NULL
)
2547 dest
= p
+ (dest
- buf
);
2551 case EILSEQ
: case EINVAL
: default:
2558 # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2559 #endif /* NLS_CATALOGS */
2565 static const char default_catalog
[] = "tcsh";
2567 char *catalog
= (char *)(intptr_t)default_catalog
;
2569 if (adrof(STRcatalog
) != NULL
)
2570 catalog
= xasprintf("tcsh.%s", short2str(varval(STRcatalog
)));
2571 catd
= catopen(catalog
, MCLoadBySet
);
2572 if (catalog
!= default_catalog
)
2574 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2575 /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
2576 catgets_iconv
= iconv_open (nl_langinfo (CODESET
),
2577 xcatgets(catd
, 255, 1, "ASCII"));
2578 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2579 #endif /* NLS_CATALOGS */
2582 #endif /* WINNT_NATIVE */
2583 errinit(); /* init the errorlist in correct locale */
2584 mesginit(); /* init the messages for signals */
2585 dateinit(); /* init the messages for dates */
2586 editinit(); /* init the editor messages */
2587 terminit(); /* init the termcap messages */
2594 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2595 if (catgets_iconv
!= (iconv_t
)-1) {
2596 iconv_close(catgets_iconv
);
2597 catgets_iconv
= (iconv_t
)-1;
2599 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2600 if (catd
!= (nl_catd
)-1) {
2602 * catclose can call other functions which can call longjmp
2603 * making us re-enter this code. Prevent infinite recursion
2604 * by resetting catd. Problem reported and solved by:
2607 nl_catd oldcatd
= catd
;
2609 while (catclose(oldcatd
) == -1 && errno
== EINTR
)
2610 handle_pending_signals();
2612 #endif /* NLS_CATALOGS */