1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.func.c,v 3.143 2006/08/24 20:56:31 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.143 2006/08/24 20:56:31 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 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
);
525 while (*cp
&& alnum(*cp
))
528 stderror(ERR_NAME
| ERR_VARALNUM
);
530 if (v
[0][0] != '(' || v
[blklen(v
) - 1][0] != ')')
531 stderror(ERR_NAME
| ERR_NOPAREN
);
535 v
= globall(v
, gflag
);
536 if (v
== 0 && !noexec
)
537 stderror(ERR_NAME
| ERR_NOMATCH
);
543 nwp
= xcalloc(1, sizeof *nwp
);
544 nwp
->w_fe
= nwp
->w_fe0
= v
;
545 btell(&nwp
->w_start
);
546 nwp
->w_fename
= Strsave(cp
);
547 nwp
->w_next
= whyles
;
548 nwp
->w_end
.type
= TCSH_F_SEEK
;
551 * Pre-read the loop so as to be more comprehensible to a terminal user.
562 dowhile(Char
**v
, struct command
*c
)
565 int again
= whyles
!= 0 &&
566 SEEKEQ(&whyles
->w_start
, &lineloc
) &&
567 whyles
->w_fename
== 0;
572 * Implement prereading here also, taking care not to evaluate the
573 * expression before the loop has been read up from a terminal.
577 else if (intty
&& !again
)
578 status
= !exp0(&v
, 1);
582 stderror(ERR_NAME
| ERR_EXPRESSION
);
584 struct whyle
*nwp
= xcalloc(1, sizeof(*nwp
));
586 nwp
->w_start
= lineloc
;
587 nwp
->w_end
.type
= TCSH_F_SEEK
;
588 nwp
->w_end
.f_seek
= 0;
589 nwp
->w_next
= whyles
;
602 /* We ain't gonna loop no more, no more! */
609 int old_pintr_disabled
;
611 whyles
->w_end
.type
= TCSH_I_SEEK
;
613 pintr_push_enable(&old_pintr_disabled
);
614 search(TC_BREAK
, 0, NULL
); /* read the expression in */
616 cleanup_until(&old_pintr_disabled
);
617 btell(&whyles
->w_end
);
622 doend(Char
**v
, struct command
*c
)
627 stderror(ERR_NAME
| ERR_NOTWHILE
);
628 btell(&whyles
->w_end
);
635 docontin(Char
**v
, struct command
*c
)
640 stderror(ERR_NAME
| ERR_NOTWHILE
);
648 /* Repeating a while is simple */
649 if (whyles
->w_fename
== 0) {
650 bseek(&whyles
->w_start
);
654 * The foreach variable list actually has a spurious word ")" at the end of
655 * the w_fe list. Thus we are at the of the list if one word beyond this
658 if (!whyles
->w_fe
[1]) {
662 setv(whyles
->w_fename
, quote(Strsave(*whyles
->w_fe
++)), VAR_READWRITE
);
663 bseek(&whyles
->w_start
);
667 dorepeat(Char
**v
, struct command
*kp
)
674 } while (v
[0] != NULL
&& Strcmp(v
[0], STRrepeat
) == 0);
680 cleanup_push(&pintr_disabled
, disabled_cleanup
);
683 if (setintr
&& pintr_disabled
== 1) {
684 cleanup_until(&pintr_disabled
);
686 cleanup_push(&pintr_disabled
, disabled_cleanup
);
691 cleanup_until(&pintr_disabled
);
697 doswbrk(Char
**v
, struct command
*c
)
702 search(TC_BRKSW
, 0, NULL
);
708 struct srch
*sp
, *sp1
, *sp2
;
712 * Ignore keywords inside heredocs
718 * Binary search Sp1 is the beginning of the current search range. Sp2 is
721 for (sp1
= srchn
, sp2
= srchn
+ nsrchn
; sp1
< sp2
;) {
722 sp
= sp1
+ ((sp2
- sp1
) >> 1);
723 if ((i
= *cp
- *sp
->s_name
) == 0 &&
724 (i
= Strcmp(cp
, str2short(sp
->s_name
))) == 0)
737 struct srch
*sp
, *sp2
;
739 for (sp
= srchn
, sp2
= srchn
+ nsrchn
; sp
< sp2
; sp
++)
740 if (sp
->s_value
== n
)
750 search(int type
, int level
, Char
*goal
)
752 struct Strbuf word
= Strbuf_INIT
;
759 if (type
== TC_GOTO
) {
761 a
.type
= TCSH_F_SEEK
;
765 cleanup_push(&word
, Strbuf_cleanup
);
767 if (intty
&& fseekp
== feobp
&& aret
== TCSH_F_SEEK
)
768 printprompt(1, isrchx(type
== TC_BREAK
? zlast
: type
));
769 /* xprintf("? "), flush(); */
770 (void) getword(&word
);
771 Strbuf_terminate(&word
);
772 switch (srchx(word
.s
)) {
775 if (level
== 0 && type
== TC_IF
)
780 while (getword(&word
))
782 if ((type
== TC_IF
|| type
== TC_ELSE
) &&
788 if (type
== TC_IF
|| type
== TC_ELSE
)
795 if (type
== TC_BREAK
)
800 if (type
== TC_BRKSW
) {
809 if (type
== TC_BREAK
)
815 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
820 if (type
== TC_SWITCH
|| type
== TC_BRKSW
)
825 if (type
== TC_GOTO
&& getword(&word
) && eq(word
.s
, goal
))
830 if (type
!= TC_GOTO
&& (type
!= TC_SWITCH
|| level
!= 0))
832 if (word
.len
== 0 || word
.s
[word
.len
- 1] != ':')
834 word
.s
[--word
.len
] = 0;
835 if ((type
== TC_GOTO
&& eq(word
.s
, goal
)) ||
836 (type
== TC_SWITCH
&& eq(word
.s
, STRdefault
)))
841 if (type
!= TC_SWITCH
|| level
!= 0)
843 (void) getword(&word
);
844 if (word
.len
!= 0 && word
.s
[word
.len
- 1] == ':')
845 word
.s
[--word
.len
] = 0;
846 cp
= strip(Dfix1(word
.s
));
847 cleanup_push(cp
, xfree
);
848 if (Gmatch(goal
, cp
))
854 if (type
== TC_SWITCH
&& level
== 0)
858 (void) getword(NULL
);
859 } while (level
>= 0);
861 cleanup_until(&word
);
865 getword(struct Strbuf
*wp
)
867 int found
= 0, first
;
875 while (c
== ' ' || c
== '\t')
880 while (c
!= CHAR_ERR
&& c
!= '\n');
893 if (c
== '\\' && (c
= readc(1)) == '\n')
895 if (c
== '\'' || c
== '"') {
904 Strbuf_append1(wp
, (Char
) c
);
905 if (!first
&& !d
&& c
== '(') {
912 } while ((d
|| (c
!= ' ' && c
!= '\t')) && c
!= '\n');
919 Strbuf_terminate(wp
);
928 stderror(ERR_NAME
| ERR_NOTFOUND
, "then/endif");
932 stderror(ERR_NAME
| ERR_NOTFOUND
, "endif");
937 stderror(ERR_NAME
| ERR_NOTFOUND
, "endsw");
941 stderror(ERR_NAME
| ERR_NOTFOUND
, "end");
945 setname(short2str(Sgoal
));
946 stderror(ERR_NAME
| ERR_NOTFOUND
, "label");
959 if (whyles
->w_end
.type
== TCSH_F_SEEK
&& whyles
->w_end
.f_seek
== 0) {
960 search(TC_BREAK
, 0, NULL
);
961 btell(&whyles
->w_end
);
962 whyles
->w_end
.f_seek
--;
965 bseek(&whyles
->w_end
);
971 wpfree(struct whyle
*wp
)
985 nwp
= NULL
; /* sun lint is dumb! */
989 static const char foo
[] = "IAFE";
995 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
996 foo
[o
.type
+ 1], o
.a_seek
, o
.f_seek
);
999 for (; whyles
; whyles
= nwp
) {
1000 struct whyle
*wp
= whyles
;
1004 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1005 foo
[wp
->w_start
.type
+1],
1006 wp
->w_start
.a_seek
, wp
->w_start
.f_seek
);
1007 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1008 foo
[wp
->w_end
.type
+ 1], wp
->w_end
.a_seek
, wp
->w_end
.f_seek
);
1012 * XXX: We free loops that have different seek types.
1014 if (wp
->w_end
.type
!= TCSH_I_SEEK
&& wp
->w_start
.type
== wp
->w_end
.type
&&
1015 wp
->w_start
.type
== o
.type
) {
1016 if (wp
->w_end
.type
== TCSH_F_SEEK
) {
1017 if (o
.f_seek
>= wp
->w_start
.f_seek
&&
1018 (wp
->w_end
.f_seek
== 0 || o
.f_seek
< wp
->w_end
.f_seek
))
1022 if (o
.a_seek
>= wp
->w_start
.a_seek
&&
1023 (wp
->w_end
.a_seek
== 0 || o
.a_seek
< wp
->w_end
.a_seek
))
1034 doecho(Char
**v
, struct command
*c
)
1042 doglob(Char
**v
, struct command
*c
)
1050 xecho(int sep
, Char
**v
)
1052 Char
*cp
, **globbed
= NULL
;
1054 int echo_style
= ECHO_STYLE
;
1057 if ((vp
= adrof(STRecho_style
)) != NULL
&& vp
->vec
!= NULL
&&
1058 vp
->vec
[0] != NULL
) {
1059 if (Strcmp(vp
->vec
[0], STRbsd
) == 0)
1060 echo_style
= BSD_ECHO
;
1061 else if (Strcmp(vp
->vec
[0], STRsysv
) == 0)
1062 echo_style
= SYSV_ECHO
;
1063 else if (Strcmp(vp
->vec
[0], STRboth
) == 0)
1064 echo_style
= BOTH_ECHO
;
1065 else if (Strcmp(vp
->vec
[0], STRnone
) == 0)
1066 echo_style
= NONE_ECHO
;
1073 int old_pintr_disabled
;
1074 pintr_push_enable(&old_pintr_disabled
);
1075 v
= glob_all_or_error(v
);
1076 cleanup_until(&old_pintr_disabled
);
1078 v
= glob_all_or_error(v
);
1081 if (globbed
!= NULL
)
1082 cleanup_push(globbed
, blk_cleanup
);
1084 if ((echo_style
& BSD_ECHO
) != 0 && sep
== ' ' && *v
&& eq(*v
, STRmn
))
1087 while ((cp
= *v
++) != 0) {
1091 int old_pintr_disabled
;
1093 pintr_push_enable(&old_pintr_disabled
);
1094 cleanup_until(&old_pintr_disabled
);
1096 while ((c
= *cp
++) != 0) {
1097 if ((echo_style
& SYSV_ECHO
) != 0 && c
== '\\') {
1098 switch (c
= *cp
++) {
1109 #if 0 /* Windows does not understand \e */
1112 c
= CTL_ESC('\033');
1135 if (*cp
>= '0' && *cp
< '8')
1136 c
= c
* 8 + *cp
++ - '0';
1137 if (*cp
>= '0' && *cp
< '8')
1138 c
= c
* 8 + *cp
++ - '0';
1139 if (*cp
>= '0' && *cp
< '8')
1140 c
= c
* 8 + *cp
++ - '0';
1147 xputchar('\\' | QUOTE
);
1151 xputwchar(c
| QUOTE
);
1155 xputchar(sep
| QUOTE
);
1158 if (sep
&& nonl
== 0)
1162 if (globbed
!= NULL
)
1163 cleanup_until(globbed
);
1166 /* check whether an environment variable should invoke 'set_locale()' */
1168 islocale_var(Char
*var
)
1170 static Char
*locale_vars
[] = {
1171 STRLANG
, STRLC_ALL
, STRLC_CTYPE
, STRLC_NUMERIC
,
1172 STRLC_TIME
, STRLC_COLLATE
, STRLC_MESSAGES
, STRLC_MONETARY
, 0
1176 for (v
= locale_vars
; *v
; ++v
)
1183 xlate_cr_cleanup(void *dummy
)
1191 doprintenv(Char
**v
, struct command
*c
)
1201 cleanup_push(&xlate_cr
, xlate_cr_cleanup
);
1202 for (ep
= STR_environ
; *ep
; ep
++) {
1204 int old_pintr_disabled
;
1206 pintr_push_enable(&old_pintr_disabled
);
1207 cleanup_until(&old_pintr_disabled
);
1209 xprintf("%S\n", *ep
);
1211 cleanup_until(&xlate_cr
);
1213 else if ((e
= tgetenv(*v
)) != NULL
) {
1216 old_output_raw
= output_raw
;
1218 cleanup_push(&old_output_raw
, output_raw_restore
);
1220 cleanup_until(&old_output_raw
);
1223 setcopy(STRstatus
, STR1
, VAR_READWRITE
);
1226 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1227 (and anything else with a modern compiler) */
1231 dosetenv(Char
**v
, struct command
*c
)
1245 for (; *lp
!= '\0' ; lp
++) {
1247 stderror(ERR_NAME
| ERR_SYNTAX
);
1249 if ((lp
= *v
++) == 0)
1252 lp
= globone(lp
, G_APPEND
);
1253 cleanup_push(lp
, xfree
);
1255 if (eq(vp
, STRKPATH
)) {
1263 if (eq(vp
, STRSYSTYPE
)) {
1270 /* dspkanji/dspmbyte autosetting */
1271 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1272 #if defined(DSPMBYTE)
1273 if(eq(vp
, STRLANG
) && !adrof(CHECK_MBYTEVAR
)) {
1274 autoset_dspmbyte(lp
);
1278 if (islocale_var(vp
)) {
1282 # ifdef SETLOCALEBUG
1284 # endif /* SETLOCALEBUG */
1285 (void) setlocale(LC_ALL
, "");
1287 (void) setlocale(LC_COLLATE
, "");
1290 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1291 # endif /* LC_CTYPE */
1292 # ifdef NLS_CATALOGS
1294 (void) setlocale(LC_MESSAGES
, "");
1295 # endif /* LC_MESSAGES */
1298 # endif /* NLS_CATALOGS */
1299 # ifdef SETLOCALEBUG
1301 # endif /* SETLOCALEBUG */
1304 # endif /* STRCOLLBUG */
1305 tw_cmd_free(); /* since the collation sequence has changed */
1306 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1308 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1312 NLSMapsAreInited
= 0;
1314 if (MapsAreInited
&& !NLSMapsAreInited
)
1321 if (eq(vp
, STRNLSPATH
)) {
1327 if (eq(vp
, STRNOREBIND
)) {
1330 NLSMapsAreInited
= 0;
1336 if (eq(vp
, STRtcshlang
)) {
1341 #endif /* WINNT_NATIVE */
1342 if (eq(vp
, STRKTERM
)) {
1345 setv(STRterm
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1349 if (noediting
&& strcmp(t
, "unknown") != 0 && strcmp(t
,"dumb") != 0) {
1359 if (eq(vp
, STRKHOME
)) {
1362 * convert to canonical pathname (possibly resolving symlinks)
1364 canon
= dcanon(lp
, lp
);
1367 cleanup_push(canon
, xfree
);
1368 setv(STRhome
, quote(canon
), VAR_READWRITE
); /* lp memory used here */
1369 cleanup_ignore(canon
);
1370 cleanup_until(canon
);
1372 /* fix directory stack for new tilde home */
1377 if (eq(vp
, STRKSHLVL
)) {
1378 setv(STRshlvl
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1384 if (eq(vp
, STRKUSER
)) {
1385 setv(STRuser
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1391 if (eq(vp
, STRKGROUP
)) {
1392 setv(STRgroup
, quote(lp
), VAR_READWRITE
); /* lp memory used here */
1399 if (eq(vp
, STRLS_COLORS
)) {
1404 #endif /* COLOR_LS_F */
1408 * Load/Update $LINES $COLUMNS
1410 if ((eq(lp
, STRNULL
) && (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
))) ||
1411 eq(vp
, STRTERMCAP
)) {
1413 check_window_size(1);
1418 * Change the size to the one directed by $LINES and $COLUMNS
1420 if (eq(vp
, STRLINES
) || eq(vp
, STRCOLUMNS
)) {
1428 #endif /* SIG_WINDOW */
1434 dounsetenv(Char
**v
, struct command
*c
)
1436 Char
**ep
, *p
, *n
, *name
;
1441 * Find the longest environment variable
1443 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1444 for (i
= 0, p
= *ep
; *p
&& *p
!= '='; p
++, i
++)
1450 name
= xmalloc((maxi
+ 1) * sizeof(Char
));
1451 cleanup_push(name
, xfree
);
1454 for (maxi
= 1; maxi
;)
1455 for (maxi
= 0, ep
= STR_environ
; *ep
; ep
++) {
1456 for (n
= name
, p
= *ep
; *p
&& *p
!= '='; *n
++ = *p
++)
1459 if (!Gmatch(name
, *v
))
1463 /* Unset the name. This wasn't being done until
1464 * later but most of the stuff following won't
1465 * work (particularly the setlocale() and getenv()
1466 * stuff) as intended until the name is actually
1471 if (eq(name
, STRNOREBIND
)) {
1474 NLSMapsAreInited
= 0;
1478 else if (eq(name
, STRSYSTYPE
))
1481 else if (islocale_var(name
)) {
1485 # ifdef SETLOCALEBUG
1487 # endif /* SETLOCALEBUG */
1488 (void) setlocale(LC_ALL
, "");
1490 (void) setlocale(LC_COLLATE
, "");
1493 (void) setlocale(LC_CTYPE
, ""); /* for iscntrl */
1494 # endif /* LC_CTYPE */
1495 # ifdef NLS_CATALOGS
1497 (void) setlocale(LC_MESSAGES
, "");
1498 # endif /* LC_MESSAGES */
1501 # endif /* NLS_CATALOGS */
1502 # ifdef SETLOCALEBUG
1504 # endif /* SETLOCALEBUG */
1507 # endif /* STRCOLLBUG */
1508 tw_cmd_free();/* since the collation sequence has changed */
1509 for (k
= 0200; k
<= 0377 && !Isprint(CTL_ESC(k
)); k
++)
1511 AsciiOnly
= MB_CUR_MAX
== 1 && k
> 0377;
1513 AsciiOnly
= getenv("LANG") == NULL
&&
1514 getenv("LC_CTYPE") == NULL
;
1516 NLSMapsAreInited
= 0;
1518 if (MapsAreInited
&& !NLSMapsAreInited
)
1523 else if (eq(name
,(STRtcshlang
))) {
1527 #endif /* WINNT_NATIVE */
1529 else if (eq(name
, STRLS_COLORS
))
1531 #endif /* COLOR_LS_F */
1533 else if (eq(name
, STRNLSPATH
)) {
1539 * start again cause the environment changes
1543 cleanup_until(name
);
1547 tsetenv(const Char
*name
, const Char
*val
)
1549 #ifdef SETENV_IN_LIB
1551 * XXX: This does not work right, since tcsh cannot track changes to
1552 * the environment this way. (the builtin setenv without arguments does
1553 * not print the right stuff neither does unsetenv). This was for Mach,
1554 * it is not needed anymore.
1561 cname
= strsave(short2str(name
));
1562 setenv(cname
, short2str(val
), 1);
1564 #else /* !SETENV_IN_LIB */
1565 Char
**ep
= STR_environ
;
1572 nt_set_env(name
,val
);
1573 #endif /* WINNT_NATIVE */
1576 for (ccp
= name
, dp
= *ep
; *ccp
&& Tolower(*ccp
& TRIM
) == Tolower(*dp
);
1579 for (ccp
= name
, dp
= *ep
; *ccp
&& (*ccp
& TRIM
) == *dp
; ccp
++, dp
++)
1580 #endif /* WINNT_NATIVE */
1582 if (*ccp
!= 0 || *dp
!= '=')
1584 cp
= Strspl(STRequal
, val
);
1586 *ep
= strip(Strspl(name
, cp
));
1588 blkfree((Char
**) environ
);
1589 environ
= short2blk(STR_environ
);
1592 cp
= Strspl(name
, STRequal
);
1593 blk
[0] = strip(Strspl(cp
, val
));
1596 STR_environ
= blkspl(STR_environ
, blk
);
1597 blkfree((Char
**) environ
);
1598 environ
= short2blk(STR_environ
);
1600 #endif /* SETENV_IN_LIB */
1604 Unsetenv(Char
*name
)
1606 Char
**ep
= STR_environ
;
1611 nt_set_env(name
,NULL
);
1612 #endif /*WINNT_NATIVE */
1614 for (cp
= name
, dp
= *ep
; *cp
&& *cp
== *dp
; cp
++, dp
++)
1616 if (*cp
!= 0 || *dp
!= '=')
1620 STR_environ
= blkspl(STR_environ
, ep
+ 1);
1621 blkfree((Char
**) environ
);
1622 environ
= short2blk(STR_environ
);
1632 doumask(Char
**v
, struct command
*c
)
1645 while (Isdigit(*cp
) && *cp
!= '8' && *cp
!= '9')
1646 i
= i
* 8 + *cp
++ - '0';
1647 if (*cp
|| i
< 0 || i
> 0777)
1648 stderror(ERR_NAME
| ERR_MASK
);
1654 typedef long RLIM_TYPE
;
1655 # ifdef _OSD_POSIX /* BS2000 */
1656 # include <ulimit.h>
1658 # ifndef RLIM_INFINITY
1659 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1660 extern RLIM_TYPE
ulimit();
1661 # endif /* ! _MINIX && !__clipper__ */
1662 # define RLIM_INFINITY 0x003fffff
1663 # define RLIMIT_FSIZE 1
1664 # endif /* RLIM_INFINITY */
1666 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1667 # define RLIMIT_DATA 3
1668 # define RLIMIT_STACK 1005
1670 # define toset(a) ((a) + 1)
1672 # else /* BSDLIMIT */
1673 # if (defined(BSD4_4) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (HPUXVERSION >= 1100)) && !defined(__386BSD__)
1674 typedef rlim_t RLIM_TYPE
;
1676 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1677 typedef rlim_t RLIM_TYPE
;
1680 typedef long long RLIM_TYPE
;
1682 typedef unsigned long RLIM_TYPE
;
1684 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1685 # endif /* BSD4_4 && !__386BSD__ */
1686 # endif /* BSDLIMIT */
1688 # if (HPUXVERSION > 700) && (HPUXVERSION < 1100) && defined(BSDLIMIT)
1689 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1690 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1692 # define RLIMIT_CPU 0
1693 # define RLIMIT_FSIZE 1
1694 # define RLIMIT_DATA 2
1695 # define RLIMIT_STACK 3
1696 # define RLIMIT_CORE 4
1697 # define RLIMIT_RSS 5
1698 # define RLIMIT_NOFILE 6
1699 # endif /* RLIMIT_CPU */
1700 # ifndef RLIM_INFINITY
1701 # define RLIM_INFINITY 0x7fffffff
1702 # endif /* RLIM_INFINITY */
1704 * old versions of HP/UX counted limits in 512 bytes
1707 # define FILESIZE512
1708 # endif /* SIGRTMIN */
1709 # endif /* (HPUXVERSION > 700) && (HPUXVERSION < 1100) && BSDLIMIT */
1711 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1712 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1713 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1714 /* than include both and get warnings, we define the extra SVR4 limits here. */
1715 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1716 /* RLIMIT_VMEM based on it? */
1717 # ifndef RLIMIT_VMEM
1718 # define RLIMIT_VMEM 6
1721 # define RLIMIT_AS RLIMIT_VMEM
1723 # endif /* SYSVREL > 3 && BSDLIMIT */
1725 # if (defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1726 # define RLIMIT_VMEM RLIMIT_AS
1729 struct limits limits
[] =
1732 { RLIMIT_CPU
, "cputime", 1, "seconds" },
1733 # endif /* RLIMIT_CPU */
1735 # ifdef RLIMIT_FSIZE
1737 { RLIMIT_FSIZE
, "filesize", 1024, "kbytes" },
1739 { RLIMIT_FSIZE
, "filesize", 512, "blocks" },
1741 # endif /* RLIMIT_FSIZE */
1744 { RLIMIT_DATA
, "datasize", 1024, "kbytes" },
1745 # endif /* RLIMIT_DATA */
1747 # ifdef RLIMIT_STACK
1749 { RLIMIT_STACK
, "stacksize", 1024, "kbytes" },
1751 { RLIMIT_STACK
, "stacksize", 1024 * 1024, "kbytes"},
1753 # endif /* RLIMIT_STACK */
1756 { RLIMIT_CORE
, "coredumpsize", 1024, "kbytes" },
1757 # endif /* RLIMIT_CORE */
1760 { RLIMIT_RSS
, "memoryuse", 1024, "kbytes" },
1761 # endif /* RLIMIT_RSS */
1764 { RLIMIT_UMEM
, "memoryuse", 1024, "kbytes" },
1765 # endif /* RLIMIT_UMEM */
1768 { RLIMIT_VMEM
, "vmemoryuse", 1024, "kbytes" },
1769 # endif /* RLIMIT_VMEM */
1771 # if defined(RLIMIT_HEAP) /* found on BS2000/OSD systems */
1772 { RLIMIT_HEAP
, "heapsize", 1024, "kbytes" },
1773 # endif /* RLIMIT_HEAP */
1775 # ifdef RLIMIT_NOFILE
1776 { RLIMIT_NOFILE
, "descriptors", 1, "" },
1777 # endif /* RLIMIT_NOFILE */
1779 # ifdef RLIMIT_CONCUR
1780 { RLIMIT_CONCUR
, "concurrency", 1, "thread(s)" },
1781 # endif /* RLIMIT_CONCUR */
1783 # ifdef RLIMIT_MEMLOCK
1784 { RLIMIT_MEMLOCK
, "memorylocked", 1024, "kbytes" },
1785 # endif /* RLIMIT_MEMLOCK */
1787 # ifdef RLIMIT_NPROC
1788 { RLIMIT_NPROC
, "maxproc", 1, "" },
1789 # endif /* RLIMIT_NPROC */
1791 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1792 { RLIMIT_OFILE
, "openfiles", 1, "" },
1793 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1795 # ifdef RLIMIT_SBSIZE
1796 { RLIMIT_SBSIZE
, "sbsize", 1, "" },
1797 # endif /* RLIMIT_SBSIZE */
1798 #ifdef RLIMIT_POSIXLOCKS
1799 { RLIMIT_POSIXLOCKS
, "posixlocks", 1, "" },
1800 #endif /* RLIMIT_POSIXLOCKS */
1801 { -1, NULL
, 0, NULL
}
1804 static struct limits
*findlim (Char
*);
1805 static RLIM_TYPE
getval (struct limits
*, Char
**);
1806 static void limtail (Char
*, const char *);
1807 static void plim (struct limits
*, int);
1808 static int setlim (struct limits
*, int, RLIM_TYPE
);
1812 restrict_limit(double value
)
1815 * is f too large to cope with? return the maximum or minimum int
1817 if (value
> (double) INT_MAX
)
1818 return (RLIM_TYPE
) INT_MAX
;
1819 else if (value
< (double) INT_MIN
)
1820 return (RLIM_TYPE
) INT_MIN
;
1822 return (RLIM_TYPE
) value
;
1825 # define restrict_limit(x) ((RLIM_TYPE) (x))
1829 static struct limits
*
1832 struct limits
*lp
, *res
;
1835 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1836 if (prefix(cp
, str2short(lp
->limname
))) {
1838 stderror(ERR_NAME
| ERR_AMBIG
);
1843 stderror(ERR_NAME
| ERR_LIMIT
);
1850 dolimit(Char
**v
, struct command
*c
)
1858 if (*v
&& eq(*v
, STRmh
)) {
1863 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
1872 limit
= getval(lp
, v
+ 1);
1873 if (setlim(lp
, hard
, limit
) < 0)
1874 stderror(ERR_SILENT
);
1878 getval(struct limits
*lp
, Char
**v
)
1883 f
= atof(short2str(cp
));
1887 * is f too large to cope with. limit f to minint, maxint - X-6768 by
1890 if ((f
< (double) INT_MIN
) || (f
> (double) INT_MAX
)) {
1891 stderror(ERR_NAME
| ERR_TOOLARGE
);
1893 # endif /* convex */
1895 while (Isdigit(*cp
) || *cp
== '.' || *cp
== 'e' || *cp
== 'E')
1899 return restrict_limit((f
* lp
->limdiv
) + 0.5);
1905 if (lp
->limconst
!= RLIMIT_CPU
)
1907 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
* 60.0 + atof(short2str(cp
+ 1))));
1909 if (lp
->limconst
!= RLIMIT_CPU
)
1911 limtail(cp
, "hours");
1915 if (lp
->limconst
== RLIMIT_CPU
) {
1916 limtail(cp
, "minutes");
1921 limtail(cp
, "megabytes");
1922 f
*= 1024.0 * 1024.0;
1925 if (lp
->limconst
!= RLIMIT_CPU
)
1927 limtail(cp
, "seconds");
1929 # endif /* RLIMIT_CPU */
1932 if (lp
->limconst
== RLIMIT_CPU
)
1934 # endif /* RLIMIT_CPU */
1936 limtail(cp
, "megabytes");
1937 f
*= 1024.0 * 1024.0;
1941 if (lp
->limconst
== RLIMIT_CPU
)
1943 # endif /* RLIMIT_CPU */
1944 limtail(cp
, "kbytes");
1949 if (lp
->limconst
== RLIMIT_CPU
)
1951 # endif /* RLIMIT_CPU */
1952 limtail(cp
, "blocks");
1956 limtail(cp
, "unlimited");
1957 return ((RLIM_TYPE
) RLIM_INFINITY
);
1961 # endif /* RLIMIT_CPU */
1962 stderror(ERR_NAME
| ERR_SCALEF
);
1965 return f
== 0.0 ? (RLIM_TYPE
) 0 : restrict_limit((f
+ 0.5));
1968 if (f
> (float) RLIM_INFINITY
)
1969 return ((RLIM_TYPE
) RLIM_INFINITY
);
1971 return ((RLIM_TYPE
) f
);
1972 # endif /* convex */
1976 limtail(Char
*cp
, const char *str
)
1981 while (*cp
&& *cp
== (Char
)*str
)
1984 stderror(ERR_BADSCALE
, sp
);
1990 plim(struct limits
*lp
, int hard
)
1994 # endif /* BSDLIMIT */
1996 int xdiv
= lp
->limdiv
;
1998 xprintf("%-13.13s", lp
->limname
);
2001 limit
= ulimit(lp
->limconst
, 0);
2003 if (lp
->limconst
== RLIMIT_DATA
)
2004 limit
-= 0x20000000;
2006 # else /* BSDLIMIT */
2007 (void) getrlimit(lp
->limconst
, &rlim
);
2008 limit
= hard
? rlim
.rlim_max
: rlim
.rlim_cur
;
2009 # endif /* BSDLIMIT */
2011 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2013 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2014 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2016 if (lp
->limconst
== RLIMIT_FSIZE
) {
2017 if (limit
>= (RLIM_INFINITY
/ 512))
2018 limit
= RLIM_INFINITY
;
2020 xdiv
= (xdiv
== 1024 ? 2 : 1);
2022 # endif /* !BSDLIMIT || FILESIZE512 */
2024 if (limit
== RLIM_INFINITY
)
2025 xprintf("unlimited");
2027 # if defined(RLIMIT_CPU) && defined(_OSD_POSIX)
2028 if (lp
->limconst
== RLIMIT_CPU
&&
2029 (unsigned long)limit
>= 0x7ffffffdUL
)
2030 xprintf("unlimited");
2034 if (lp
->limconst
== RLIMIT_CPU
)
2037 # endif /* RLIMIT_CPU */
2038 xprintf("%ld %s", (long) (limit
/ xdiv
), lp
->limscale
);
2044 dounlimit(Char
**v
, struct command
*c
)
2052 while (*++v
&& **v
== '-') {
2063 stderror(ERR_ULIMUS
);
2069 for (lp
= limits
; lp
->limconst
>= 0; lp
++)
2070 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0)
2073 stderror(ERR_SILENT
);
2078 if (setlim(lp
, hard
, (RLIM_TYPE
) RLIM_INFINITY
) < 0 && !force
)
2079 stderror(ERR_SILENT
);
2084 setlim(struct limits
*lp
, int hard
, RLIM_TYPE limit
)
2089 (void) getrlimit(lp
->limconst
, &rlim
);
2092 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2093 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2095 # endif /* FILESIZE512 */
2097 rlim
.rlim_max
= limit
;
2098 else if (limit
== RLIM_INFINITY
&& euid
!= 0)
2099 rlim
.rlim_cur
= rlim
.rlim_max
;
2101 rlim
.rlim_cur
= limit
;
2103 if (rlim
.rlim_cur
> rlim
.rlim_max
)
2104 rlim
.rlim_max
= rlim
.rlim_cur
;
2106 if (setrlimit(lp
->limconst
, &rlim
) < 0) {
2107 # else /* BSDLIMIT */
2108 if (limit
!= RLIM_INFINITY
&& lp
->limconst
== RLIMIT_FSIZE
)
2111 if (lp
->limconst
== RLIMIT_DATA
)
2112 limit
+= 0x20000000;
2114 if (ulimit(toset(lp
->limconst
), limit
) < 0) {
2115 # endif /* BSDLIMIT */
2120 op
= strsave(limit
== RLIM_INFINITY
? CGETS(15, 2, "remove") :
2121 CGETS(15, 3, "set"));
2122 cleanup_push(op
, xfree
);
2123 type
= strsave(hard
? CGETS(15, 4, " hard") : "");
2124 cleanup_push(type
, xfree
);
2125 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname
,
2126 lp
->limname
, op
, type
, strerror(err
));
2133 #endif /* !HAVENOLIMIT */
2137 dosuspend(Char
**v
, struct command
*c
)
2141 struct sigaction old
;
2142 #endif /* BSDJOBS */
2148 stderror(ERR_SUSPLOG
);
2152 sigaction(SIGTSTP
, NULL
, &old
);
2153 signal(SIGTSTP
, SIG_DFL
);
2154 (void) kill(0, SIGTSTP
);
2155 /* the shell stops here */
2156 sigaction(SIGTSTP
, &old
, NULL
);
2157 #else /* !BSDJOBS */
2158 stderror(ERR_JOBCONTROL
);
2159 #endif /* BSDJOBS */
2164 ctpgrp
= tcgetpgrp(FSHTTY
);
2166 stderror(ERR_SYSTEM
, "tcgetpgrp", strerror(errno
));
2167 if (ctpgrp
!= opgrp
) {
2168 sigaction(SIGTTIN
, NULL
, &old
);
2169 signal(SIGTTIN
, SIG_DFL
);
2170 (void) kill(0, SIGTTIN
);
2171 sigaction(SIGTTIN
, &old
, NULL
);
2174 (void) setpgid(0, shpgrp
);
2175 (void) tcsetpgrp(FSHTTY
, shpgrp
);
2177 #endif /* BSDJOBS */
2178 (void) setdisc(FSHTTY
);
2181 /* This is the dreaded EVAL built-in.
2182 * If you don't fiddle with file descriptors, and reset didfds,
2183 * this command will either ignore redirection inside or outside
2184 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2185 * The stuff here seems to work, but I did it by trial and error rather
2186 * than really knowing what was going on. If tpgrp is zero, we are
2187 * probably a background eval, e.g. "eval date &", and we want to
2188 * make sure that any processes we start stay in our pgrp.
2189 * This is also the case for "time eval date" -- stay in same pgrp.
2190 * Otherwise, under stty tostop, processes will stop in the wrong
2191 * pgrp, with no way for the shell to get them going again. -IAN!
2196 Char
**evalvec
, *evalp
;
2198 #ifndef CLOSE_ON_EXEC
2201 int saveIN
, saveOUT
, saveDIAG
;
2202 int SHIN
, SHOUT
, SHDIAG
;
2206 doeval_cleanup(void *xstate
)
2208 struct doeval_state
*state
;
2211 evalvec
= state
->evalvec
;
2212 evalp
= state
->evalp
;
2214 #ifndef CLOSE_ON_EXEC
2215 didcch
= state
->didcch
;
2216 #endif /* CLOSE_ON_EXEC */
2217 didfds
= state
->didfds
;
2221 close_on_exec(SHIN
= dmove(state
->saveIN
, state
->SHIN
), 1);
2222 close_on_exec(SHOUT
= dmove(state
->saveOUT
, state
->SHOUT
), 1);
2223 close_on_exec(SHDIAG
= dmove(state
->saveDIAG
, state
->SHDIAG
), 1);
2228 doeval(Char
**v
, struct command
*c
)
2230 struct doeval_state state
;
2240 gv
= v
= globall(v
, gflag
);
2242 stderror(ERR_NOMATCH
);
2243 cleanup_push(gv
, blk_cleanup
);
2252 state
.evalvec
= evalvec
;
2253 state
.evalp
= evalp
;
2254 state
.didfds
= didfds
;
2255 #ifndef CLOSE_ON_EXEC
2256 state
.didcch
= didcch
;
2257 #endif /* CLOSE_ON_EXEC */
2259 state
.SHOUT
= SHOUT
;
2260 state
.SHDIAG
= SHDIAG
;
2262 (void)close_on_exec(state
.saveIN
= dcopy(SHIN
, -1), 1);
2263 (void)close_on_exec(state
.saveOUT
= dcopy(SHOUT
, -1), 1);
2264 (void)close_on_exec(state
.saveDIAG
= dcopy(SHDIAG
, -1), 1);
2266 cleanup_push(&state
, doeval_cleanup
);
2270 (void)close_on_exec(SHIN
= dcopy(0, -1), 1);
2271 (void)close_on_exec(SHOUT
= dcopy(1, -1), 1);
2272 (void)close_on_exec(SHDIAG
= dcopy(2, -1), 1);
2273 #ifndef CLOSE_ON_EXEC
2275 #endif /* CLOSE_ON_EXEC */
2279 cleanup_until(&state
);
2285 /*************************************************************************/
2286 /* print list of builtin commands */
2289 lbuffed_cleanup (void *dummy
)
2297 dobuiltins(Char
**v
, struct command
*c
)
2299 /* would use print_by_column() in tw.parse.c but that assumes
2300 * we have an array of Char * to pass.. (sg)
2302 const struct biltins
*b
;
2303 int row
, col
, columns
, rows
;
2304 unsigned int w
, maxwidth
;
2308 lbuffed
= 0; /* turn off line buffering */
2309 cleanup_push(&lbuffed
, lbuffed_cleanup
);
2311 /* find widest string */
2312 for (maxwidth
= 0, b
= bfunc
; b
< &bfunc
[nbfunc
]; ++b
)
2313 maxwidth
= max(maxwidth
, strlen(b
->bname
));
2314 ++maxwidth
; /* for space */
2316 columns
= (TermH
+ 1) / maxwidth
; /* PWP: terminal size change */
2319 rows
= (nbfunc
+ (columns
- 1)) / columns
;
2321 for (b
= bfunc
, row
= 0; row
< rows
; row
++) {
2322 for (col
= 0; col
< columns
; col
++) {
2323 if (b
< &bfunc
[nbfunc
]) {
2324 w
= strlen(b
->bname
);
2325 xprintf("%s", b
->bname
);
2326 if (col
< (columns
- 1)) /* Not last column? */
2327 for (; w
< maxwidth
; w
++)
2332 if (row
< (rows
- 1)) {
2339 nt_print_builtins(maxwidth
);
2344 #endif /* WINNT_NATIVE */
2346 cleanup_until(&lbuffed
); /* turn back on line buffering */
2352 xcatgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2357 while ((res
= catgets(ctd
, set_id
, msg_id
, s
)) == s
&& errno
== EINTR
) {
2358 handle_pending_signals();
2365 # if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2367 iconv_catgets(nl_catd ctd
, int set_id
, int msg_id
, const char *s
)
2369 static char *buf
= NULL
;
2370 static size_t buf_size
= 0;
2372 char *orig
, *dest
, *p
;
2373 ICONV_CONST
char *src
;
2374 size_t src_size
, dest_size
;
2376 orig
= xcatgets(ctd
, set_id
, msg_id
, s
);
2377 if (catgets_iconv
== (iconv_t
)-1 || orig
== s
)
2380 src_size
= strlen(src
) + 1;
2381 if (buf
== NULL
&& (buf
= xmalloc(buf_size
= src_size
+ 32)) == NULL
)
2384 while (src_size
!= 0) {
2385 dest_size
= buf
+ buf_size
- dest
;
2386 if (iconv(catgets_iconv
, &src
, &src_size
, &dest
, &dest_size
)
2390 if ((p
= xrealloc(buf
, buf_size
* 2)) == NULL
)
2393 dest
= p
+ (dest
- buf
);
2397 case EILSEQ
: case EINVAL
: default:
2404 # endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2405 #endif /* NLS_CATALOGS */
2411 static const char default_catalog
[] = "tcsh";
2413 char *catalog
= (char *)(intptr_t)default_catalog
;
2415 if (adrof(STRcatalog
) != NULL
)
2416 catalog
= xasprintf("tcsh.%s", short2str(varval(STRcatalog
)));
2417 catd
= catopen(catalog
, MCLoadBySet
);
2418 if (catalog
!= default_catalog
)
2420 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2421 /* xcatgets (), not CGETS, the charset name should be in ASCII anyway. */
2422 catgets_iconv
= iconv_open (nl_langinfo (CODESET
),
2423 xcatgets(catd
, 255, 1, "ASCII"));
2424 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2425 #endif /* NLS_CATALOGS */
2428 #endif /* WINNT_NATIVE */
2429 errinit(); /* init the errorlist in correct locale */
2430 mesginit(); /* init the messages for signals */
2431 dateinit(); /* init the messages for dates */
2432 editinit(); /* init the editor messages */
2433 terminit(); /* init the termcap messages */
2440 #if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO)
2441 if (catgets_iconv
!= (iconv_t
)-1) {
2442 iconv_close(catgets_iconv
);
2443 catgets_iconv
= (iconv_t
)-1;
2445 #endif /* HAVE_ICONV && HAVE_NL_LANGINFO */
2446 if (catd
!= (nl_catd
)-1) {
2448 * catclose can call other functions which can call longjmp
2449 * making us re-enter this code. Prevent infinite recursion
2450 * by resetting catd. Problem reported and solved by:
2453 nl_catd oldcatd
= catd
;
2455 while (catclose(oldcatd
) == -1 && errno
== EINTR
)
2456 handle_pending_signals();
2458 #endif /* NLS_CATALOGS */