After the channel TX power bug fixing in rt2560_read_config(), it is impossble
[dragonfly.git] / contrib / tcsh / sh.func.c
blobb74b42b999cad451b46cf93820e450a9c0f459e4
1 /* $Header: /src/pub/tcsh/sh.func.c,v 3.103 2002/07/09 12:56:55 christos Exp $ */
2 /*
3 * sh.func.c: csh builtin functions
4 */
5 /*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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
31 * SUCH DAMAGE.
33 #include "sh.h"
35 RCSID("$Id: sh.func.c,v 3.103 2002/07/09 12:56:55 christos Exp $")
37 #include "ed.h"
38 #include "tw.h"
39 #include "tc.h"
40 #ifdef WINNT_NATIVE
41 #include "nt.const.h"
42 #endif /* WINNT_NATIVE */
45 * C shell
47 extern int just_signaled;
48 extern char **environ;
50 extern bool MapsAreInited;
51 extern bool NLSMapsAreInited;
52 extern bool NoNLSRebind;
53 extern bool GotTermCaps;
55 static int zlast = -1;
57 static void islogin __P((void));
58 static void preread __P((void));
59 static void doagain __P((void));
60 static char *isrchx __P((int));
61 static void search __P((int, int, Char *));
62 static int getword __P((Char *));
63 static void toend __P((void));
64 static void xecho __P((int, Char **));
65 static bool islocale_var __P((Char *));
67 struct biltins *
68 isbfunc(t)
69 struct command *t;
71 register Char *cp = t->t_dcom[0];
72 register struct biltins *bp, *bp1, *bp2;
73 static struct biltins label = {"", dozip, 0, 0};
74 static struct biltins foregnd = {"%job", dofg1, 0, 0};
75 static struct biltins backgnd = {"%job &", dobg1, 0, 0};
78 * We never match a builtin that has quoted the first
79 * character; this has been the traditional way to escape
80 * builtin commands.
82 if (*cp & QUOTE)
83 return NULL;
85 if (*cp != ':' && lastchr(cp) == ':') {
86 label.bname = short2str(cp);
87 return (&label);
89 if (*cp == '%') {
90 if (t->t_dflg & F_AMPERSAND) {
91 t->t_dflg &= ~F_AMPERSAND;
92 backgnd.bname = short2str(cp);
93 return (&backgnd);
95 foregnd.bname = short2str(cp);
96 return (&foregnd);
98 #ifdef WARP
100 * This is a perhaps kludgy way to determine if the warp builtin is to be
101 * acknowledged or not. If checkwarp() fails, then we are to assume that
102 * the warp command is invalid, and carry on as we would handle any other
103 * non-builtin command. -- JDK 2/4/88
105 if (eq(STRwarp, cp) && !checkwarp()) {
106 return (0); /* this builtin disabled */
108 #endif /* WARP */
110 * Binary search Bp1 is the beginning of the current search range. Bp2 is
111 * one past the end.
113 for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
114 int i;
116 bp = bp1 + ((bp2 - bp1) >> 1);
117 if ((i = ((char) *cp) - *bp->bname) == 0 &&
118 (i = StrQcmp(cp, str2short(bp->bname))) == 0)
119 return bp;
120 if (i < 0)
121 bp2 = bp;
122 else
123 bp1 = bp + 1;
125 #ifdef WINNT_NATIVE
126 return nt_check_additional_builtins(cp);
127 #endif /*WINNT_NATIVE*/
128 return (0);
131 void
132 func(t, bp)
133 register struct command *t;
134 register struct biltins *bp;
136 int i;
138 xechoit(t->t_dcom);
139 setname(bp->bname);
140 i = blklen(t->t_dcom) - 1;
141 if (i < bp->minargs)
142 stderror(ERR_NAME | ERR_TOOFEW);
143 if (i > bp->maxargs)
144 stderror(ERR_NAME | ERR_TOOMANY);
145 (*bp->bfunct) (t->t_dcom, t);
148 /*ARGSUSED*/
149 void
150 doonintr(v, c)
151 Char **v;
152 struct command *c;
154 register Char *cp;
155 register Char *vv = v[1];
157 USE(c);
158 if (parintr == SIG_IGN)
159 return;
160 if (setintr && intty)
161 stderror(ERR_NAME | ERR_TERMINAL);
162 cp = gointr;
163 gointr = 0;
164 xfree((ptr_t) cp);
165 if (vv == 0) {
166 #ifdef BSDSIGS
167 if (setintr) {
168 (void) sigblock(sigmask(SIGINT));
169 (void) signal(SIGINT, pintr);
171 else
172 (void) signal(SIGINT, SIG_DFL);
173 #else /* !BSDSIGS */
174 if (setintr) {
175 (void) sighold(SIGINT);
176 (void) sigset(SIGINT, pintr);
178 else
179 (void) sigset(SIGINT, SIG_DFL);
180 #endif /* BSDSIGS */
181 gointr = 0;
183 else if (eq((vv = strip(vv)), STRminus)) {
184 #ifdef BSDSIGS
185 (void) signal(SIGINT, SIG_IGN);
186 #else /* !BSDSIGS */
187 (void) sigset(SIGINT, SIG_IGN);
188 #endif /* BSDSIGS */
189 gointr = Strsave(STRminus);
191 else {
192 gointr = Strsave(vv);
193 #ifdef BSDSIGS
194 (void) signal(SIGINT, pintr);
195 #else /* !BSDSIGS */
196 (void) sigset(SIGINT, pintr);
197 #endif /* BSDSIGS */
201 /*ARGSUSED*/
202 void
203 donohup(v, c)
204 Char **v;
205 struct command *c;
207 USE(c);
208 USE(v);
209 if (intty)
210 stderror(ERR_NAME | ERR_TERMINAL);
211 if (setintr == 0) {
212 (void) signal(SIGHUP, SIG_IGN);
213 #ifdef CC
214 submit(getpid());
215 #endif /* CC */
219 /*ARGSUSED*/
220 void
221 dohup(v, c)
222 Char **v;
223 struct command *c;
225 USE(c);
226 USE(v);
227 if (intty)
228 stderror(ERR_NAME | ERR_TERMINAL);
229 if (setintr == 0)
230 (void) signal(SIGHUP, SIG_DFL);
234 /*ARGSUSED*/
235 void
236 dozip(v, c)
237 Char **v;
238 struct command *c;
240 USE(c);
241 USE(v);
244 /*ARGSUSED*/
245 void
246 dofiletest(v, c)
247 Char **v;
248 struct command *c;
250 Char **fileptr, *ftest, *res;
252 if (*(ftest = *++v) != '-')
253 stderror(ERR_NAME | ERR_FILEINQ);
254 ++v;
256 gflag = 0;
257 tglob(v);
258 if (gflag) {
259 v = globall(v);
260 if (v == 0)
261 stderror(ERR_NAME | ERR_NOMATCH);
263 else
264 v = gargv = saveblk(v);
265 trim(v);
267 while (*(fileptr = v++) != '\0') {
268 xprintf("%S", res = filetest(ftest, &fileptr, 0));
269 xfree((ptr_t) res);
270 if (*v)
271 xprintf(" ");
273 xprintf("\n");
275 if (gargv) {
276 blkfree(gargv);
277 gargv = 0;
281 void
282 prvars()
284 plist(&shvhed, VAR_ALL);
287 /*ARGSUSED*/
288 void
289 doalias(v, c)
290 register Char **v;
291 struct command *c;
293 register struct varent *vp;
294 register Char *p;
296 USE(c);
297 v++;
298 p = *v++;
299 if (p == 0)
300 plist(&aliases, VAR_ALL);
301 else if (*v == 0) {
302 vp = adrof1(strip(p), &aliases);
303 if (vp && vp->vec)
304 blkpr(vp->vec), xputchar('\n');
306 else {
307 if (eq(p, STRalias) || eq(p, STRunalias)) {
308 setname(short2str(p));
309 stderror(ERR_NAME | ERR_DANGER);
311 set1(strip(p), saveblk(v), &aliases, VAR_READWRITE);
312 tw_cmd_free();
316 /*ARGSUSED*/
317 void
318 unalias(v, c)
319 Char **v;
320 struct command *c;
322 USE(c);
323 unset1(v, &aliases);
324 tw_cmd_free();
327 /*ARGSUSED*/
328 void
329 dologout(v, c)
330 Char **v;
331 struct command *c;
333 USE(c);
334 USE(v);
335 islogin();
336 goodbye(NULL, NULL);
339 /*ARGSUSED*/
340 void
341 dologin(v, c)
342 Char **v;
343 struct command *c;
345 USE(c);
346 #ifdef WINNT_NATIVE
347 USE(v);
348 #else /* !WINNT_NATIVE */
349 islogin();
350 rechist(NULL, adrof(STRsavehist) != NULL);
351 (void) signal(SIGTERM, parterm);
352 (void) execl(_PATH_BIN_LOGIN, "login", short2str(v[1]), NULL);
353 (void) execl(_PATH_USRBIN_LOGIN, "login", short2str(v[1]), NULL);
354 untty();
355 xexit(1);
356 #endif /* !WINNT_NATIVE */
360 #ifdef NEWGRP
361 /*ARGSUSED*/
362 void
363 donewgrp(v, c)
364 Char **v;
365 struct command *c;
367 char **p;
368 if (chkstop == 0 && setintr)
369 panystop(0);
370 (void) signal(SIGTERM, parterm);
371 p = short2blk(v);
373 * From Beto Appleton (beto@aixwiz.austin.ibm.com)
374 * Newgrp can take 2 arguments...
376 (void) execv(_PATH_BIN_NEWGRP, p);
377 (void) execv(_PATH_USRBIN_NEWGRP, p);
378 blkfree((Char **) p);
379 untty();
380 xexit(1);
382 #endif /* NEWGRP */
384 static void
385 islogin()
387 if (chkstop == 0 && setintr)
388 panystop(0);
389 if (loginsh)
390 return;
391 stderror(ERR_NOTLOGIN);
394 void
395 doif(v, kp)
396 Char **v;
397 struct command *kp;
399 register int i;
400 register Char **vv;
402 v++;
403 i = expr(&v);
404 vv = v;
405 if (*vv == NULL)
406 stderror(ERR_NAME | ERR_EMPTYIF);
407 if (eq(*vv, STRthen)) {
408 if (*++vv)
409 stderror(ERR_NAME | ERR_IMPRTHEN);
410 setname(short2str(STRthen));
412 * If expression was zero, then scan to else , otherwise just fall into
413 * following code.
415 if (!i)
416 search(TC_IF, 0, NULL);
417 return;
420 * Simple command attached to this if. Left shift the node in this tree,
421 * munging it so we can reexecute it.
423 if (i) {
424 lshift(kp->t_dcom, vv - kp->t_dcom);
425 reexecute(kp);
426 donefds();
431 * Reexecute a command, being careful not
432 * to redo i/o redirection, which is already set up.
434 void
435 reexecute(kp)
436 register struct command *kp;
438 kp->t_dflg &= F_SAVE;
439 kp->t_dflg |= F_REPEAT;
441 * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
442 * pgrp's as the jobs would then have no way to get the tty (we can't give
443 * it to them, and our parent wouldn't know their pgrp, etc.
445 execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL, TRUE);
448 /*ARGSUSED*/
449 void
450 doelse (v, c)
451 Char **v;
452 struct command *c;
454 USE(c);
455 USE(v);
456 search(TC_ELSE, 0, NULL);
459 /*ARGSUSED*/
460 void
461 dogoto(v, c)
462 Char **v;
463 struct command *c;
465 Char *lp;
467 USE(c);
468 gotolab(lp = globone(v[1], G_ERROR));
469 xfree((ptr_t) lp);
472 void
473 gotolab(lab)
474 Char *lab;
476 register struct whyle *wp;
478 * While we still can, locate any unknown ends of existing loops. This
479 * obscure code is the WORST result of the fact that we don't really parse.
481 zlast = TC_GOTO;
482 for (wp = whyles; wp; wp = wp->w_next)
483 if (wp->w_end.type == TCSH_F_SEEK && wp->w_end.f_seek == 0) {
484 search(TC_BREAK, 0, NULL);
485 btell(&wp->w_end);
487 else {
488 bseek(&wp->w_end);
490 search(TC_GOTO, 0, lab);
492 * Eliminate loops which were exited.
494 wfree();
497 /*ARGSUSED*/
498 void
499 doswitch(v, c)
500 register Char **v;
501 struct command *c;
503 register Char *cp, *lp;
505 USE(c);
506 v++;
507 if (!*v || *(*v++) != '(')
508 stderror(ERR_SYNTAX);
509 cp = **v == ')' ? STRNULL : *v++;
510 if (*(*v++) != ')')
511 v--;
512 if (*v)
513 stderror(ERR_SYNTAX);
514 search(TC_SWITCH, 0, lp = globone(cp, G_ERROR));
515 xfree((ptr_t) lp);
518 /*ARGSUSED*/
519 void
520 dobreak(v, c)
521 Char **v;
522 struct command *c;
524 USE(v);
525 USE(c);
526 if (whyles)
527 toend();
528 else
529 stderror(ERR_NAME | ERR_NOTWHILE);
532 /*ARGSUSED*/
533 void
534 doexit(v, c)
535 Char **v;
536 struct command *c;
538 USE(c);
540 if (chkstop == 0 && (intty || intact) && evalvec == 0)
541 panystop(0);
543 * Don't DEMAND parentheses here either.
545 v++;
546 if (*v) {
547 set(STRstatus, putn(expr(&v)), VAR_READWRITE);
548 if (*v)
549 stderror(ERR_NAME | ERR_EXPRESSION);
551 btoeof();
552 #if 0
553 if (intty)
554 #endif
555 /* Always close, why only on ttys? */
556 (void) close(SHIN);
559 /*ARGSUSED*/
560 void
561 doforeach(v, c)
562 register Char **v;
563 struct command *c;
565 register Char *cp, *sp;
566 register struct whyle *nwp;
568 USE(c);
569 v++;
570 sp = cp = strip(*v);
571 if (!letter(*sp))
572 stderror(ERR_NAME | ERR_VARBEGIN);
573 while (*cp && alnum(*cp))
574 cp++;
575 if (*cp)
576 stderror(ERR_NAME | ERR_VARALNUM);
577 if ((cp - sp) > MAXVARLEN)
578 stderror(ERR_NAME | ERR_VARTOOLONG);
579 cp = *v++;
580 if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
581 stderror(ERR_NAME | ERR_NOPAREN);
582 v++;
583 gflag = 0, tglob(v);
584 if (gflag) {
585 v = globall(v);
586 if (v == 0)
587 stderror(ERR_NAME | ERR_NOMATCH);
589 else {
590 v = gargv = saveblk(v);
591 trim(v);
593 nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
594 nwp->w_fe = nwp->w_fe0 = v;
595 gargv = 0;
596 btell(&nwp->w_start);
597 nwp->w_fename = Strsave(cp);
598 nwp->w_next = whyles;
599 nwp->w_end.type = TCSH_F_SEEK;
600 whyles = nwp;
602 * Pre-read the loop so as to be more comprehensible to a terminal user.
604 zlast = TC_FOREACH;
605 if (intty)
606 preread();
607 doagain();
610 /*ARGSUSED*/
611 void
612 dowhile(v, c)
613 Char **v;
614 struct command *c;
616 register int status;
617 register bool again = whyles != 0 &&
618 SEEKEQ(&whyles->w_start, &lineloc) &&
619 whyles->w_fename == 0;
621 USE(c);
622 v++;
624 * Implement prereading here also, taking care not to evaluate the
625 * expression before the loop has been read up from a terminal.
627 if (intty && !again)
628 status = !exp0(&v, 1);
629 else
630 status = !expr(&v);
631 if (*v)
632 stderror(ERR_NAME | ERR_EXPRESSION);
633 if (!again) {
634 register struct whyle *nwp =
635 (struct whyle *) xcalloc(1, sizeof(*nwp));
637 nwp->w_start = lineloc;
638 nwp->w_end.type = TCSH_F_SEEK;
639 nwp->w_end.f_seek = 0;
640 nwp->w_next = whyles;
641 whyles = nwp;
642 zlast = TC_WHILE;
643 if (intty) {
645 * The tty preread
647 preread();
648 doagain();
649 return;
652 if (status)
653 /* We ain't gonna loop no more, no more! */
654 toend();
657 static void
658 preread()
660 whyles->w_end.type = TCSH_I_SEEK;
661 if (setintr)
662 #ifdef BSDSIGS
663 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
664 #else /* !BSDSIGS */
665 (void) sigrelse (SIGINT);
666 #endif /* BSDSIGS */
667 search(TC_BREAK, 0, NULL); /* read the expression in */
668 if (setintr)
669 #ifdef BSDSIGS
670 (void) sigblock(sigmask(SIGINT));
671 #else /* !BSDSIGS */
672 (void) sighold(SIGINT);
673 #endif /* BSDSIGS */
674 btell(&whyles->w_end);
677 /*ARGSUSED*/
678 void
679 doend(v, c)
680 Char **v;
681 struct command *c;
683 USE(v);
684 USE(c);
685 if (!whyles)
686 stderror(ERR_NAME | ERR_NOTWHILE);
687 btell(&whyles->w_end);
688 doagain();
691 /*ARGSUSED*/
692 void
693 docontin(v, c)
694 Char **v;
695 struct command *c;
697 USE(v);
698 USE(c);
699 if (!whyles)
700 stderror(ERR_NAME | ERR_NOTWHILE);
701 doagain();
704 static void
705 doagain()
707 /* Repeating a while is simple */
708 if (whyles->w_fename == 0) {
709 bseek(&whyles->w_start);
710 return;
713 * The foreach variable list actually has a spurious word ")" at the end of
714 * the w_fe list. Thus we are at the of the list if one word beyond this
715 * is 0.
717 if (!whyles->w_fe[1]) {
718 dobreak(NULL, NULL);
719 return;
721 set(whyles->w_fename, quote(Strsave(*whyles->w_fe++)), VAR_READWRITE);
722 bseek(&whyles->w_start);
725 void
726 dorepeat(v, kp)
727 Char **v;
728 struct command *kp;
730 int i = 1;
732 #ifdef BSDSIGS
733 register sigmask_t omask = 0;
734 #endif /* BSDSIGS */
736 do {
737 i *= getn(v[1]);
738 lshift(v, 2);
739 } while (v[0] != NULL && Strcmp(v[0], STRrepeat) == 0);
741 if (setintr)
742 #ifdef BSDSIGS
743 omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
744 #else /* !BSDSIGS */
745 (void) sighold(SIGINT);
746 #endif /* BSDSIGS */
747 while (i > 0) {
748 if (setintr)
749 #ifdef BSDSIGS
750 (void) sigsetmask(omask);
751 #else /* !BSDSIGS */
752 (void) sigrelse (SIGINT);
753 #endif /* BSDSIGS */
754 reexecute(kp);
755 --i;
757 donefds();
758 if (setintr)
759 #ifdef BSDSIGS
760 (void) sigsetmask(omask);
761 #else /* !BSDSIGS */
762 (void) sigrelse (SIGINT);
763 #endif /* BSDSIGS */
766 /*ARGSUSED*/
767 void
768 doswbrk(v, c)
769 Char **v;
770 struct command *c;
772 USE(v);
773 USE(c);
774 search(TC_BRKSW, 0, NULL);
778 srchx(cp)
779 Char *cp;
781 struct srch *sp, *sp1, *sp2;
782 int i;
785 * Ignore keywords inside heredocs
787 if (inheredoc)
788 return -1;
791 * Binary search Sp1 is the beginning of the current search range. Sp2 is
792 * one past the end.
794 for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
795 sp = sp1 + ((sp2 - sp1) >> 1);
796 if ((i = *cp - *sp->s_name) == 0 &&
797 (i = Strcmp(cp, str2short(sp->s_name))) == 0)
798 return sp->s_value;
799 if (i < 0)
800 sp2 = sp;
801 else
802 sp1 = sp + 1;
804 return (-1);
807 static char *
808 isrchx(n)
809 register int n;
811 register struct srch *sp, *sp2;
813 for (sp = srchn, sp2 = srchn + nsrchn; sp < sp2; sp++)
814 if (sp->s_value == n)
815 return (sp->s_name);
816 return ("");
820 static Char Stype;
821 static Char *Sgoal;
823 static void
824 search(type, level, goal)
825 int type;
826 register int level;
827 Char *goal;
829 Char wordbuf[BUFSIZE];
830 register Char *aword = wordbuf;
831 register Char *cp;
833 Stype = (Char) type;
834 Sgoal = goal;
835 if (type == TC_GOTO) {
836 struct Ain a;
837 a.type = TCSH_F_SEEK;
838 a.f_seek = 0;
839 bseek(&a);
841 do {
842 if (intty && fseekp == feobp && aret == TCSH_F_SEEK)
843 printprompt(1, isrchx(type == TC_BREAK ? zlast : type));
844 /* xprintf("? "), flush(); */
845 aword[0] = 0;
846 (void) getword(aword);
847 switch (srchx(aword)) {
849 case TC_ELSE:
850 if (level == 0 && type == TC_IF)
851 return;
852 break;
854 case TC_IF:
855 while (getword(aword))
856 continue;
857 if ((type == TC_IF || type == TC_ELSE) &&
858 eq(aword, STRthen))
859 level++;
860 break;
862 case TC_ENDIF:
863 if (type == TC_IF || type == TC_ELSE)
864 level--;
865 break;
867 case TC_FOREACH:
868 case TC_WHILE:
869 if (type == TC_BREAK)
870 level++;
871 break;
873 case TC_END:
874 if (type == TC_BREAK)
875 level--;
876 break;
878 case TC_SWITCH:
879 if (type == TC_SWITCH || type == TC_BRKSW)
880 level++;
881 break;
883 case TC_ENDSW:
884 if (type == TC_SWITCH || type == TC_BRKSW)
885 level--;
886 break;
888 case TC_LABEL:
889 if (type == TC_GOTO && getword(aword) && eq(aword, goal))
890 level = -1;
891 break;
893 default:
894 if (type != TC_GOTO && (type != TC_SWITCH || level != 0))
895 break;
896 if (lastchr(aword) != ':')
897 break;
898 aword[Strlen(aword) - 1] = 0;
899 if ((type == TC_GOTO && eq(aword, goal)) ||
900 (type == TC_SWITCH && eq(aword, STRdefault)))
901 level = -1;
902 break;
904 case TC_CASE:
905 if (type != TC_SWITCH || level != 0)
906 break;
907 (void) getword(aword);
908 if (lastchr(aword) == ':')
909 aword[Strlen(aword) - 1] = 0;
910 cp = strip(Dfix1(aword));
911 if (Gmatch(goal, cp))
912 level = -1;
913 xfree((ptr_t) cp);
914 break;
916 case TC_DEFAULT:
917 if (type == TC_SWITCH && level == 0)
918 level = -1;
919 break;
921 (void) getword(NULL);
922 } while (level >= 0);
925 static int
926 getword(wp)
927 register Char *wp;
929 int found = 0, first;
930 int c, d;
932 c = readc(1);
933 d = 0;
934 do {
935 while (c == ' ' || c == '\t')
936 c = readc(1);
937 if (c == '#')
939 c = readc(1);
940 while (c >= 0 && c != '\n');
941 if (c < 0)
942 goto past;
943 if (c == '\n') {
944 if (wp)
945 break;
946 return (0);
948 unreadc(c);
949 found = 1;
950 first = 1;
951 do {
952 c = readc(1);
953 if (c == '\\' && (c = readc(1)) == '\n')
954 c = ' ';
955 if (c == '\'' || c == '"') {
956 if (d == 0)
957 d = c;
958 else if (d == c)
959 d = 0;
961 if (c < 0)
962 goto past;
963 if (wp) {
964 *wp++ = (Char) c;
965 *wp = '\0';
967 if (!first && !d && c == '(') {
968 if (wp) {
969 unreadc(c);
970 *--wp = '\0';
971 return found;
973 else
974 break;
976 first = 0;
977 } while ((d || (c != ' ' && c != '\t')) && c != '\n');
978 } while (wp == 0);
980 unreadc(c);
981 if (found)
982 *--wp = '\0';
984 return (found);
986 past:
987 switch (Stype) {
989 case TC_IF:
990 stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
991 break;
993 case TC_ELSE:
994 stderror(ERR_NAME | ERR_NOTFOUND, "endif");
995 break;
997 case TC_BRKSW:
998 case TC_SWITCH:
999 stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
1000 break;
1002 case TC_BREAK:
1003 stderror(ERR_NAME | ERR_NOTFOUND, "end");
1004 break;
1006 case TC_GOTO:
1007 setname(short2str(Sgoal));
1008 stderror(ERR_NAME | ERR_NOTFOUND, "label");
1009 break;
1011 default:
1012 break;
1014 /* NOTREACHED */
1015 return (0);
1018 static void
1019 toend()
1021 if (whyles->w_end.type == TCSH_F_SEEK && whyles->w_end.f_seek == 0) {
1022 search(TC_BREAK, 0, NULL);
1023 btell(&whyles->w_end);
1024 whyles->w_end.f_seek--;
1026 else {
1027 bseek(&whyles->w_end);
1029 wfree();
1032 void
1033 wfree()
1035 struct Ain o;
1036 struct whyle *nwp;
1037 #ifdef lint
1038 nwp = NULL; /* sun lint is dumb! */
1039 #endif
1041 #ifdef FDEBUG
1042 static char foo[] = "IAFE";
1043 #endif /* FDEBUG */
1045 btell(&o);
1047 #ifdef FDEBUG
1048 xprintf("o->type %c o->a_seek %d o->f_seek %d\n",
1049 foo[o.type + 1], o.a_seek, o.f_seek);
1050 #endif /* FDEBUG */
1052 for (; whyles; whyles = nwp) {
1053 register struct whyle *wp = whyles;
1054 nwp = wp->w_next;
1056 #ifdef FDEBUG
1057 xprintf("start->type %c start->a_seek %d start->f_seek %d\n",
1058 foo[wp->w_start.type+1],
1059 wp->w_start.a_seek, wp->w_start.f_seek);
1060 xprintf("end->type %c end->a_seek %d end->f_seek %d\n",
1061 foo[wp->w_end.type + 1], wp->w_end.a_seek, wp->w_end.f_seek);
1062 #endif /* FDEBUG */
1065 * XXX: We free loops that have different seek types.
1067 if (wp->w_end.type != TCSH_I_SEEK && wp->w_start.type == wp->w_end.type &&
1068 wp->w_start.type == o.type) {
1069 if (wp->w_end.type == TCSH_F_SEEK) {
1070 if (o.f_seek >= wp->w_start.f_seek &&
1071 (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
1072 break;
1074 else {
1075 if (o.a_seek >= wp->w_start.a_seek &&
1076 (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
1077 break;
1081 if (wp->w_fe0)
1082 blkfree(wp->w_fe0);
1083 if (wp->w_fename)
1084 xfree((ptr_t) wp->w_fename);
1085 xfree((ptr_t) wp);
1089 /*ARGSUSED*/
1090 void
1091 doecho(v, c)
1092 Char **v;
1093 struct command *c;
1095 USE(c);
1096 xecho(' ', v);
1099 /*ARGSUSED*/
1100 void
1101 doglob(v, c)
1102 Char **v;
1103 struct command *c;
1105 USE(c);
1106 xecho(0, v);
1107 flush();
1110 static void
1111 xecho(sep, v)
1112 int sep;
1113 register Char **v;
1115 register Char *cp;
1116 int nonl = 0;
1117 #ifdef ECHO_STYLE
1118 int echo_style = ECHO_STYLE;
1119 #else /* !ECHO_STYLE */
1120 # if SYSVREL > 0
1121 int echo_style = SYSV_ECHO;
1122 # else /* SYSVREL == 0 */
1123 int echo_style = BSD_ECHO;
1124 # endif /* SYSVREL */
1125 #endif /* ECHO_STYLE */
1126 struct varent *vp;
1128 if ((vp = adrof(STRecho_style)) != NULL && vp->vec != NULL &&
1129 vp->vec[0] != NULL) {
1130 if (Strcmp(vp->vec[0], STRbsd) == 0)
1131 echo_style = BSD_ECHO;
1132 else if (Strcmp(vp->vec[0], STRsysv) == 0)
1133 echo_style = SYSV_ECHO;
1134 else if (Strcmp(vp->vec[0], STRboth) == 0)
1135 echo_style = BOTH_ECHO;
1136 else if (Strcmp(vp->vec[0], STRnone) == 0)
1137 echo_style = NONE_ECHO;
1140 if (setintr)
1141 #ifdef BSDSIGS
1142 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1143 #else /* !BSDSIGS */
1144 (void) sigrelse (SIGINT);
1145 #endif /* BSDSIGS */
1146 v++;
1147 if (*v == 0)
1148 goto done;
1149 gflag = 0, tglob(v);
1150 if (gflag) {
1151 v = globall(v);
1152 if (v == 0)
1153 stderror(ERR_NAME | ERR_NOMATCH);
1155 else {
1156 v = gargv = saveblk(v);
1157 trim(v);
1160 if ((echo_style & BSD_ECHO) != 0 && sep == ' ' && *v && eq(*v, STRmn))
1161 nonl++, v++;
1163 while ((cp = *v++) != 0) {
1164 register int c;
1166 while ((c = *cp++) != 0) {
1167 if ((echo_style & SYSV_ECHO) != 0 && c == '\\') {
1168 switch (c = *cp++) {
1169 case 'a':
1170 c = '\a';
1171 break;
1172 case 'b':
1173 c = '\b';
1174 break;
1175 case 'c':
1176 nonl = 1;
1177 goto done;
1178 case 'e':
1179 #if 0 /* Windows does not understand \e */
1180 c = '\e';
1181 #else
1182 c = '\033';
1183 #endif
1184 break;
1185 case 'f':
1186 c = '\f';
1187 break;
1188 case 'n':
1189 c = '\n';
1190 break;
1191 case 'r':
1192 c = '\r';
1193 break;
1194 case 't':
1195 c = '\t';
1196 break;
1197 case 'v':
1198 c = '\v';
1199 break;
1200 case '\\':
1201 c = '\\';
1202 break;
1203 case '0':
1204 c = 0;
1205 if (*cp >= '0' && *cp < '8')
1206 c = c * 8 + *cp++ - '0';
1207 if (*cp >= '0' && *cp < '8')
1208 c = c * 8 + *cp++ - '0';
1209 if (*cp >= '0' && *cp < '8')
1210 c = c * 8 + *cp++ - '0';
1211 break;
1212 case '\0':
1213 c = '\\';
1214 cp--;
1215 break;
1216 default:
1217 xputchar('\\' | QUOTE);
1218 break;
1221 xputchar(c | QUOTE);
1224 if (*v)
1225 xputchar(sep | QUOTE);
1227 done:
1228 if (sep && nonl == 0)
1229 xputchar('\n');
1230 else
1231 flush();
1232 if (setintr)
1233 #ifdef BSDSIGS
1234 (void) sigblock(sigmask(SIGINT));
1235 #else /* !BSDSIGS */
1236 (void) sighold(SIGINT);
1237 #endif /* BSDSIGS */
1238 if (gargv)
1239 blkfree(gargv), gargv = 0;
1242 /* check whether an environment variable should invoke 'set_locale()' */
1243 static bool
1244 islocale_var(var)
1245 Char *var;
1247 static Char *locale_vars[] = {
1248 STRLANG, STRLC_CTYPE, STRLC_NUMERIC, STRLC_TIME,
1249 STRLC_COLLATE, STRLC_MESSAGES, STRLC_MONETARY, 0
1251 register Char **v;
1253 for (v = locale_vars; *v; ++v)
1254 if (eq(var, *v))
1255 return 1;
1256 return 0;
1259 /*ARGSUSED*/
1260 void
1261 doprintenv(v, c)
1262 register Char **v;
1263 struct command *c;
1265 Char *e;
1266 extern bool output_raw;
1267 extern bool xlate_cr;
1269 USE(c);
1270 if (setintr)
1271 #ifdef BSDSIGS
1272 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1273 #else /* !BSDSIGS */
1274 (void) sigrelse (SIGINT);
1275 #endif /* BSDSIGS */
1277 v++;
1278 if (*v == 0) {
1279 register Char **ep;
1281 xlate_cr = 1;
1282 for (ep = STR_environ; *ep; ep++)
1283 xprintf("%S\n", *ep);
1284 xlate_cr = 0;
1286 else if ((e = tgetenv(*v)) != NULL) {
1287 output_raw = 1;
1288 xprintf("%S\n", e);
1289 output_raw = 0;
1291 else
1292 set(STRstatus, Strsave(STR1), VAR_READWRITE);
1295 /* from "Karl Berry." <karl%mote.umb.edu@relay.cs.net> -- for NeXT things
1296 (and anything else with a modern compiler) */
1298 /*ARGSUSED*/
1299 void
1300 dosetenv(v, c)
1301 register Char **v;
1302 struct command *c;
1304 Char *vp, *lp;
1306 USE(c);
1307 if (*++v == 0) {
1308 doprintenv(--v, 0);
1309 return;
1312 vp = *v++;
1314 lp = vp;
1315 if (!letter(*lp))
1316 stderror(ERR_NAME | ERR_VARBEGIN);
1318 for (; alnum(*lp); lp++)
1319 continue;
1321 if (*lp != '\0')
1322 stderror(ERR_NAME | ERR_SYNTAX);
1324 if ((lp = *v++) == 0)
1325 lp = STRNULL;
1327 tsetenv(vp, lp = globone(lp, G_APPEND));
1328 if (eq(vp, STRKPATH)) {
1329 importpath(lp);
1330 dohash(NULL, NULL);
1331 xfree((ptr_t) lp);
1332 return;
1335 #ifdef apollo
1336 if (eq(vp, STRSYSTYPE)) {
1337 dohash(NULL, NULL);
1338 xfree((ptr_t) lp);
1339 return;
1341 #endif /* apollo */
1343 /* dspkanji/dspmbyte autosetting */
1344 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1345 #if defined(DSPMBYTE)
1346 if(eq(vp, STRLANG) && !adrof(CHECK_MBYTEVAR)) {
1347 autoset_dspmbyte(lp);
1349 #endif
1351 if (islocale_var(vp)) {
1352 #ifdef NLS
1353 int k;
1355 # ifdef SETLOCALEBUG
1356 dont_free = 1;
1357 # endif /* SETLOCALEBUG */
1358 (void) setlocale(LC_ALL, "");
1359 # ifdef LC_COLLATE
1360 (void) setlocale(LC_COLLATE, "");
1361 # endif
1362 # ifdef NLS_CATALOGS
1363 # ifdef LC_MESSAGES
1364 (void) setlocale(LC_MESSAGES, "");
1365 # endif /* LC_MESSAGES */
1366 (void) catclose(catd);
1367 nlsinit();
1368 # endif /* NLS_CATALOGS */
1369 # ifdef LC_CTYPE
1370 (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
1371 # endif /* LC_CTYPE */
1372 # ifdef SETLOCALEBUG
1373 dont_free = 0;
1374 # endif /* SETLOCALEBUG */
1375 # ifdef STRCOLLBUG
1376 fix_strcoll_bug();
1377 # endif /* STRCOLLBUG */
1378 tw_cmd_free(); /* since the collation sequence has changed */
1379 for (k = 0200; k <= 0377 && !Isprint(k); k++)
1380 continue;
1381 AsciiOnly = k > 0377;
1382 #else /* !NLS */
1383 AsciiOnly = 0;
1384 #endif /* NLS */
1385 NLSMapsAreInited = 0;
1386 ed_Init();
1387 if (MapsAreInited && !NLSMapsAreInited)
1388 ed_InitNLSMaps();
1389 xfree((ptr_t) lp);
1390 return;
1393 #ifdef NLS_CATALOGS
1394 if (eq(vp, STRNLSPATH)) {
1395 (void) catclose(catd);
1396 nlsinit();
1398 #endif
1400 if (eq(vp, STRNOREBIND)) {
1401 NoNLSRebind = 1;
1402 MapsAreInited = 0;
1403 NLSMapsAreInited = 0;
1404 ed_InitMaps();
1405 xfree((ptr_t) lp);
1406 return;
1408 #ifdef WINNT_NATIVE
1409 if (eq(vp, STRtcshlang)) {
1410 nlsinit();
1411 xfree((ptr_t) lp);
1412 return;
1414 #endif /* WINNT_NATIVE */
1415 if (eq(vp, STRKTERM)) {
1416 char *t;
1417 set(STRterm, quote(lp), VAR_READWRITE); /* lp memory used here */
1418 t = short2str(lp);
1419 if (noediting && strcmp(t, "unknown") != 0 && strcmp(t,"dumb") != 0) {
1420 editing = 1;
1421 noediting = 0;
1422 set(STRedit, Strsave(STRNULL), VAR_READWRITE);
1424 GotTermCaps = 0;
1425 ed_Init();
1426 return;
1429 if (eq(vp, STRKHOME)) {
1431 * convert to canonical pathname (possibly resolving symlinks)
1433 lp = dcanon(lp, lp);
1434 set(STRhome, quote(lp), VAR_READWRITE); /* cp memory used here */
1436 /* fix directory stack for new tilde home */
1437 dtilde();
1438 return;
1441 if (eq(vp, STRKSHLVL)) {
1442 /* lp memory used here */
1443 set(STRshlvl, quote(lp), VAR_READWRITE);
1444 return;
1447 if (eq(vp, STRKUSER)) {
1448 set(STRuser, quote(lp), VAR_READWRITE); /* lp memory used here */
1449 return;
1452 if (eq(vp, STRKGROUP)) {
1453 set(STRgroup, quote(lp), VAR_READWRITE); /* lp memory used here */
1454 return;
1457 #ifdef COLOR_LS_F
1458 if (eq(vp, STRLS_COLORS)) {
1459 parseLS_COLORS(lp);
1460 return;
1462 #endif /* COLOR_LS_F */
1464 #ifdef SIG_WINDOW
1466 * Load/Update $LINES $COLUMNS
1468 if ((eq(lp, STRNULL) && (eq(vp, STRLINES) || eq(vp, STRCOLUMNS))) ||
1469 eq(vp, STRTERMCAP)) {
1470 xfree((ptr_t) lp);
1471 check_window_size(1);
1472 return;
1476 * Change the size to the one directed by $LINES and $COLUMNS
1478 if (eq(vp, STRLINES) || eq(vp, STRCOLUMNS)) {
1479 #if 0
1480 GotTermCaps = 0;
1481 #endif
1482 xfree((ptr_t) lp);
1483 ed_Init();
1484 return;
1486 #endif /* SIG_WINDOW */
1487 xfree((ptr_t) lp);
1490 /*ARGSUSED*/
1491 void
1492 dounsetenv(v, c)
1493 register Char **v;
1494 struct command *c;
1496 Char **ep, *p, *n;
1497 int i, maxi;
1498 static Char *name = NULL;
1500 USE(c);
1501 if (name)
1502 xfree((ptr_t) name);
1504 * Find the longest environment variable
1506 for (maxi = 0, ep = STR_environ; *ep; ep++) {
1507 for (i = 0, p = *ep; *p && *p != '='; p++, i++)
1508 continue;
1509 if (i > maxi)
1510 maxi = i;
1513 name = (Char *) xmalloc((size_t) ((maxi + 1) * sizeof(Char)));
1515 while (++v && *v)
1516 for (maxi = 1; maxi;)
1517 for (maxi = 0, ep = STR_environ; *ep; ep++) {
1518 for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
1519 continue;
1520 *n = '\0';
1521 if (!Gmatch(name, *v))
1522 continue;
1523 maxi = 1;
1525 /* Unset the name. This wasn't being done until
1526 * later but most of the stuff following won't
1527 * work (particularly the setlocale() and getenv()
1528 * stuff) as intended until the name is actually
1529 * removed. (sg)
1531 Unsetenv(name);
1533 if (eq(name, STRNOREBIND)) {
1534 NoNLSRebind = 0;
1535 MapsAreInited = 0;
1536 NLSMapsAreInited = 0;
1537 ed_InitMaps();
1539 #ifdef apollo
1540 else if (eq(name, STRSYSTYPE))
1541 dohash(NULL, NULL);
1542 #endif /* apollo */
1543 else if (islocale_var(name)) {
1544 #ifdef NLS
1545 int k;
1547 # ifdef SETLOCALEBUG
1548 dont_free = 1;
1549 # endif /* SETLOCALEBUG */
1550 (void) setlocale(LC_ALL, "");
1551 # ifdef LC_COLLATE
1552 (void) setlocale(LC_COLLATE, "");
1553 # endif
1554 # ifdef NLS_CATALOGS
1555 # ifdef LC_MESSAGES
1556 (void) setlocale(LC_MESSAGES, "");
1557 # endif /* LC_MESSAGES */
1558 (void) catclose(catd);
1559 nlsinit();
1560 # endif /* NLS_CATALOGS */
1561 # ifdef LC_CTYPE
1562 (void) setlocale(LC_CTYPE, ""); /* for iscntrl */
1563 # endif /* LC_CTYPE */
1564 # ifdef SETLOCALEBUG
1565 dont_free = 0;
1566 # endif /* SETLOCALEBUG */
1567 # ifdef STRCOLLBUG
1568 fix_strcoll_bug();
1569 # endif /* STRCOLLBUG */
1570 tw_cmd_free();/* since the collation sequence has changed */
1571 for (k = 0200; k <= 0377 && !Isprint(k); k++)
1572 continue;
1573 AsciiOnly = k > 0377;
1574 #else /* !NLS */
1575 AsciiOnly = getenv("LANG") == NULL &&
1576 getenv("LC_CTYPE") == NULL;
1577 #endif /* NLS */
1578 NLSMapsAreInited = 0;
1579 ed_Init();
1580 if (MapsAreInited && !NLSMapsAreInited)
1581 ed_InitNLSMaps();
1584 #ifdef WINNT_NATIVE
1585 else if (eq(name,(STRtcshlang))) {
1586 nls_dll_unload();
1587 nlsinit();
1589 #endif /* WINNT_NATIVE */
1590 #ifdef COLOR_LS_F
1591 else if (eq(name, STRLS_COLORS))
1592 parseLS_COLORS(n);
1593 #endif /* COLOR_LS_F */
1594 #ifdef NLS_CATALOGS
1595 else if (eq(name, STRNLSPATH)) {
1596 (void) catclose(catd);
1597 nlsinit();
1599 #endif
1601 * start again cause the environment changes
1603 break;
1605 xfree((ptr_t) name); name = NULL;
1608 void
1609 tsetenv(name, val)
1610 Char *name, *val;
1612 #ifdef SETENV_IN_LIB
1614 * XXX: This does not work right, since tcsh cannot track changes to
1615 * the environment this way. (the builtin setenv without arguments does
1616 * not print the right stuff neither does unsetenv). This was for Mach,
1617 * it is not needed anymore.
1619 #undef setenv
1620 char nameBuf[BUFSIZE];
1621 char *cname = short2str(name);
1623 if (cname == NULL)
1624 return;
1625 (void) strcpy(nameBuf, cname);
1626 setenv(nameBuf, short2str(val), 1);
1627 #else /* !SETENV_IN_LIB */
1628 register Char **ep = STR_environ;
1629 register Char *cp, *dp;
1630 Char *blk[2];
1631 Char **oep = ep;
1633 #ifdef WINNT_NATIVE
1634 nt_set_env(name,val);
1635 #endif /* WINNT_NATIVE */
1636 for (; *ep; ep++) {
1637 #ifdef WINNT_NATIVE
1638 for (cp = name, dp = *ep; *cp && Tolower(*cp & TRIM) == Tolower(*dp);
1639 cp++, dp++)
1640 #else
1641 for (cp = name, dp = *ep; *cp && (*cp & TRIM) == *dp; cp++, dp++)
1642 #endif /* WINNT_NATIVE */
1643 continue;
1644 if (*cp != 0 || *dp != '=')
1645 continue;
1646 cp = Strspl(STRequal, val);
1647 xfree((ptr_t) * ep);
1648 *ep = strip(Strspl(name, cp));
1649 xfree((ptr_t) cp);
1650 blkfree((Char **) environ);
1651 environ = short2blk(STR_environ);
1652 return;
1654 cp = Strspl(name, STRequal);
1655 blk[0] = strip(Strspl(cp, val));
1656 xfree((ptr_t) cp);
1657 blk[1] = 0;
1658 STR_environ = blkspl(STR_environ, blk);
1659 blkfree((Char **) environ);
1660 environ = short2blk(STR_environ);
1661 xfree((ptr_t) oep);
1662 #endif /* SETENV_IN_LIB */
1665 void
1666 Unsetenv(name)
1667 Char *name;
1669 register Char **ep = STR_environ;
1670 register Char *cp, *dp;
1671 Char **oep = ep;
1673 #ifdef WINNT_NATIVE
1674 nt_set_env(name,NULL);
1675 #endif /*WINNT_NATIVE */
1676 for (; *ep; ep++) {
1677 for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
1678 continue;
1679 if (*cp != 0 || *dp != '=')
1680 continue;
1681 cp = *ep;
1682 *ep = 0;
1683 STR_environ = blkspl(STR_environ, ep + 1);
1684 blkfree((Char **) environ);
1685 environ = short2blk(STR_environ);
1686 *ep = cp;
1687 xfree((ptr_t) cp);
1688 xfree((ptr_t) oep);
1689 return;
1693 /*ARGSUSED*/
1694 void
1695 doumask(v, c)
1696 register Char **v;
1697 struct command *c;
1699 register Char *cp = v[1];
1700 register int i;
1702 USE(c);
1703 if (cp == 0) {
1704 i = (int)umask(0);
1705 (void) umask(i);
1706 xprintf("%o\n", i);
1707 return;
1709 i = 0;
1710 while (Isdigit(*cp) && *cp != '8' && *cp != '9')
1711 i = i * 8 + *cp++ - '0';
1712 if (*cp || i < 0 || i > 0777)
1713 stderror(ERR_NAME | ERR_MASK);
1714 (void) umask(i);
1717 #ifndef HAVENOLIMIT
1718 # ifndef BSDLIMIT
1719 typedef long RLIM_TYPE;
1720 # ifndef RLIM_INFINITY
1721 # if !defined(_MINIX) && !defined(__clipper__) && !defined(_CRAY)
1722 extern RLIM_TYPE ulimit();
1723 # endif /* ! _MINIX && !__clipper__ */
1724 # define RLIM_INFINITY 0x003fffff
1725 # define RLIMIT_FSIZE 1
1726 # endif /* RLIM_INFINITY */
1727 # ifdef aiws
1728 # define toset(a) (((a) == 3) ? 1004 : (a) + 1)
1729 # define RLIMIT_DATA 3
1730 # define RLIMIT_STACK 1005
1731 # else /* aiws */
1732 # define toset(a) ((a) + 1)
1733 # endif /* aiws */
1734 # else /* BSDLIMIT */
1735 # if (defined(BSD4_4) || defined(__linux__)) && !defined(__386BSD__)
1736 typedef rlim_t RLIM_TYPE;
1737 # else
1738 # if defined(SOLARIS2) || (defined(sgi) && SYSVREL > 3)
1739 typedef rlim_t RLIM_TYPE;
1740 # else
1741 # if defined(_SX)
1742 typedef long long RLIM_TYPE;
1743 # else /* !_SX */
1744 typedef unsigned long RLIM_TYPE;
1745 # endif /* _SX */
1746 # endif /* SOLARIS2 || (sgi && SYSVREL > 3) */
1747 # endif /* BSD4_4 && !__386BSD__ */
1748 # endif /* BSDLIMIT */
1750 # if (HPUXVERSION > 700) && defined(BSDLIMIT)
1751 /* Yes hpux8.0 has limits but <sys/resource.h> does not make them public */
1752 /* Yes, we could have defined _KERNEL, and -I/etc/conf/h, but is that better? */
1753 # ifndef RLIMIT_CPU
1754 # define RLIMIT_CPU 0
1755 # define RLIMIT_FSIZE 1
1756 # define RLIMIT_DATA 2
1757 # define RLIMIT_STACK 3
1758 # define RLIMIT_CORE 4
1759 # define RLIMIT_RSS 5
1760 # define RLIMIT_NOFILE 6
1761 # endif /* RLIMIT_CPU */
1762 # ifndef RLIM_INFINITY
1763 # define RLIM_INFINITY 0x7fffffff
1764 # endif /* RLIM_INFINITY */
1766 * old versions of HP/UX counted limits in 512 bytes
1768 # ifndef SIGRTMIN
1769 # define FILESIZE512
1770 # endif /* SIGRTMIN */
1771 # endif /* (HPUXVERSION > 700) && BSDLIMIT */
1773 # if SYSVREL > 3 && defined(BSDLIMIT) && !defined(_SX)
1774 /* In order to use rusage, we included "/usr/ucbinclude/sys/resource.h" in */
1775 /* sh.h. However, some SVR4 limits are defined in <sys/resource.h>. Rather */
1776 /* than include both and get warnings, we define the extra SVR4 limits here. */
1777 /* XXX: I don't understand if RLIMIT_AS is defined, why don't we define */
1778 /* RLIMIT_VMEM based on it? */
1779 # ifndef RLIMIT_VMEM
1780 # define RLIMIT_VMEM 6
1781 # endif
1782 # ifndef RLIMIT_AS
1783 # define RLIMIT_AS RLIMIT_VMEM
1784 # endif
1785 # endif /* SYSVREL > 3 && BSDLIMIT */
1787 # if defined(__linux__) && defined(RLIMIT_AS) && !defined(RLIMIT_VMEM)
1788 # define RLIMIT_VMEM RLIMIT_AS
1789 # endif
1791 struct limits limits[] =
1793 # ifdef RLIMIT_CPU
1794 { RLIMIT_CPU, "cputime", 1, "seconds" },
1795 # endif /* RLIMIT_CPU */
1797 # ifdef RLIMIT_FSIZE
1798 # ifndef aiws
1799 { RLIMIT_FSIZE, "filesize", 1024, "kbytes" },
1800 # else
1801 { RLIMIT_FSIZE, "filesize", 512, "blocks" },
1802 # endif /* aiws */
1803 # endif /* RLIMIT_FSIZE */
1805 # ifdef RLIMIT_DATA
1806 { RLIMIT_DATA, "datasize", 1024, "kbytes" },
1807 # endif /* RLIMIT_DATA */
1809 # ifdef RLIMIT_STACK
1810 # ifndef aiws
1811 { RLIMIT_STACK, "stacksize", 1024, "kbytes" },
1812 # else
1813 { RLIMIT_STACK, "stacksize", 1024 * 1024, "kbytes"},
1814 # endif /* aiws */
1815 # endif /* RLIMIT_STACK */
1817 # ifdef RLIMIT_CORE
1818 { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" },
1819 # endif /* RLIMIT_CORE */
1821 # ifdef RLIMIT_RSS
1822 { RLIMIT_RSS, "memoryuse", 1024, "kbytes" },
1823 # endif /* RLIMIT_RSS */
1825 # ifdef RLIMIT_UMEM
1826 { RLIMIT_UMEM, "memoryuse", 1024, "kbytes" },
1827 # endif /* RLIMIT_UMEM */
1829 # ifdef RLIMIT_VMEM
1830 { RLIMIT_VMEM, "vmemoryuse", 1024, "kbytes" },
1831 # endif /* RLIMIT_VMEM */
1833 # ifdef RLIMIT_NOFILE
1834 { RLIMIT_NOFILE, "descriptors", 1, "" },
1835 # endif /* RLIMIT_NOFILE */
1837 # ifdef RLIMIT_CONCUR
1838 { RLIMIT_CONCUR, "concurrency", 1, "thread(s)" },
1839 # endif /* RLIMIT_CONCUR */
1841 # ifdef RLIMIT_MEMLOCK
1842 { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" },
1843 # endif /* RLIMIT_MEMLOCK */
1845 # ifdef RLIMIT_NPROC
1846 { RLIMIT_NPROC, "maxproc", 1, "" },
1847 # endif /* RLIMIT_NPROC */
1849 # if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
1850 { RLIMIT_OFILE, "openfiles", 1, "" },
1851 # endif /* RLIMIT_OFILE && !defined(RLIMIT_NOFILE) */
1853 # ifdef RLIMIT_SBSIZE
1854 { RLIMIT_SBSIZE, "sbsize", 1, "" },
1855 # endif /* RLIMIT_SBSIZE */
1857 #ifdef RLIMIT_POSIXLOCKS
1858 { RLIMIT_POSIXLOCKS, "posixlocks", 1, "" },
1859 #endif /* RLIMIT_POSIXLOCKS */
1861 { -1, NULL, 0, NULL }
1864 static struct limits *findlim __P((Char *));
1865 static RLIM_TYPE getval __P((struct limits *, Char **));
1866 static void limtail __P((Char *, char*));
1867 static void plim __P((struct limits *, int));
1868 static int setlim __P((struct limits *, int, RLIM_TYPE));
1870 #ifdef convex
1871 static RLIM_TYPE
1872 restrict_limit(value)
1873 double value;
1876 * is f too large to cope with? return the maximum or minimum int
1878 if (value > (double) INT_MAX)
1879 return (RLIM_TYPE) INT_MAX;
1880 else if (value < (double) INT_MIN)
1881 return (RLIM_TYPE) INT_MIN;
1882 else
1883 return (RLIM_TYPE) value;
1885 #else /* !convex */
1886 # define restrict_limit(x) ((RLIM_TYPE) (x))
1887 #endif /* convex */
1890 static struct limits *
1891 findlim(cp)
1892 Char *cp;
1894 register struct limits *lp, *res;
1896 res = (struct limits *) NULL;
1897 for (lp = limits; lp->limconst >= 0; lp++)
1898 if (prefix(cp, str2short(lp->limname))) {
1899 if (res)
1900 stderror(ERR_NAME | ERR_AMBIG);
1901 res = lp;
1903 if (res)
1904 return (res);
1905 stderror(ERR_NAME | ERR_LIMIT);
1906 /* NOTREACHED */
1907 return (0);
1910 /*ARGSUSED*/
1911 void
1912 dolimit(v, c)
1913 register Char **v;
1914 struct command *c;
1916 register struct limits *lp;
1917 register RLIM_TYPE limit;
1918 int hard = 0;
1920 USE(c);
1921 v++;
1922 if (*v && eq(*v, STRmh)) {
1923 hard = 1;
1924 v++;
1926 if (*v == 0) {
1927 for (lp = limits; lp->limconst >= 0; lp++)
1928 plim(lp, hard);
1929 return;
1931 lp = findlim(v[0]);
1932 if (v[1] == 0) {
1933 plim(lp, hard);
1934 return;
1936 limit = getval(lp, v + 1);
1937 if (setlim(lp, hard, limit) < 0)
1938 stderror(ERR_SILENT);
1941 static RLIM_TYPE
1942 getval(lp, v)
1943 register struct limits *lp;
1944 Char **v;
1946 register float f;
1947 #ifndef atof /* This can be a macro on linux */
1948 extern double atof __P((const char *));
1949 #endif /* atof */
1950 Char *cp = *v++;
1952 f = atof(short2str(cp));
1954 # ifdef convex
1956 * is f too large to cope with. limit f to minint, maxint - X-6768 by
1957 * strike
1959 if ((f < (double) INT_MIN) || (f > (double) INT_MAX)) {
1960 stderror(ERR_NAME | ERR_TOOLARGE);
1962 # endif /* convex */
1964 while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
1965 cp++;
1966 if (*cp == 0) {
1967 if (*v == 0)
1968 return restrict_limit((f * lp->limdiv) + 0.5);
1969 cp = *v;
1971 switch (*cp) {
1972 # ifdef RLIMIT_CPU
1973 case ':':
1974 if (lp->limconst != RLIMIT_CPU)
1975 goto badscal;
1976 return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f * 60.0 + atof(short2str(cp + 1))));
1977 case 'h':
1978 if (lp->limconst != RLIMIT_CPU)
1979 goto badscal;
1980 limtail(cp, "hours");
1981 f *= 3600.0;
1982 break;
1983 case 'm':
1984 if (lp->limconst == RLIMIT_CPU) {
1985 limtail(cp, "minutes");
1986 f *= 60.0;
1987 break;
1989 *cp = 'm';
1990 limtail(cp, "megabytes");
1991 f *= 1024.0 * 1024.0;
1992 break;
1993 case 's':
1994 if (lp->limconst != RLIMIT_CPU)
1995 goto badscal;
1996 limtail(cp, "seconds");
1997 break;
1998 # endif /* RLIMIT_CPU */
1999 case 'M':
2000 # ifdef RLIMIT_CPU
2001 if (lp->limconst == RLIMIT_CPU)
2002 goto badscal;
2003 # endif /* RLIMIT_CPU */
2004 *cp = 'm';
2005 limtail(cp, "megabytes");
2006 f *= 1024.0 * 1024.0;
2007 break;
2008 case 'k':
2009 # ifdef RLIMIT_CPU
2010 if (lp->limconst == RLIMIT_CPU)
2011 goto badscal;
2012 # endif /* RLIMIT_CPU */
2013 limtail(cp, "kbytes");
2014 f *= 1024.0;
2015 break;
2016 case 'b':
2017 # ifdef RLIMIT_CPU
2018 if (lp->limconst == RLIMIT_CPU)
2019 goto badscal;
2020 # endif /* RLIMIT_CPU */
2021 limtail(cp, "blocks");
2022 f *= 512.0;
2023 break;
2024 case 'u':
2025 limtail(cp, "unlimited");
2026 return ((RLIM_TYPE) RLIM_INFINITY);
2027 default:
2028 # ifdef RLIMIT_CPU
2029 badscal:
2030 # endif /* RLIMIT_CPU */
2031 stderror(ERR_NAME | ERR_SCALEF);
2033 # ifdef convex
2034 return f == 0.0 ? (RLIM_TYPE) 0 : restrict_limit((f + 0.5));
2035 # else
2036 f += 0.5;
2037 if (f > (float) RLIM_INFINITY)
2038 return ((RLIM_TYPE) RLIM_INFINITY);
2039 else
2040 return ((RLIM_TYPE) f);
2041 # endif /* convex */
2044 static void
2045 limtail(cp, str)
2046 Char *cp;
2047 char *str;
2049 char *sp;
2051 sp = str;
2052 while (*cp && *cp == *str)
2053 cp++, str++;
2054 if (*cp)
2055 stderror(ERR_BADSCALE, sp);
2059 /*ARGSUSED*/
2060 static void
2061 plim(lp, hard)
2062 register struct limits *lp;
2063 int hard;
2065 # ifdef BSDLIMIT
2066 struct rlimit rlim;
2067 # endif /* BSDLIMIT */
2068 RLIM_TYPE limit;
2069 int div = lp->limdiv;
2071 xprintf("%s \t", lp->limname);
2073 # ifndef BSDLIMIT
2074 limit = ulimit(lp->limconst, 0);
2075 # ifdef aiws
2076 if (lp->limconst == RLIMIT_DATA)
2077 limit -= 0x20000000;
2078 # endif /* aiws */
2079 # else /* BSDLIMIT */
2080 (void) getrlimit(lp->limconst, &rlim);
2081 limit = hard ? rlim.rlim_max : rlim.rlim_cur;
2082 # endif /* BSDLIMIT */
2084 # if !defined(BSDLIMIT) || defined(FILESIZE512)
2086 * Christos: filesize comes in 512 blocks. we divide by 2 to get 1024
2087 * blocks. Note we cannot pre-multiply cause we might overflow (A/UX)
2089 if (lp->limconst == RLIMIT_FSIZE) {
2090 if (limit >= (RLIM_INFINITY / 512))
2091 limit = RLIM_INFINITY;
2092 else
2093 div = (div == 1024 ? 2 : 1);
2095 # endif /* !BSDLIMIT || FILESIZE512 */
2097 if (limit == RLIM_INFINITY)
2098 xprintf("unlimited");
2099 else
2100 # ifdef RLIMIT_CPU
2101 if (lp->limconst == RLIMIT_CPU)
2102 psecs((long) limit);
2103 else
2104 # endif /* RLIMIT_CPU */
2105 xprintf("%ld %s", (long) (limit / div), lp->limscale);
2106 xputchar('\n');
2109 /*ARGSUSED*/
2110 void
2111 dounlimit(v, c)
2112 register Char **v;
2113 struct command *c;
2115 register struct limits *lp;
2116 int lerr = 0;
2117 int hard = 0;
2118 int force = 0;
2120 USE(c);
2121 while (*++v && **v == '-') {
2122 Char *vp = *v;
2123 while (*++vp)
2124 switch (*vp) {
2125 case 'f':
2126 force = 1;
2127 break;
2128 case 'h':
2129 hard = 1;
2130 break;
2131 default:
2132 stderror(ERR_ULIMUS);
2133 break;
2137 if (*v == 0) {
2138 for (lp = limits; lp->limconst >= 0; lp++)
2139 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
2140 lerr++;
2141 if (!force && lerr)
2142 stderror(ERR_SILENT);
2143 return;
2145 while (*v) {
2146 lp = findlim(*v++);
2147 if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0 && !force)
2148 stderror(ERR_SILENT);
2152 static int
2153 setlim(lp, hard, limit)
2154 register struct limits *lp;
2155 int hard;
2156 RLIM_TYPE limit;
2158 # ifdef BSDLIMIT
2159 struct rlimit rlim;
2161 (void) getrlimit(lp->limconst, &rlim);
2163 # ifdef FILESIZE512
2164 /* Even though hpux has setrlimit(), it expects fsize in 512 byte blocks */
2165 if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
2166 limit /= 512;
2167 # endif /* FILESIZE512 */
2168 if (hard)
2169 rlim.rlim_max = limit;
2170 else if (limit == RLIM_INFINITY && euid != 0)
2171 rlim.rlim_cur = rlim.rlim_max;
2172 else
2173 rlim.rlim_cur = limit;
2175 if (rlim.rlim_cur > rlim.rlim_max)
2176 rlim.rlim_max = rlim.rlim_cur;
2178 if (setrlimit(lp->limconst, &rlim) < 0) {
2179 # else /* BSDLIMIT */
2180 if (limit != RLIM_INFINITY && lp->limconst == RLIMIT_FSIZE)
2181 limit /= 512;
2182 # ifdef aiws
2183 if (lp->limconst == RLIMIT_DATA)
2184 limit += 0x20000000;
2185 # endif /* aiws */
2186 if (ulimit(toset(lp->limconst), limit) < 0) {
2187 # endif /* BSDLIMIT */
2188 xprintf(CGETS(15, 1, "%s: %s: Can't %s%s limit (%s)\n"), bname,
2189 lp->limname, limit == RLIM_INFINITY ? CGETS(15, 2, "remove") :
2190 CGETS(15, 3, "set"), hard ? CGETS(14, 4, " hard") : "",
2191 strerror(errno));
2192 return (-1);
2194 return (0);
2197 #endif /* !HAVENOLIMIT */
2199 /*ARGSUSED*/
2200 void
2201 dosuspend(v, c)
2202 Char **v;
2203 struct command *c;
2205 #ifdef BSDJOBS
2206 int ctpgrp;
2208 signalfun_t old;
2209 #endif /* BSDJOBS */
2211 USE(c);
2212 USE(v);
2214 if (loginsh)
2215 stderror(ERR_SUSPLOG);
2216 untty();
2218 #ifdef BSDJOBS
2219 old = signal(SIGTSTP, SIG_DFL);
2220 (void) kill(0, SIGTSTP);
2221 /* the shell stops here */
2222 (void) signal(SIGTSTP, old);
2223 #else /* !BSDJOBS */
2224 stderror(ERR_JOBCONTROL);
2225 #endif /* BSDJOBS */
2227 #ifdef BSDJOBS
2228 if (tpgrp != -1) {
2229 retry:
2230 ctpgrp = tcgetpgrp(FSHTTY);
2231 if (ctpgrp != opgrp) {
2232 old = signal(SIGTTIN, SIG_DFL);
2233 (void) kill(0, SIGTTIN);
2234 (void) signal(SIGTTIN, old);
2235 goto retry;
2237 (void) setpgid(0, shpgrp);
2238 (void) tcsetpgrp(FSHTTY, shpgrp);
2240 #endif /* BSDJOBS */
2241 (void) setdisc(FSHTTY);
2244 /* This is the dreaded EVAL built-in.
2245 * If you don't fiddle with file descriptors, and reset didfds,
2246 * this command will either ignore redirection inside or outside
2247 * its arguments, e.g. eval "date >x" vs. eval "date" >x
2248 * The stuff here seems to work, but I did it by trial and error rather
2249 * than really knowing what was going on. If tpgrp is zero, we are
2250 * probably a background eval, e.g. "eval date &", and we want to
2251 * make sure that any processes we start stay in our pgrp.
2252 * This is also the case for "time eval date" -- stay in same pgrp.
2253 * Otherwise, under stty tostop, processes will stop in the wrong
2254 * pgrp, with no way for the shell to get them going again. -IAN!
2257 static Char **gv = NULL, **gav = NULL;
2259 /*ARGSUSED*/
2260 void
2261 doeval(v, c)
2262 Char **v;
2263 struct command *c;
2265 Char **oevalvec;
2266 Char *oevalp;
2267 int odidfds;
2268 #ifndef CLOSE_ON_EXEC
2269 int odidcch;
2270 #endif /* CLOSE_ON_EXEC */
2271 jmp_buf_t osetexit;
2272 int my_reenter;
2273 Char **savegv;
2274 int saveIN, saveOUT, saveDIAG;
2275 int oSHIN, oSHOUT, oSHDIAG;
2277 USE(c);
2278 oevalvec = evalvec;
2279 oevalp = evalp;
2280 odidfds = didfds;
2281 #ifndef CLOSE_ON_EXEC
2282 odidcch = didcch;
2283 #endif /* CLOSE_ON_EXEC */
2284 oSHIN = SHIN;
2285 oSHOUT = SHOUT;
2286 oSHDIAG = SHDIAG;
2288 savegv = gv;
2289 gav = v;
2291 gav++;
2292 if (*gav == 0)
2293 return;
2294 gflag = 0, tglob(gav);
2295 if (gflag) {
2296 gv = gav = globall(gav);
2297 gargv = 0;
2298 if (gav == 0)
2299 stderror(ERR_NOMATCH);
2300 gav = copyblk(gav);
2302 else {
2303 gv = NULL;
2304 gav = copyblk(gav);
2305 trim(gav);
2308 saveIN = dcopy(SHIN, -1);
2309 saveOUT = dcopy(SHOUT, -1);
2310 saveDIAG = dcopy(SHDIAG, -1);
2312 getexit(osetexit);
2314 /* PWP: setjmp/longjmp bugfix for optimizing compilers */
2315 #ifdef cray
2316 my_reenter = 1; /* assume non-zero return val */
2317 if (setexit() == 0) {
2318 my_reenter = 0; /* Oh well, we were wrong */
2319 #else /* !cray */
2320 if ((my_reenter = setexit()) == 0) {
2321 #endif /* cray */
2322 evalvec = gav;
2323 evalp = 0;
2324 SHIN = dcopy(0, -1);
2325 SHOUT = dcopy(1, -1);
2326 SHDIAG = dcopy(2, -1);
2327 #ifndef CLOSE_ON_EXEC
2328 didcch = 0;
2329 #endif /* CLOSE_ON_EXEC */
2330 didfds = 0;
2331 process(0);
2334 evalvec = oevalvec;
2335 evalp = oevalp;
2336 doneinp = 0;
2337 #ifndef CLOSE_ON_EXEC
2338 didcch = odidcch;
2339 #endif /* CLOSE_ON_EXEC */
2340 didfds = odidfds;
2341 (void) close(SHIN);
2342 (void) close(SHOUT);
2343 (void) close(SHDIAG);
2344 SHIN = dmove(saveIN, oSHIN);
2345 SHOUT = dmove(saveOUT, oSHOUT);
2346 SHDIAG = dmove(saveDIAG, oSHDIAG);
2348 if (gv)
2349 blkfree(gv);
2351 gv = savegv;
2352 resexit(osetexit);
2353 if (my_reenter)
2354 stderror(ERR_SILENT);
2357 /*************************************************************************/
2358 /* print list of builtin commands */
2360 /*ARGSUSED*/
2361 void
2362 dobuiltins(v, c)
2363 Char **v;
2364 struct command *c;
2366 /* would use print_by_column() in tw.parse.c but that assumes
2367 * we have an array of Char * to pass.. (sg)
2369 extern int Tty_raw_mode;
2370 extern int TermH; /* from the editor routines */
2371 extern int lbuffed; /* from sh.print.c */
2373 register struct biltins *b;
2374 register int row, col, columns, rows;
2375 unsigned int w, maxwidth;
2377 USE(c);
2378 USE(v);
2379 lbuffed = 0; /* turn off line buffering */
2381 /* find widest string */
2382 for (maxwidth = 0, b = bfunc; b < &bfunc[nbfunc]; ++b)
2383 maxwidth = max(maxwidth, strlen(b->bname));
2384 ++maxwidth; /* for space */
2386 columns = (TermH + 1) / maxwidth; /* PWP: terminal size change */
2387 if (!columns)
2388 columns = 1;
2389 rows = (nbfunc + (columns - 1)) / columns;
2391 for (b = bfunc, row = 0; row < rows; row++) {
2392 for (col = 0; col < columns; col++) {
2393 if (b < &bfunc[nbfunc]) {
2394 w = strlen(b->bname);
2395 xprintf("%s", b->bname);
2396 if (col < (columns - 1)) /* Not last column? */
2397 for (; w < maxwidth; w++)
2398 xputchar(' ');
2399 ++b;
2402 if (row < (rows - 1)) {
2403 if (Tty_raw_mode)
2404 xputchar('\r');
2405 xputchar('\n');
2408 #ifdef WINNT_NATIVE
2409 nt_print_builtins(maxwidth);
2410 #else
2411 if (Tty_raw_mode)
2412 xputchar('\r');
2413 xputchar('\n');
2414 #endif /* WINNT_NATIVE */
2416 lbuffed = 1; /* turn back on line buffering */
2417 flush();
2420 void
2421 nlsinit()
2423 #ifdef NLS_CATALOGS
2424 char catalog[ 256 ] = { 't', 'c', 's', 'h', '\0' };
2426 if (adrof(STRcatalog) != NULL)
2427 xsnprintf((char *)catalog, sizeof(catalog), "tcsh.%s",
2428 short2str(varval(STRcatalog)));
2429 catd = catopen(catalog, MCLoadBySet);
2430 #endif /* NLS_CATALOGS */
2431 #ifdef WINNT_NATIVE
2432 nls_dll_init();
2433 #endif /* WINNT_NATIVE */
2434 errinit(); /* init the errorlist in correct locale */
2435 mesginit(); /* init the messages for signals */
2436 dateinit(); /* init the messages for dates */
2437 editinit(); /* init the editor messages */
2438 terminit(); /* init the termcap messages */