1 /* $NetBSD: csh.c,v 1.46 2013/07/16 17:47:43 christos Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)csh.c 8.2 (Berkeley) 10/12/93";
42 __RCSID("$NetBSD: csh.c,v 1.46 2013/07/16 17:47:43 christos Exp $");
46 #include <sys/types.h>
47 #include <sys/ioctl.h>
53 #include <paths.h> /* should this be included in pathnames.h instead? */
64 #include "pathnames.h"
70 * Bill Joy, UC Berkeley, California, USA
71 * October 1978, May 1980
73 * Jim Kulp, IIASA, Laxenburg, Austria
76 * Christos Zoulas, Cornell University
80 Char
*dumphist
[] = {STRhistory
, STRmh
, 0, 0};
81 Char
*tildehist
[] = {STRsource
, STRmh
, STRtildothist
, 0};
94 extern char **environ
;
96 static ssize_t
readf(void *, void *, size_t);
97 static off_t
seekf(void *, off_t
, int);
98 static ssize_t
writef(void *, const void *, size_t);
99 static int closef(void *);
100 static int srccat(Char
*, Char
*);
101 static int srcfile(const char *, int, int);
102 __dead
static void phup(int);
103 static void srcunit(int, int, int);
104 static void mailchk(void);
105 #ifndef _PATH_DEFPATH
106 static Char
**defaultpath(void);
113 main(int argc
, char *argv
[])
115 struct sigaction oact
;
126 setprogname(argv
[0]);
127 settimes(); /* Immed. estab. timing base */
130 * Initialize non constant strings
133 STR_BSHELL
= SAVE(_PATH_BSHELL
);
136 STR_SHELLPATH
= SAVE(_PATH_CSHELL
);
138 STR_environ
= blk2short(environ
);
139 environ
= short2blk(STR_environ
); /* So that we can free it */
140 STR_WORD_CHARS
= SAVE(WORD_CHARS
);
144 word_chars
= STR_WORD_CHARS
;
147 if (eq(str2short(tempv
[0]), STRaout
)) /* A.out's are quittable */
154 * We are a login shell if: 1. we were invoked as -<something> and we had
155 * no arguments 2. or we were invoked only with the -l flag
157 loginsh
= (**tempv
== '-' && argc
== 1) ||
158 (argc
== 2 && tempv
[1][0] == '-' && tempv
[1][1] == 'l' &&
159 tempv
[1][2] == '\0');
161 if (loginsh
&& **tempv
!= '-') {
163 * Mangle the argv space
168 for (tcp
= *tempv
; *tcp
++;)
170 for (tcp
--; tcp
>= *tempv
; tcp
--)
180 (void)setlocale(LC_ALL
, "");
184 for (k
= 0200; k
<= 0377 && !Isprint(k
); k
++)
186 AsciiOnly
= k
> 0377;
189 AsciiOnly
= getenv("LANG") == NULL
&& getenv("LC_CTYPE") == NULL
;
193 * Move the descriptors to safe places. The variable didfds is 0 while we
194 * have only FSH* to work with. When didfds is true, we have 0,1,2 and
195 * prefer to use these.
199 * XXX: This is to keep programs that use stdio happy.
200 * what we really want is freunopen() ....
201 * Closing cshin cshout and csherr (which are really stdin stdout
202 * and stderr at this point and then reopening them in the same order
203 * gives us again stdin == cshin stdout == cshout and stderr == csherr.
204 * If that was not the case builtins like printf that use stdio
205 * would break. But in any case we could fix that with memcpy and
206 * a bit of pointer manipulation...
207 * Fortunately this is not needed under the current implementation
211 (void)fclose(cshout
);
212 (void)fclose(csherr
);
213 if (!(cshin
= funopen2((void *) &SHIN
, readf
, writef
, seekf
, NULL
,
216 if (!(cshout
= funopen2((void *) &SHOUT
, readf
, writef
, seekf
, NULL
,
219 if (!(csherr
= funopen2((void *) &SHERR
, readf
, writef
, seekf
, NULL
,
222 (void)setvbuf(cshin
, NULL
, _IOLBF
, 0);
223 (void)setvbuf(cshout
, NULL
, _IOLBF
, 0);
224 (void)setvbuf(csherr
, NULL
, _IOLBF
, 0);
227 * Initialize the shell variables. ARGV and PROMPT are initialized later.
228 * STATUS is also munged in several places. CHILD is munged when
231 set(STRstatus
, Strsave(STR0
));
233 if ((ecp
= getenv("HOME")) != NULL
)
234 cp
= quote(SAVE(ecp
));
239 fast
= 1; /* No home -> can't read scripts */
242 dinit(cp
); /* dinit thinks that HOME == cwd in a login
245 * Grab other useful things from the environment. Should we grab
248 if ((ecp
= getenv("LOGNAME")) != NULL
||
249 (ecp
= getenv("USER")) != NULL
)
250 set(STRuser
, quote(SAVE(ecp
)));
251 if ((ecp
= getenv("TERM")) != NULL
)
252 set(STRterm
, quote(SAVE(ecp
)));
255 * Re-initialize path if set in environment
257 if ((ecp
= getenv("PATH")) == NULL
) {
259 importpath(str2short(_PATH_DEFPATH
));
261 setq(STRpath
, defaultpath(), &shvhed
);
264 importpath(str2short(ecp
));
267 set(STRshell
, Strsave(STR_SHELLPATH
));
269 doldol
= putn((int) getpid()); /* For $$ */
270 shtemp
= Strspl(STRtmpsh
, doldol
); /* For << */
273 * Record the interrupt states from the parent process. If the parent is
274 * non-interruptible our hand must be forced or we (and our children) won't
275 * be either. Our children inherit termination from our parent. We catch it
276 * only if we are the login shell.
278 /* parents interruptibility */
279 (void)sigaction(SIGINT
, NULL
, &oact
);
280 parintr
= oact
.sa_handler
;
281 (void)sigaction(SIGTERM
, NULL
, &oact
);
282 parterm
= oact
.sa_handler
;
284 /* catch these all, login shell or not */
285 (void)signal(SIGHUP
, phup
); /* exit processing on HUP */
286 (void)signal(SIGXCPU
, phup
); /* ...and on XCPU */
287 (void)signal(SIGXFSZ
, phup
); /* ...and on XFSZ */
290 * Process the arguments.
292 * Note that processing of -v/-x is actually delayed till after script
295 * We set the first character of our name to be '-' if we are a shell
296 * running interruptible commands. Many programs which examine ps'es
297 * use this to filter such shells out.
300 while (argc
> 0 && (tcp
= tempv
[0])[0] == '-' && *++tcp
!= '\0' && !batch
) {
303 case 0: /* - Interruptible, no prompt */
308 case 'b': /* -b Next arg is input file */
311 case 'c': /* -c Command input from arg */
315 arginp
= SAVE(tempv
[0]);
319 case 'e': /* -e Exit on any error */
322 case 'f': /* -f Fast start */
325 case 'i': /* -i Interactive, even if !intty */
329 case 'm': /* -m read .cshrc (from su) */
332 case 'n': /* -n Don't execute */
335 case 'q': /* -q (Undoc'd) ... die on quit */
338 case 's': /* -s Read from std input */
341 case 't': /* -t Read one line from input */
346 case 'v': /* -v Echo hist expanded input */
347 nverbose
= 1; /* ... later */
349 case 'x': /* -x Echo just before execution */
350 nexececho
= 1; /* ... later */
352 case 'V': /* -V Echo hist expanded input */
353 setNS(STRverbose
); /* NOW! */
355 case 'X': /* -X Echo just before execution */
356 setNS(STRecho
); /* NOW! */
363 if (quitit
) /* With all due haste, for debugging */
364 (void)signal(SIGQUIT
, SIG_DFL
);
367 * Unless prevented by -, -c, -i, -s, or -t, if there are remaining
368 * arguments the first of them is the name of a shell file from which to
371 if (nofile
== 0 && argc
> 0) {
372 nofile
= open(tempv
[0], O_RDONLY
);
374 child
= 1; /* So this doesn't return */
375 stderror(ERR_SYSTEM
, tempv
[0], strerror(errno
));
377 ffile
= SAVE(tempv
[0]);
379 * Replace FSHIN. Handle /dev/std{in,out,err} specially
380 * since once they are closed we cannot open them again.
381 * In that case we use our own saved descriptors
383 if ((SHIN
= dmove(nofile
, FSHIN
)) < 0)
395 stderror(ERR_SYSTEM
, tempv
[0], strerror(errno
));
398 (void)ioctl(SHIN
, FIOCLEX
, NULL
);
400 /* argc not used any more */ tempv
++;
403 intty
= isatty(SHIN
);
405 if (intty
|| (intact
&& isatty(SHOUT
))) {
406 if (!batch
&& (uid
!= euid
|| gid
!= egid
)) {
408 child
= 1; /* So this doesn't return */
409 stderror(ERR_SYSTEM
, "csh", strerror(errno
));
413 * Decide whether we should play with signals or not. If we are explicitly
414 * told (via -i, or -) or we are a login shell (arg0 starts with -) or the
415 * input and output are both the ttys("csh", or "csh</dev/ttyx>/dev/ttyx")
416 * Note that in only the login shell is it likely that parent may have set
417 * signals to be ignored
419 if (loginsh
|| intact
|| (intty
&& isatty(SHOUT
)))
423 * Save the remaining arguments in argv.
425 setq(STRargv
, blk2short(tempv
), &shvhed
);
431 set(STRprompt
, Strsave(uid
== 0 ? STRsymhash
: STRsymcent
));
432 /* that's a meta-questionmark */
433 set(STRprompt2
, Strsave(STRmquestion
));
437 * If we are an interactive shell, then start fiddling with the signals;
438 * this is a tricky game.
444 if (!quitit
) /* Wary! */
445 (void)signal(SIGQUIT
, SIG_IGN
);
446 (void)signal(SIGINT
, pintr
);
447 sigemptyset(&nsigset
);
448 (void)sigaddset(&nsigset
, SIGINT
);
449 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
450 (void)signal(SIGTERM
, SIG_IGN
);
451 if (quitit
== 0 && arginp
== 0) {
452 (void)signal(SIGTSTP
, SIG_IGN
);
453 (void)signal(SIGTTIN
, SIG_IGN
);
454 (void)signal(SIGTTOU
, SIG_IGN
);
456 * Wait till in foreground, in case someone stupidly runs csh &
457 * dont want to try to grab away the tty.
461 else if (isatty(FSHOUT
))
463 else if (isatty(OLDSTD
))
468 if ((tpgrp
= tcgetpgrp(f
)) != -1) {
469 if (tpgrp
!= shpgrp
) {
470 sig_t old
= signal(SIGTTIN
, SIG_DFL
);
471 (void)kill(0, SIGTTIN
);
472 (void)signal(SIGTTIN
, old
);
479 * Setpgid will fail if we are a session leader and
480 * mypid == mypgrp (POSIX 4.3.3)
483 if (setpgid(0, shpgrp
) == -1)
486 * We do that after we set our process group, to make sure
487 * that the process group belongs to a process in the same
488 * session as the tty (our process and our group) (POSIX 7.2.4)
490 if (tcsetpgrp(f
, shpgrp
) == -1)
492 (void)ioctl(dcopy(f
, FSHTTY
), FIOCLEX
, NULL
);
496 #ifndef __minix /* MINIX3 has no job control. No need to report this. */
497 (void)fprintf(csherr
, "Warning: no access to tty (%s).\n",
499 (void)fprintf(csherr
, "Thus no job control in this shell.\n");
506 if ((setintr
== 0) && (parintr
== SIG_DFL
))
508 (void)signal(SIGCHLD
, pchild
); /* while signals not ready */
511 * Set an exit here in case of an interrupt or error reading the shell
514 reenter
= setexit(); /* PWP */
515 haderr
= 0; /* In case second time through */
516 if (!fast
&& reenter
== 0) {
517 /* Will have value(STRhome) here because set fast if don't */
525 sigemptyset(&nsigset
);
526 (void)sigaddset(&nsigset
, SIGINT
);
527 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
530 parintr
= SIG_IGN
; /* Disable onintr */
531 #ifdef _PATH_DOTCSHRC
532 (void)srcfile(_PATH_DOTCSHRC
, 0, 0);
534 if (!fast
&& !arginp
&& !onelflg
)
536 #ifdef _PATH_DOTLOGIN
538 (void)srcfile(_PATH_DOTLOGIN
, 0, 0);
540 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
544 (void)srccat(value(STRhome
), STRsldotcshrc
);
546 if (!fast
&& !arginp
&& !onelflg
&& !havhash
)
549 * Source history before .login so that it is available in .login
551 if ((cp
= value(STRhistfile
)) != STRNULL
)
553 dosource(tildehist
, NULL
);
555 (void)srccat(value(STRhome
), STRsldotlogin
);
559 * Now are ready for the -v and -x flags
567 * All the rest of the world is inside this call. The argument to process
568 * indicates whether it should catch "error unwinds". Thus if we are a
569 * interactive shell our call here will never return by being blown past on
579 (void)fprintf(cshout
, "logout\n");
585 (void)fprintf(cshout
, "exit\n");
597 (void)setpgid(0, opgrp
);
598 (void)tcsetpgrp(FSHTTY
, opgrp
);
609 for (dp
= cp
; *dp
; dp
++)
613 * i+2 where i is the number of colons in the path. There are i+1
614 * directories in the path plus we need room for a zero terminator.
616 pv
= (Char
**)xcalloc((size_t) (i
+ 2), sizeof(Char
**));
621 if ((c
= *dp
) == ':' || c
== 0) {
623 pv
[i
++] = Strsave(*cp
? cp
: STRdot
);
634 setq(STRpath
, pv
, &shvhed
);
638 * Source to the file which is the catenation of the argument names.
641 srccat(Char
*cp
, Char
*dp
)
649 return srcfile(ptr
, mflag
? 0 : 1, 0);
653 * Source to a file putting the file descriptor in a safe place (> 2).
656 srcfile(const char *f
, int onlyown
, int flag
)
660 if ((unit
= open(f
, O_RDONLY
)) == -1)
662 unit
= dmove(unit
, -1);
664 (void) ioctl(unit
, FIOCLEX
, NULL
);
665 srcunit(unit
, onlyown
, flag
);
670 * Source to a unit. If onlyown it must be our file or our group or
671 * we don't chance it. This occurs on ".cshrc"s and the like.
676 srcunit(int unit
, int onlyown
, int hflg
)
678 /* We have to push down a lot of state here */
679 /* All this could go into a structure */
680 struct whyle
*oldwhyl
;
682 sigset_t nsigset
, osigset
;
684 Char
*oarginp
, *oevalp
, **oevalvec
, *ogointr
;
686 int oSHIN
, oinsource
, oldintty
, oonelflg
;
687 int oenterhist
, otell
;
688 /* The (few) real local variables */
693 oinsource
= insource
;
700 oenterhist
= enterhist
;
711 if (fstat(unit
, &stb
) < 0) {
718 * There is a critical section here while we are pushing down the input
719 * stream since we have stuff in different structures. If we weren't
720 * careful an interrupt could corrupt SHIN's Bin structure and kill the
723 * We could avoid the critical region by grouping all the stuff in a single
724 * structure and pointing at it to move it all at once. This is less
725 * efficient globally on many variable references however.
731 sigemptyset(&nsigset
);
732 (void)sigaddset(&nsigset
, SIGINT
);
733 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
735 /* Setup the new values of the state stuff saved above */
736 (void)memcpy(&saveB
, &B
, sizeof(B
));
738 fseekp
= feobp
= fblocks
= 0;
739 oSHIN
= SHIN
, SHIN
= unit
, arginp
= 0, onelflg
= 0;
740 intty
= isatty(SHIN
), whyles
= 0, gointr
= 0;
748 * Now if we are allowing commands to be interrupted, we let ourselves be
752 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
755 if ((my_reenter
= setexit()) == 0)
756 process(0); /* 0 -> blow away on errors */
759 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
763 /* We made it to the new state... free up its storage */
764 /* This code could get run twice but xfree doesn't care */
765 for (i
= 0; i
< fblocks
; i
++)
766 xfree((ptr_t
) fbuf
[i
]);
769 /* Reset input arena */
770 (void)memcpy(&B
, &saveB
, sizeof(B
));
772 (void)close(SHIN
), SHIN
= oSHIN
;
773 arginp
= oarginp
, onelflg
= oonelflg
;
774 evalp
= oevalp
, evalvec
= oevalvec
;
775 intty
= oldintty
, whyles
= oldwhyl
, gointr
= ogointr
;
778 enterhist
= oenterhist
;
784 * If process reset() (effectively an unwind) then we must also unwind.
787 stderror(ERR_SILENT
);
788 insource
= oinsource
;
794 Char buf
[BUFSIZE
], hbuf
[BUFSIZE
], *hfile
;
795 int fp
, ftmp
, oldidfds
;
796 struct varent
*shist
;
800 * If $savehist is just set, we use the value of $history
801 * else we use the value in $savehist
803 if ((shist
= adrof(STRsavehist
)) != NULL
) {
804 if (shist
->vec
[0][0] != '\0')
805 (void)Strcpy(hbuf
, shist
->vec
[0]);
806 else if ((shist
= adrof(STRhistory
)) && shist
->vec
[0][0] != '\0')
807 (void)Strcpy(hbuf
, shist
->vec
[0]);
814 if ((hfile
= value(STRhistfile
)) == STRNULL
) {
815 hfile
= Strcpy(buf
, value(STRhome
));
816 (void) Strcat(buf
, STRsldthist
);
819 if ((fp
= open(short2str(hfile
), O_WRONLY
| O_CREAT
| O_TRUNC
,
828 dohist(dumphist
, NULL
);
841 (void)signal(SIGQUIT
, SIG_IGN
);
842 (void)signal(SIGINT
, SIG_IGN
);
843 (void)signal(SIGTERM
, SIG_IGN
);
844 setintr
= 0; /* No interrupts after "logout" */
845 if (!(adrof(STRlogout
)))
846 set(STRlogout
, STRnormal
);
847 #ifdef _PATH_DOTLOGOUT
848 (void)srcfile(_PATH_DOTLOGOUT
, 0, 0);
851 (void)srccat(value(STRhome
), STRsldtlogout
);
865 * Note that if STATUS is corrupted (i.e. getn bombs) then error will exit
866 * directly because we poke child here. Otherwise we might continue
867 * unwarrantedly (sic).
870 s
= value(STRstatus
);
871 xexit(s
? getn(s
) : 0);
876 * in the event of a HUP we want to save the history
884 * We kill the last foreground process group. It then becomes
885 * responsible to propagate the SIGHUP to its progeny.
888 struct process
*pp
, *np
;
890 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
) {
893 * Find if this job is in the foreground. It could be that
894 * the process leader has exited and the foreground flag
899 * If a process is in the foreground; we try to kill
900 * its process group. If we succeed, then the
901 * whole job is gone. Otherwise we keep going...
902 * But avoid sending HUP to the shell again.
904 if ((np
->p_flags
& PFOREGND
) != 0 && np
->p_jobid
!= shpgrp
&&
905 kill(-np
->p_jobid
, SIGHUP
) != -1) {
906 /* In case the job was suspended... */
907 (void)kill(-np
->p_jobid
, SIGCONT
);
910 while ((np
= np
->p_friends
) != pp
);
917 Char
*jobargv
[2] = {STRjobs
, 0};
920 * Catch an interrupt, e.g. during lexical input.
921 * If we are an interactive shell, we reset the interrupt catch
922 * immediately. In any case we drain the shell output,
923 * and finally go through the normal error mechanism, which
924 * gets a chance to make the shell go away.
938 sigset_t nsigset
, osigset
;
940 sigemptyset(&nsigset
);
941 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
944 (void)sigdelset(&nsigset
, SIGINT
);
945 (void)sigprocmask(SIG_SETMASK
, &nsigset
, NULL
);
948 (void)fprintf(cshout
, "\n");
949 dojobs(jobargv
, NULL
);
950 stderror(ERR_NAME
| ERR_INTR
);
953 (void)sigdelset(&osigset
, SIGCHLD
);
954 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
955 (void)fpurge(cshout
);
959 * If we have an active "onintr" then we search for the label. Note that if
960 * one does "onintr -" then we shan't be interruptible so we needn't worry
966 if ((v
= pargv
) != NULL
)
967 pargv
= 0, blkfree(v
);
968 if ((v
= gargv
) != NULL
)
969 gargv
= 0, blkfree(v
);
972 else if (intty
&& wantnl
) {
973 (void)fputc('\r', cshout
);
974 (void)fputc('\n', cshout
);
976 stderror(ERR_SILENT
);
981 * Process is the main driving routine for the shell.
982 * It runs all command processing, except for those within { ... }
983 * in expressions (which is run by a routine evalav in sh.exp.c which
984 * is a stripped down process), and `...` evaluation which is run
985 * also by a subset of this code in sh.glob.c in the routine backeval.
987 * The code here is a little strange because part of it is interruptible
988 * and hence freeing of structures appears to occur when none is necessary
989 * if this is ignored.
991 * Note that if catch is not set then we will unwind on any error.
992 * If an end-of-file occurs, we return.
994 static struct command
*savet
= NULL
;
1008 paraml
.next
= paraml
.prev
= ¶ml
;
1009 paraml
.word
= STRNULL
;
1011 justpr
= enterhist
; /* execute if not entering history */
1014 * Interruptible during interactive reads
1017 sigemptyset(&nsigset
);
1018 (void)sigaddset(&nsigset
, SIGINT
);
1019 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
1023 * For the sake of reset()
1027 freesyn(savet
), savet
= NULL
;
1039 * Every error is eventually caught here or the shell dies. It is
1040 * at this point that we clean up any left-over open files, by
1041 * closing all but a fixed number of pre-defined files. Thus
1042 * routines don't have to worry about leaving files open due to
1043 * deeper errors... they will get closed here.
1056 if (intty
&& prompt
&& evalvec
== 0) {
1059 * If we are at the end of the input buffer then we are going to
1060 * read fresh stuff. Otherwise, we are rereading input and don't
1061 * need or want to prompt.
1063 if (aret
== F_SEEK
&& fseekp
== feobp
)
1065 (void)fflush(cshout
);
1068 xfree((ptr_t
) seterr
);
1073 * Echo not only on VERBOSE, but also with history expansion. If there
1074 * is a lexical error then we forego history echo.
1076 if ((lex(¶ml
) && !seterr
&& intty
) || adrof(STRverbose
)) {
1077 int odidfds
= didfds
;
1080 prlex(csherr
, ¶ml
);
1086 * The parser may lose space if interrupted.
1089 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
1092 * Save input text on the history list if reading in old history, or it
1093 * is from the terminal at the top level and not in a loop.
1095 * PWP: entry of items in the history list while in a while loop is done
1098 if (enterhist
|| (catch && intty
&& !whyles
))
1102 * Print lexical error messages, except when sourcing history lists.
1104 if (!enterhist
&& seterr
)
1108 * If had a history command :p modifier then this is as far as we
1117 * Parse the words of the input into a parse tree.
1119 savet
= syntax(paraml
.next
, ¶ml
, 0);
1123 execute(savet
, (tpgrp
> 0 ? tpgrp
: -1), NULL
, NULL
);
1129 freesyn((struct command
*) savet
), savet
= NULL
;
1137 dosource(Char
**v
, struct command
*t
)
1139 Char buf
[BUFSIZE
], *f
;
1144 if (*v
&& eq(*v
, STRmh
)) {
1146 stderror(ERR_NAME
| ERR_HFLAG
);
1149 (void)Strcpy(buf
, *v
);
1150 f
= globone(buf
, G_ERROR
);
1151 (void)strcpy((char *)buf
, short2str(f
));
1153 if (!srcfile((char *)buf
, 0, hflg
) && !hflg
)
1154 stderror(ERR_SYSTEM
, (char *)buf
, strerror(errno
));
1159 * If we are a login shell, then we don't want to tell
1160 * about any mail file unless its been modified
1161 * after the time we started.
1162 * This prevents us from telling the user things he already
1163 * knows, since the login program insists on saying
1182 intvl
= (cnt
&& number(*vp
)) ? (--cnt
, getn(*vp
++)) : MAILINTVL
;
1185 if (chktim
+ intvl
> t
)
1188 if (stat(short2str(*vp
), &stb
) < 0)
1190 new = stb
.st_mtime
> time0
.tv_sec
;
1191 if (stb
.st_size
== 0 || stb
.st_atime
> stb
.st_mtime
||
1192 (stb
.st_atime
< chktim
&& stb
.st_mtime
< chktim
) ||
1196 (void)fprintf(cshout
, "You have %smail.\n", new ? "new " : "");
1198 (void)fprintf(cshout
, "%s in %s.\n", new ? "New mail" : "Mail",
1205 * Extract a home directory from the password file
1206 * The argument points to a buffer where the name of the
1207 * user whose home directory is sought is currently.
1208 * We write the home directory of the user back there.
1219 if (*home
== '\0') {
1220 if ((h
= value(STRhome
)) != NULL
) {
1221 (void)Strcpy(home
, h
);
1228 if ((pw
= getpwnam(short2str(home
))) != NULL
) {
1229 (void)Strcpy(home
, str2short(pw
->pw_dir
));
1237 * When didfds is set, we do I/O from 0, 1, 2 otherwise from 15, 16, 17
1238 * We also check if the shell has already changed the descriptor to point to
1239 * 0, 1, 2 when didfds is set.
1241 #define DESC(a) (*((int *) (a)) - (didfds && *((int *) a) >= FSHIN ? FSHIN : 0))
1244 readf(void *oreo
, void *buf
, size_t siz
)
1246 return read(DESC(oreo
), buf
, siz
);
1251 writef(void *oreo
, const void *buf
, size_t siz
)
1253 return write(DESC(oreo
), buf
, siz
);
1257 seekf(void *oreo
, off_t off
, int whence
)
1259 return lseek(DESC(oreo
), off
, whence
);
1266 return close(DESC(oreo
));
1271 * Print the visible version of a string.
1274 vis_fputc(int ch
, FILE *fp
)
1276 char uenc
[5]; /* 4 + NULL */
1279 return fputc(ch
& TRIM
, fp
);
1281 * XXX: When we are in AsciiOnly we want all characters >= 0200 to
1282 * be encoded, but currently there is no way in vis to do that.
1284 (void)vis(uenc
, ch
& TRIM
, VIS_NOSLASH
, 0);
1285 return (fputs(uenc
, fp
));
1289 * Move the initial descriptors to their eventual
1290 * resting places, closing all other units.
1295 didfds
= 0; /* 0, 1, 2 aren't set up */
1296 (void)ioctl(SHIN
= dcopy(0, FSHIN
), FIOCLEX
, NULL
);
1297 (void)ioctl(SHOUT
= dcopy(1, FSHOUT
), FIOCLEX
, NULL
);
1298 (void)ioctl(SHERR
= dcopy(2, FSHERR
), FIOCLEX
, NULL
);
1299 (void)ioctl(OLDSTD
= dcopy(SHIN
, FOLDSTD
), FIOCLEX
, NULL
);
1316 #ifndef _PATH_DEFPATH
1324 blkp
= blk
= xmalloc((size_t) sizeof(Char
*) * 10);
1326 #define DIRAPPEND(a) \
1327 if (stat(ptr = a, &stb) == 0 && S_ISDIR(stb.st_mode)) \
1330 DIRAPPEND(RESCUEDIR
);
1332 DIRAPPEND(_PATH_BIN
);
1333 DIRAPPEND(_PATH_USRBIN
);
1338 if (euid
!= 0 && uid
!= 0)
1339 *blkp
++ = Strsave(STRdot
);
1345 #endif /* _PATH_DEFPATH */
1356 for (cp
= value(STRprompt
); *cp
; cp
++)
1358 (void)fprintf(cshout
, "%d", eventno
+ 1);
1360 if (*cp
== '\\' && cp
[1] == HIST
)
1362 (void)vis_fputc(*cp
| QUOTE
, cshout
);
1367 * Prompt for forward reading loop body content.
1369 (void)fprintf(cshout
, "? ");
1370 (void)fflush(cshout
);
1375 printpromptstr(EditLine
*elx
) {
1376 static char pbuf
[1024];
1377 static char qspace
[] = "? ";
1385 for (cp
= value(STRprompt
); *cp
; cp
++) {
1386 if (i
>= sizeof(pbuf
))
1390 r
= snprintf(pbuf
+ i
, sizeof(pbuf
) - i
, "%d", eventno
+ 1);
1394 pbuf
[i
++] = (char)*cp
;
1396 if (i
>= sizeof(pbuf
))
1397 i
= sizeof(pbuf
) - 1;