1fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes/*	$OpenBSD: main.c,v 1.57 2015/09/10 22:48:58 nicm Exp $	*/
256b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes/*	$OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $	*/
3fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes/*	$OpenBSD: io.c,v 1.26 2015/09/11 08:00:27 guenther Exp $	*/
4fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes/*	$OpenBSD: table.c,v 1.16 2015/09/01 13:12:31 tedu Exp $	*/
55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
7c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
8a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes *		 2011, 2012, 2013, 2014, 2015, 2016, 2017
9fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes *	mirabilos <m@mirbsd.org>
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define EXTERN
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_LANGINFO_CODESET
315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <langinfo.h>
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SETLOCALE_CTYPE
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <locale.h>
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
37a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes__RCSID("$MirOS: src/bin/mksh/main.c,v 1.332 2017/04/12 16:01:45 tg Exp $");
385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruextern char **environ;
405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSHRC_PATH
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MKSHRC_PATH	"~/.mkshrc"
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_DEFAULT_TMPDIR
4696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#define MKSH_DEFAULT_TMPDIR	MKSH_UNIXROOT "/tmp"
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
49c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic uint8_t isuc(const char *);
50c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int main_init(int, const char *[], Source **, struct block **);
5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid chvt_reinit(void);
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void reclaim(void);
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void remove_temps(struct temp *);
5403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic mksh_uari_t rndsetup(void);
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH
565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void x_sigwinch(int);
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char initsubs[] =
60966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${PS2=> }"
61966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${PS3=#? }"
62966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${PS4=+ }"
63966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${SECONDS=0}"
64966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${TMOUT=0}"
65966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes    "${EPOCHREALTIME=}";
665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *initcoms[] = {
6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Ttypeset, "-r", initvsn, NULL,
6977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	Ttypeset, "-x", "HOME", TPATH, TSHELL, NULL,
70c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Talias,
72a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"integer=\\\\builtin typeset -i",
73a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"local=\\\\builtin typeset",
7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* not "alias -t --": hash -r needs to work */
75a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"hash=\\\\builtin alias -t",
76a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"type=\\\\builtin whence -v",
77a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"autoload=\\\\builtin typeset -fu",
78a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"functions=\\\\builtin typeset -f",
79a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"history=\\\\builtin fc -l",
80a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"nameref=\\\\builtin typeset -n",
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	"nohup=nohup ",
82a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"r=\\\\builtin fc -e -",
83a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	"login=\\\\builtin exec login",
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	NULL,
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 /* this is what AT&T ksh seems to track, with the addition of emacs */
8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Talias, "-tU",
8796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes	Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
8877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	"make", "mv", "pr", "rm", "sed", Tsh, "vi", "who", NULL,
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	NULL
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *restr_com[] = {
9377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	Ttypeset, "-r", TPATH, "ENV", TSHELL, NULL
9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra};
9503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
96c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic bool initio_done;
975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* top-level parsing and execution environment */
9903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic struct env env;
10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct env *e = &env;
10103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
102a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* compile-time assertions */
103a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#define cta(name, expr) struct cta_ ## name { char t[(expr) ? 1 : -1]; }
104a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
105a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* this one should be defined by the standard */
106a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(char_is_1_char, (sizeof(char) == 1) && (sizeof(signed char) == 1) &&
107a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes    (sizeof(unsigned char) == 1));
108a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(char_is_8_bits, ((CHAR_BIT) == 8) && ((int)(unsigned char)0xFF == 0xFF) &&
109a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes    ((int)(unsigned char)0x100 == 0) && ((int)(unsigned char)(int)-1 == 0xFF));
110a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* the next assertion is probably not really needed */
111a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(short_is_2_char, sizeof(short) == 2);
112a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(short_size_no_matter_of_signedness, sizeof(short) == sizeof(unsigned short));
113a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* the next assertion is probably not really needed */
114a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(int_is_4_char, sizeof(int) == 4);
115a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(int_size_no_matter_of_signedness, sizeof(int) == sizeof(unsigned int));
116a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
117a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(long_ge_int, sizeof(long) >= sizeof(int));
118a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(long_size_no_matter_of_signedness, sizeof(long) == sizeof(unsigned long));
119a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
120a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#ifndef MKSH_LEGACY_MODE
121a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* the next assertion is probably not really needed */
122a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ari_is_4_char, sizeof(mksh_ari_t) == 4);
123a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* but this is */
124a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ari_has_31_bit, 0 < (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1));
125a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* the next assertion is probably not really needed */
126a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(uari_is_4_char, sizeof(mksh_uari_t) == 4);
127a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* but the next three are; we REQUIRE unsigned integer wraparound */
128a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(uari_has_31_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 2 + 1));
129a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3));
130a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(uari_wrap_32_bit,
131a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes    (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
132a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes    (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
133a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#endif
134a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* these are always required */
135a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
136a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
137a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* we require these to have the precisely same size and assume 2s complement */
138a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
139a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
140a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
141a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
142a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
143a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes/* our formatting routines assume this */
144a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
145a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughescta(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
146a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic mksh_uari_t
14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrarndsetup(void)
14903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
15003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	register uint32_t h;
15103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct {
15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ALLOC_ITEM alloc_INT;
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		void *dataptr, *stkptr, *mallocptr;
154c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(__GLIBC__) && (__GLIBC__ >= 2)
15503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigjmp_buf jbuf;
156c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		struct timeval tv;
15803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} *bufptr;
15903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp;
16003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
16177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	cp = alloc(sizeof(*bufptr) - sizeof(ALLOC_ITEM), APERM);
162966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes	/* clear the allocated space, for valgrind and to avoid UB */
16377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	memset(cp, 0, sizeof(*bufptr) - sizeof(ALLOC_ITEM));
16403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* undo what alloc() did to the malloc result address */
16577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	bufptr = (void *)(cp - sizeof(ALLOC_ITEM));
16603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* PIE or something similar provides us with deltas here */
16703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bufptr->dataptr = &rndsetupstate;
16803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* ASLR in at least Windows, Linux, some BSDs */
16903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bufptr->stkptr = &bufptr;
17003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* randomised malloc in BSD (and possibly others) */
17103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bufptr->mallocptr = bufptr;
172c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(__GLIBC__) && (__GLIBC__ >= 2)
17303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* glibc pointer guard */
17403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	sigsetjmp(bufptr->jbuf, 1);
175c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
176c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* introduce variation (and yes, second arg MBZ for portability) */
177c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_TIME(bufptr->tv);
17803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
17977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
18077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	mprotect(((char *)bufptr) + 4096, 4096, PROT_READ | PROT_WRITE);
18177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes#endif
182811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	h = chvt_rndsetup(bufptr, sizeof(*bufptr));
183811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser
184811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	afree(cp, APERM);
185811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	return ((mksh_uari_t)h);
186811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser}
187811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchvt_reinit(void)
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	kshpid = procpid = getpid();
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ksheuid = geteuid();
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	kshpgrp = getpgrp();
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	kshppid = getppid();
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
19703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *empty_argv[] = {
19877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	Tmksh, NULL
19903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra};
20003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
201c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic uint8_t
202c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserisuc(const char *cx) {
203c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	char *cp, *x;
204c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	uint8_t rv = 0;
205c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
206c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (!cx || !*cx)
207c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (0);
208c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
209c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* uppercase a string duplicate */
210c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	strdupx(x, cx, ATEMP);
211c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cp = x;
212c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while ((*cp = ksh_toupper(*cp)))
213c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		++cp;
214c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
215c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* check for UTF-8 */
216c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (strstr(x, "UTF-8") || strstr(x, "UTF8"))
217c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		rv = 1;
218c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
219c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* free copy and out */
220c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	afree(x, ATEMP);
221c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (rv);
222c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
223c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
224c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int
225c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermain_init(int argc, const char *argv[], Source **sp, struct block **lp)
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argi, i;
22803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Source *s = NULL;
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l;
23056b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes	unsigned char restricted_shell, errexit, utf_flag;
23103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp;
23203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *ccp, **wp;
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp;
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct stat s_stdin;
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
23603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t k;
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23996b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#ifdef __OS2__
24096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes	for (i = 0; i < 3; ++i)
24196b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if (!isatty(i))
24296b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes			setmode(i, O_BINARY);
243a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes
244a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	os2_init(&argc, &argv);
24596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#endif
24696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* do things like getpgrp() et al. */
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	chvt_reinit();
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
250fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	/* make sure argv[] is sane, for weird OSes */
2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!*argv) {
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argv = empty_argv;
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argc = 1;
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	kshname = argv[0];
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* initialise permanent Area */
25803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ainit(&aperm);
25977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	/* max. name length: -2147483648 = 11 (+ NUL) */
26077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	vtemp = alloc(offsetof(struct tbl, name[0]) + 12, APERM);
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set up base environment */
26303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	env.type = E_NONE;
26403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ainit(&env.area);
26503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* set up global l->vars and l->funs */
26603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	newblock();
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Do this first so output routines (eg, errorf, shellf) can work */
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	initio();
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* determine the basename (without '-' or path) of the executable */
27203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ccp = kshname;
273966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes	goto begin_parsing_kshname;
27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((i = ccp[argi++])) {
275966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes		if (mksh_cdirsep(i)) {
27603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp += argi;
277966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes begin_parsing_kshname:
27803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			argi = 0;
27903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (*ccp == '-')
28003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				++ccp;
28103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
28203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
28303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!*ccp)
28403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ccp = empty_argv[0];
28503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
286737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	/*
287737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 * Turn on nohup by default. (AT&T ksh does not have a nohup
288737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 * option - it always sends the hup).
289737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 */
290737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	Flag(FNOHUP) = 1;
291737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes
292737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	/*
293737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 * Turn on brace expansion by default. AT&T kshs that have
294737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 * alternation always have it on.
295737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 */
296737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	Flag(FBRACEEXPAND) = 1;
297737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes
298737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	/*
299737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 * Turn on "set -x" inheritance by default.
300737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	 */
301737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	Flag(FXTRACEREC) = 1;
302737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes
30303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* define built-in commands and see if we were called as one */
30403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(APERM, &builtins,
305fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	    /* currently up to 54 builtins: 75% of 128 = 2^7 */
306c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    7);
30703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	for (i = 0; mkshbuiltins[i].name != NULL; i++)
30803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!strcmp(ccp, builtin(mkshbuiltins[i].name,
30903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    mkshbuiltins[i].func)))
31003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Flag(FAS_BUILTIN) = 1;
31103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
31203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!Flag(FAS_BUILTIN)) {
31303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* check for -T option early */
31403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		argi = parse_args(argv, OF_FIRSTTIME, NULL);
31503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (argi < 0)
31603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (1);
31703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
318811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
319811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		/* are we called as -sh or /bin/sh or so? */
32096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) {
321811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			/* either also turns off braceexpand */
322811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifdef MKSH_BINSHPOSIX
323811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			/* enable better POSIX conformance */
324811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			change_flag(FPOSIX, OF_FIRSTTIME, true);
325811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif
32603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef MKSH_BINSHREDUCED
327811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			/* enable kludge/compat mode */
328c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			change_flag(FSH, OF_FIRSTTIME, true);
32903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
330811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		}
331811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif
33203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	initvar();
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	initctypes();
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	inittraps();
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	coproc_init();
3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set up variable and command dictionaries */
34303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(APERM, &taliases, 0);
34403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(APERM, &aliases, 0);
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM
34603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ktinit(APERM, &homedirs, 0);
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* define shell keywords */
3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	initkeywords();
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	init_histvec();
3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
354c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* initialise tty size before importing environment */
355c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	change_winsz();
356c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _PATH_DEFPATH
3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	def_path = _PATH_DEFPATH;
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _CS_PATH
36103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((k = confstr(_CS_PATH, NULL, 0)) > 0 &&
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1)
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		def_path = cp;
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * this is uniform across all OSes unless it
36877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		 * breaks somewhere hard; don't try to optimise,
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * e.g. add stuff for Interix or remove /usr
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * for HURD, because e.g. Debian GNU/HURD is
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * "keeping a regular /usr"; this is supposed
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * to be a sane 'basic' default PATH
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
37496b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS
37596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		    MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS
37696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		    MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS
37796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		    MKSH_UNIXROOT "/usr/sbin";
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
38003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
38103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Set PATH to def_path (will set the path global variable).
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * (import of environment below will probably change this setting).
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
38477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	vp = global(TPATH);
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* setstr can't fail here */
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setstr(vp, def_path, KSH_RETURN_ERROR);
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
388c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
38903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
39003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Set edit mode to emacs by default, may be overridden
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * by the environment or the user. Also, we want tab completion
39203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * on in vi by default.
39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 */
394c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	change_flag(FEMACS, OF_SPECIAL, true);
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FVITABCOMPLETE) = 1;
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
398c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* import environment */
401737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	if (environ != NULL) {
402737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		wp = (const char **)environ;
403737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		while (*wp != NULL) {
404737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			rndpush(*wp);
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
406737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			++wp;
407737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		}
408737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	}
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
410c2036115102d80c026b70846812a42204522f9acSandeep Patil	/* override default PATH regardless of environment */
411c2036115102d80c026b70846812a42204522f9acSandeep Patil#ifdef MKSH_DEFPATH_OVERRIDE
412c2036115102d80c026b70846812a42204522f9acSandeep Patil	 vp = global(TPATH);
413c2036115102d80c026b70846812a42204522f9acSandeep Patil	 setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR);
414c2036115102d80c026b70846812a42204522f9acSandeep Patil#endif
415c2036115102d80c026b70846812a42204522f9acSandeep Patil
41603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* for security */
417a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	typeset("IFS= \t\n", 0, 0, 0, 0);
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* assign default shell variable values */
420a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	typeset("PATHSEP=" MKSH_PATHSEPS, 0, 0, 0, 0);
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	substitute(initsubs, 0);
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Figure out the current working directory and set $PWD */
42477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	vp = global(TPWD);
42503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	cp = str_val(vp);
42603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* Try to use existing $PWD if it is valid */
42777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp,
42877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	    Tdot, true)) ? cp : NULL);
42903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (current_wd[0])
43003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		simplify_path(current_wd);
43103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* Only set pwd if we know where we are or if it had a bogus value */
43203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (current_wd[0] || *cp)
43303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* setstr can't fail here */
43403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		setstr(vp, current_wd, KSH_RETURN_ERROR);
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (wp = initcoms; *wp != NULL; wp++) {
437a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		c_builtin(wp);
4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*wp != NULL)
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
441c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n(global("OPTIND"), 1, 10);
44203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
44303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	kshuid = getuid();
44403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	kshgid = getgid();
44503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	kshegid = getegid();
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	safe_prompt = ksheuid ? "$ " : "# ";
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp = global("PS1");
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Set PS1 if unset or we are root and prompt doesn't contain a # */
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(vp->flag & ISSET) ||
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (!ksheuid && !strchr(str_val(vp), '#')))
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* setstr can't fail here */
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setstr(vp, safe_prompt, KSH_RETURN_ERROR);
454c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("BASHPID")), 0, 10);
455c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	vp->flag |= INT_U;
456c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10);
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= INT_U;
458c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10);
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= INT_U;
460c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10);
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= INT_U;
462c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10);
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vp->flag |= INT_U;
464c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10);
46503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp->flag |= INT_U;
466c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10);
46703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp->flag |= INT_U;
468c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp = global("RANDOM")), rndsetup(), 10);
46903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vp->flag |= INT_U;
470c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Set this before parsing arguments */
473fc0307d88e2ab13777f102dc63c0d1c968dc8bb2Elliott Hughes	Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* this to note if monitor is set on command line (see below) */
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FMONITOR) = 127;
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* this to note if utf-8 mode is set on command line (see below) */
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	UTFMODE = 2;
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
48203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!Flag(FAS_BUILTIN)) {
48303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		argi = parse_args(argv, OF_CMDLINE, NULL);
48403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (argi < 0)
48503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (1);
48603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
48703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* process this later only, default to off (hysterical raisins) */
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	utf_flag = UTFMODE;
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	UTFMODE = 0;
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
49203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (Flag(FAS_BUILTIN)) {
49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* auto-detect from environment variables, always */
49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		utf_flag = 3;
49503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else if (Flag(FCOMMAND)) {
496c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		s = pushs(SSTRINGCMDLINE, ATEMP);
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(s->start = s->str = argv[argi++]))
49877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			errorf(Tf_optfoo, "", "", 'c', Treq_arg);
499c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		while (*s->str) {
500c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
501c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				break;
502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			s->str++;
503c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!*s->str)
505c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			s->flags |= SF_MAYEXEC;
506c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		s->str = s->start;
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			++argi;
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (argv[argi])
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			kshname = argv[argi++];
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (argi < argc && !Flag(FSTDIN)) {
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = pushs(SFILE, ATEMP);
51696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#ifdef __OS2__
51796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		/*
51896b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		 * A bug in OS/2 extproc (like shebang) handling makes
51996b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		 * it not pass the full pathname of a script, so we need
52096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		 * to search for it. This changes the behaviour of a
52196b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		 * simple "mksh foo", but can't be helped.
52296b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		 */
523a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		s->file = argv[argi++];
524a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		if (search_access(s->file, X_OK) != 0)
525a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			s->file = search_path(s->file, path, X_OK, NULL);
52696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if (!s->file || !*s->file)
52796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes			s->file = argv[argi - 1];
52896b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#else
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->file = argv[argi++];
53096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes#endif
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->u.shf = shf_open(s->file, O_RDONLY, 0,
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    SHF_MAPHI | SHF_CLEXEC);
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->u.shf == NULL) {
53403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shl_stdout_ok = false;
53577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			warningf(true, Tf_sD_s, s->file, cstrerror(errno));
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* mandated by SUSv4 */
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = 127;
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unwind(LERROR);
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		kshname = s->file;
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Flag(FSTDIN) = 1;
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = pushs(SSTDIN, ATEMP);
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->file = "<stdin>";
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    NULL);
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (isatty(0) && isatty(2)) {
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Flag(FTALKING) = Flag(FTALKING_I) = 1;
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* The following only if isatty(0) */
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->flags |= SF_TTY;
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->u.shf->flags |= SHF_INTERRUPT;
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s->file = NULL;
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* this bizarreness is mandated by POSIX */
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) &&
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    Flag(FTALKING))
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		reset_nonblock(0);
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* initialise job control */
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	j_init();
563c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* do this after j_init() which calls tty_init_state() */
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Flag(FTALKING)) {
5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (utf_flag == 2) {
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_ASSUME_UTF8
56703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* auto-detect from locale or environment */
56803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			utf_flag = 4;
569737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes#else /* this may not be an #elif */
570737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes#if MKSH_ASSUME_UTF8
57103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			utf_flag = 1;
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
57303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* always disable UTF-8 (for interactive) */
57403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			utf_flag = 0;
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
576737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes#endif
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
578c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		x_init();
580c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGWINCH].flags |= TF_SHELL_USES;
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGWINCH], x_sigwinch,
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l = e->loc;
59003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (Flag(FAS_BUILTIN)) {
59103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argc = argc;
59203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argv = argv;
59303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argv[0] = ccp;
59403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
59503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argc = argc - argi;
596c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/*
597c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * allocate a new array because otherwise, when we modify
598c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * it in-place, ps(1) output changes; the meaning of argc
599c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * here is slightly different as it excludes kshname, and
600c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * we add a trailing NULL sentinel as well
601c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 */
602c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		l->argv = alloc2(l->argc + 2, sizeof(void *), APERM);
60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argv[0] = kshname;
604c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *));
605c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		l->argv[l->argc + 1] = NULL;
60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		getopts_reset(1);
60703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
60803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
60903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* divine the initial state of the utf8-mode Flag */
61003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ccp = null;
61103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (utf_flag) {
61203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
61303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* auto-detect from locale or environment */
61403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 4:
61503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SETLOCALE_CTYPE
61603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ccp = setlocale(LC_CTYPE, "");
61703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_LANGINFO_CODESET
61803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!isuc(ccp))
61903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp = nl_langinfo(CODESET);
62003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
62103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!isuc(ccp))
62203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp = null;
62303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
624966dd55b233982d9657c50b971cfa754d0315c19Elliott Hughes		/* FALLTHROUGH */
62503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
62603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* auto-detect from environment */
62703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 3:
62803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* these were imported from environ earlier */
62903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (ccp == null)
63003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp = str_val(global("LC_ALL"));
63103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (ccp == null)
63203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp = str_val(global("LC_CTYPE"));
63303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (ccp == null)
63403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ccp = str_val(global("LANG"));
63503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		UTFMODE = isuc(ccp);
63603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
63703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
63803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* not set on command line, not FTALKING */
63903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 2:
64003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* unknown values */
64103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	default:
64203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		utf_flag = 0;
64303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* FALLTHROUGH */
64403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
64503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* known values */
64603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 1:
64703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 0:
64803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		UTFMODE = utf_flag;
64903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
65003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Disable during .profile/ENV reading */
65356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes	restricted_shell = Flag(FRESTRICTED);
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FRESTRICTED) = 0;
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	errexit = Flag(FERREXIT);
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FERREXIT) = 0;
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
65803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
65903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Do this before profile/$ENV so that if it causes problems in them,
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * user will know why things broke.
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!current_wd[0] && Flag(FTALKING))
66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		warningf(false, "can't determine current directory");
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
665737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	if (Flag(FLOGIN))
666c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
667737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	if (!Flag(FPRIVILEGED)) {
668737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		if (Flag(FLOGIN))
669737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			include(substitute("$HOME/.profile", 0), 0, NULL, true);
670737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		if (Flag(FTALKING)) {
671737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
672737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			    0), DOTILDE);
673737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			if (cp[0] != '\0')
674737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes				include(cp, 0, NULL, true);
675737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		}
676737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes	} else {
677c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		include(MKSH_SUID_PROFILE, 0, NULL, true);
678737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		/* turn off -p if not set explicitly */
679737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		if (Flag(FPRIVILEGED) != 1)
680737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes			change_flag(FPRIVILEGED, OF_INTERNAL, false);
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
68356b517d46cdf4f6ccd6b62b207110e2afc3db30bElliott Hughes	if (restricted_shell) {
684a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		c_builtin(restr_com);
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* After typeset command... */
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Flag(FRESTRICTED) = 1;
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FERREXIT) = errexit;
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
690c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (Flag(FTALKING) && s)
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hist_init(s);
69203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else
69303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* set after ENV */
69403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Flag(FTRACKALL) = 1;
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	alarm_init();
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
698c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	*sp = s;
699c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	*lp = l;
70003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (0);
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
703c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* this indirection barrier reduces stack usage during normal operation */
704c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
705c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserint
706c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermain(int argc, const char *argv[])
707c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
708c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int rv;
709c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	Source *s;
710c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct block *l;
711c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
712c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((rv = main_init(argc, argv, &s, &l)) == 0) {
713c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (Flag(FAS_BUILTIN)) {
714a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			rv = c_builtin(l->argv);
715c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		} else {
716a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			shell(s, 0);
717c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* NOTREACHED */
718c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
719c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
720c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (rv);
721c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
722c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
724c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserinclude(const char *name, int argc, const char **argv, bool intr_ok)
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *volatile s = NULL;
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf *shf;
7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **volatile old_argv;
7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	volatile int old_argc;
7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC);
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (shf == NULL)
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argv) {
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_argv = e->loc->argv;
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_argc = e->loc->argc;
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_argv = NULL;
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_argc = 0;
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	newenv(E_INCL);
744c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((i = kshsetjmp(e->jbuf))) {
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		quitenv(s ? s->u.shf : NULL);
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (old_argv) {
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			e->loc->argv = old_argv;
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			e->loc->argc = old_argc;
7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (i) {
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LRETURN:
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LERROR:
75303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* see below */
75403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (exstat & 0xFF);
7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LINTR:
75603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
75703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * intr_ok is set if we are including .profile or $ENV.
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * If user ^Cs out, we don't want to kill the shell...
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
760c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (intr_ok && ((exstat & 0xFF) - 128) != SIGTERM)
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LEXIT:
7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LLEAVE:
7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case LSHELL:
7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unwind(i);
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* NOTREACHED */
7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
769a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			internal_errorf(Tunexpected_type, Tunwind, Tsource, i);
7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* NOTREACHED */
7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argv) {
7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->loc->argv = argv;
7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->loc->argc = argc;
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = pushs(SFILE, ATEMP);
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->u.shf = shf;
7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	strdupx(s->file, name, ATEMP);
780a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	i = shell(s, 1);
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	quitenv(s->u.shf);
7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (old_argv) {
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->loc->argv = old_argv;
7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->loc->argc = old_argc;
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* & 0xff to ensure value not -1 */
78703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (i & 0xFF);
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* spawn a command into a shell optionally keeping track of the line number */
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucommand(const char *comm, int line)
7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
79477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	Source *s, *sold = source;
79577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	int rv;
7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = pushs(SSTRING, ATEMP);
7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->start = s->str = comm;
7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->line = line;
800a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	rv = shell(s, 1);
80177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	source = sold;
80277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	return (rv);
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * run the commands from the input source, returning status.
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
809a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughesshell(Source * volatile s, volatile int level)
8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct op *t;
812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	volatile bool wastty = tobool(s->flags & SF_TTY);
813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	volatile uint8_t attempts = 13;
814a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	volatile bool interactive = (level == 0) && Flag(FTALKING);
81503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	volatile bool sfirst = true;
8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *volatile old_source = source;
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
819a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	newenv(level == 2 ? E_EVAL : E_PARSE);
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (interactive)
821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		really_exit = false;
822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	switch ((i = kshsetjmp(e->jbuf))) {
823c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 0:
824c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
825a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	case LBREAK:
826a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	case LCONTIN:
827a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		if (level != 2) {
828a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			source = old_source;
829a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			quitenv(NULL);
830a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			internal_errorf(Tf_cant_s, Tshell,
831a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			    i == LBREAK ? Tbreak : Tcontinue);
832a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			/* NOTREACHED */
833a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		}
834a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		/* assert: interactive == false */
835a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		/* FALLTHROUGH */
836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LINTR:
837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* we get here if SIGINT not caught or ignored */
838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LERROR:
839c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LSHELL:
840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (interactive) {
841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (i == LINTR)
842c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shellf("\n");
843c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/*
844c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * Reset any eof that was read as part of a
845c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * multiline command.
846c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 */
847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (Flag(FIGNOREEOF) && s->type == SEOF && wastty)
848c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				s->type = SSTDIN;
849c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/*
850c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * Used by exit command to get back to
851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * top level shell. Kind of strange since
852c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * interactive is set if we are reading from
853c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * a tty, but to have stopped jobs, one only
854c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * needs FMONITOR set (not FTALKING/SF_TTY)...
855c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 */
856c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* toss any input we have so far */
857c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			yyrecursive_pop(true);
858c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			s->start = s->str = null;
859c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			retrace_info = NULL;
860c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			herep = heres;
861c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			break;
8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
863c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* FALLTHROUGH */
864c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LEXIT:
865c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LLEAVE:
866c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case LRETURN:
867c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		source = old_source;
868c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		quitenv(NULL);
869c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* keep on going */
870c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		unwind(i);
871c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* NOTREACHED */
872c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	default:
873c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		source = old_source;
874c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		quitenv(NULL);
875a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		internal_errorf(Tunexpected_type, Tunwind, Tshell, i);
876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* NOTREACHED */
8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
87803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (trap)
8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			runtraps(0);
8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (s->next == NULL) {
8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (Flag(FVERBOSE))
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags |= SF_ECHO;
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->flags &= ~SF_ECHO;
8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (interactive) {
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			j_notify();
8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			set_prompt(PS1, s);
8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
892a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		t = compile(s, sfirst, true);
89396b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if (interactive)
89496b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes			histsave(&s->line, NULL, HIST_FLUSH, true);
89503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sfirst = false;
896c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!t)
897c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto source_no_tree;
898c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (t->type == TEOF) {
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {
90003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shellf("Use 'exit' to leave mksh\n");
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SSTDIN;
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (wastty && !really_exit &&
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    j_stopped_running()) {
904c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				really_exit = true;
9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s->type = SSTDIN;
9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
90703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
90803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * this for POSIX which says EXIT traps
9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * shall be taken in the environment
9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * immediately after the last command
9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * executed.
9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
913a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes				if (level == 0)
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					unwind(LEXIT);
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
917737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		} else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
918c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			t->u.evalflags |= DOTCOMEXEC;
919c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
920c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			exstat = execute(t, 0, NULL) & 0xFF;
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (t->type != TEOF && interactive && really_exit)
923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			really_exit = false;
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
925c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser source_no_tree:
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		reclaim();
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	quitenv(NULL);
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = old_source;
930c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (exstat & 0xFF);
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* return to closest error handler or shell(), exit if none found */
934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* note: i MUST NOT be 0 */
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunwind(int i)
9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/*
939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * This is a kludge. We need to restore everything that was
940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * changed in the new environment, see cid 1005090337C7A669439
941c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * and 10050903386452ACBF1, but fail to even save things most of
942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * the time. funcs.c:c_eval() changes FERREXIT temporarily to 0,
943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * which needs to be restored thus (related to Debian #696823).
944c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * We did not save the shell flags, so we use a special or'd
945c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * value here... this is mostly to clean up behind *other*
946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * callers of unwind(LERROR) here; exec.c has the regular case.
947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 */
948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (Flag(FERREXIT) & 0x80) {
949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* GNU bash does not run this trapsig */
950c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		trapsig(ksh_SIGERR);
951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		Flag(FERREXIT) &= ~0x80;
952c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
953c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */
955811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	if (i == LEXIT || ((i == LERROR || i == LINTR) &&
956811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	    sigtraps[ksh_SIGEXIT].trap &&
957811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	    (!Flag(FTALKING) || Flag(FERREXIT)))) {
95803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++trap_nested;
95903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		runtrap(&sigtraps[ksh_SIGEXIT], trap_nested == 1);
96003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--trap_nested;
9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = LLEAVE;
962c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else if (Flag(FERREXIT) == 1 && (i == LERROR || i == LINTR)) {
96303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++trap_nested;
96403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		runtrap(&sigtraps[ksh_SIGERR], trap_nested == 1);
96503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--trap_nested;
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = LLEAVE;
9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
968c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
96903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (/* CONSTCOND */ 1) {
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (e->type) {
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_PARSE:
9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_FUNC:
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_INCL:
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_LOOP:
9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_ERRH:
976a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		case E_EVAL:
977c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			kshlongjmp(e->jbuf, i);
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* NOTREACHED */
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case E_NONE:
9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (i == LINTR)
9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				e->flags |= EF_FAKE_SIGDIE;
9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* FALLTHROUGH */
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			quitenv(NULL);
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunewenv(int type)
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep;
9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *cp;
9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * struct env includes ALLOC_ITEM for alignment constraints
9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * so first get the actually used memory, then assign it
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
99977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	cp = alloc(sizeof(struct env) - sizeof(ALLOC_ITEM), ATEMP);
100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* undo what alloc() did to the malloc result address */
100177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	ep = (void *)(cp - sizeof(ALLOC_ITEM));
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* initialise public members of struct env (not the ALLOC_ITEM) */
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ainit(&ep->area);
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->oenv = e;
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->loc = e->loc;
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->savefd = NULL;
10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->temps = NULL;
1008c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	ep->yyrecursive_statep = NULL;
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->type = type;
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ep->flags = 0;
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* jump buffer is invalid because flags == 0 */
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	e = ep;
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruquitenv(struct shf *shf)
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep = e;
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *cp;
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd;
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1022c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	yyrecursive_pop(true);
1023c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while (ep->oenv && ep->oenv->loc != ep->loc)
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		popblock();
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ep->savefd != NULL) {
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (fd = 0; fd < NUFILE; fd++)
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* if ep->savefd[fd] < 0, means fd was closed */
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ep->savefd[fd])
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				restfd(fd, ep->savefd[fd]);
103003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (ep->savefd[2])
103103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* Clear any write errors */
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_reopen(2, SHF_WR, shl_out);
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Bottom of the stack.
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Either main shell is exiting or cleanup_parents_env() was called.
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ep->oenv == NULL) {
1039c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DEBUG_LEAKS
1040c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		int i;
1041c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1042c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
104303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (ep->type == E_NONE) {
104403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* Main shell exiting? */
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (Flag(FTALKING))
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hist_finish();
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			j_exit();
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ep->flags & EF_FAKE_SIGDIE) {
1051c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				int sig = (exstat & 0xFF) - 128;
10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
105303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/*
105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				 * ham up our death a bit (AT&T ksh
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * only seems to do this for SIGTERM)
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * Don't do it for SIGQUIT, since we'd
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * dump a core..
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((sig == SIGINT || sig == SIGTERM) &&
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    (kshpgrp == kshpid)) {
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					setsig(&sigtraps[sig], SIG_DFL,
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    SS_RESTORE_CURR | SS_FORCE);
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					kill(0, sig);
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (shf)
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_close(shf);
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		reclaim();
1070c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DEBUG_LEAKS
1071c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
1072c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		x_done();
1073c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1074811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_NOPROSPECTOFWORK
1075811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		/* block at least SIGCHLD during/after afreeall */
1076811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		sigprocmask(SIG_BLOCK, &sm_sigchld, NULL);
1077811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif
1078c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		afreeall(APERM);
1079c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		for (fd = 3; fd < NUFILE; fd++)
1080c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((i = fcntl(fd, F_GETFD, 0)) != -1 &&
1081c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			    (i & FD_CLOEXEC))
1082c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				close(fd);
1083c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(2);
1084c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(1);
1085c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(0);
1086c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1087c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		exit(exstat & 0xFF);
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (shf)
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_close(shf);
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	reclaim();
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	e = e->oenv;
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* free the struct env - tricky due to the ALLOC_ITEM inside */
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cp = (void *)ep;
109777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	afree(cp + sizeof(ALLOC_ITEM), ATEMP);
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called after a fork to cleanup stuff left over from parents environment */
11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleanup_parents_env(void)
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep;
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd;
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Don't clean up temporary files - parent will probably need them.
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Also, can't easily reclaim memory since variables, etc. could be
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * anywhere.
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* close all file descriptors hiding in savefd */
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (ep = e; ep; ep = ep->oenv) {
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ep->savefd) {
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (fd = 0; fd < NUFILE; fd++)
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (ep->savefd[fd] > 0)
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					close(ep->savefd[fd]);
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(ep->savefd, &ep->area);
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ep->savefd = NULL;
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1122c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DEBUG_LEAKS
1123c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ep->type != E_NONE)
1124c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			ep->type = E_GONE;
1125c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1127c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef DEBUG_LEAKS
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	e->oenv = NULL;
1129c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called just before an execve cleanup stuff temporary files */
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleanup_proc_env(void)
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep;
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (ep = e; ep; ep = ep->oenv)
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		remove_temps(ep->temps);
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* remove temp files and free ATEMP Area */
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureclaim(void)
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1146c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct block *l;
1147c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1148c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while ((l = e->loc) && (!e->oenv || e->oenv->loc != l)) {
1149c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		e->loc = l->next;
1150c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		afreeall(&l->area);
1151c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1152c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	remove_temps(e->temps);
11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	e->temps = NULL;
115577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes
115677740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	/*
115777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	 * if the memory backing source is reclaimed, things
115877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	 * will end up badly when a function expecting it to
115977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	 * be valid is run; a NULL pointer is easily debugged
116077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	 */
116177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if (source && source->areap == &e->area)
116277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		source = NULL;
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afreeall(&e->area);
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruremove_temps(struct temp *tp)
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
116977740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	while (tp) {
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tp->pid == procpid)
1171c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			unlink(tp->tffn);
117277740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		tp = tp->next;
117377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	}
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
117603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
1177c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Initialise tty_fd. Used for tracking the size of the terminal,
1178c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * saving/resetting tty modes upon forground job completion, and
1179c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * for setting up the tty process group. Return values:
1180c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *	0 = got controlling tty
1181c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *	1 = got terminal but no controlling tty
1182c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *	2 = cannot find a terminal
1183c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *	3 = cannot dup fd
1184c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *	4 = cannot make fd close-on-exec
1185c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * An existing tty_fd is cached if no "better" one could be found,
1186c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * i.e. if tty_devtty was already set or the new would not set it.
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
1188c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserint
1189c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasertty_init_fd(void)
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1191c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int fd, rv, eno = 0;
1192c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	bool do_close = false, is_devtty = true;
11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1194c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (tty_devtty) {
1195c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* already got a tty which is /dev/tty */
1196c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (0);
11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _UWIN
120003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*XXX imake style */
120103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (isatty(3)) {
120203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* fd 3 on UWIN _is_ /dev/tty (or our controlling tty) */
1203c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		fd = 3;
1204c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto got_fd;
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1206c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
120777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if ((fd = open(T_devtty, O_RDWR, 0)) >= 0) {
1208c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		do_close = true;
1209c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto got_fd;
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1211c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	eno = errno;
12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tty_fd >= 0) {
1214c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* already got a non-devtty one */
1215c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		rv = 1;
1216c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto out;
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1218c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	is_devtty = false;
1219c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1220c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (isatty((fd = 0)) || isatty((fd = 2)))
1221c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto got_fd;
1222c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* cannot find one */
1223c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	rv = 2;
1224c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* assert: do_close == false */
1225c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	goto out;
1226c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1227c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser got_fd:
1228c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((rv = fcntl(fd, F_DUPFD, FDBASE)) < 0) {
1229c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		eno = errno;
1230c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		rv = 3;
1231c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto out;
1232c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1233c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (fcntl(rv, F_SETFD, FD_CLOEXEC) < 0) {
1234c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		eno = errno;
1235c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(rv);
1236c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		rv = 4;
1237c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto out;
1238c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1239c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	tty_fd = rv;
1240c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	tty_devtty = is_devtty;
1241c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	rv = eno = 0;
1242c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser out:
1243c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (do_close)
1244c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(fd);
1245c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	errno = eno;
1246c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (rv);
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* A shell error occurred (eg, syntax error, etc.) */
125003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
125103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_ERRORPREFIX	1
125203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_FILELINE	2
125303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_BUILTIN	4
125403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_INTERNAL	8
125503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
125603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void vwarningf(unsigned int, const char *, va_list)
125703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra    MKSH_A_FORMAT(__printf__, 2, 0);
125803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
125903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void
126003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravwarningf(unsigned int flags, const char *fmt, va_list ap)
126103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
1262c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (fmt) {
126303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (flags & VWARNINGF_INTERNAL)
126477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			shf_fprintf(shl_out, Tf_sD_, "internal error");
126503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (flags & VWARNINGF_ERRORPREFIX)
126603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			error_prefix(tobool(flags & VWARNINGF_FILELINE));
126703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((flags & VWARNINGF_BUILTIN) &&
126803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    /* not set when main() calls parse_args() */
126903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    builtin_argv0 && builtin_argv0 != kshname)
127077740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes			shf_fprintf(shl_out, Tf_sD_, builtin_argv0);
127103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_vfprintf(shl_out, fmt, ap);
127203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shf_putchar('\n', shl_out);
127303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
127403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_flush(shl_out);
127503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
127603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
127703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid
127803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraerrorfx(int rc, const char *fmt, ...)
127903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
128003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_list va;
128103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
128203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	exstat = rc;
128303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
128403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* debugging: note that stdout not valid */
128503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shl_stdout_ok = false;
128603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
128703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_start(va, fmt);
128803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
128903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_end(va);
129003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	unwind(LERROR);
129103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
129203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruerrorf(const char *fmt, ...)
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	exstat = 1;
129903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
130003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* debugging: note that stdout not valid */
130103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shl_stdout_ok = false;
130203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
130303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_start(va, fmt);
130403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
130503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_end(va);
13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(LERROR);
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* like errorf(), but no unwind is done */
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwarningf(bool fileline, const char *fmt, ...)
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
131603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_ERRORPREFIX | (fileline ? VWARNINGF_FILELINE : 0),
131703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    fmt, va);
13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
132103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
132203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Used by built-in utilities to prefix shell and utility name to message
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (also unwinds environments for special builtins).
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubi_errorf(const char *fmt, ...)
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
133003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* debugging: note that stdout not valid */
133103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shl_stdout_ok = false;
133203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	exstat = 1;
133403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
133503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_start(va, fmt);
133603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE |
133703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    VWARNINGF_BUILTIN, fmt, va);
133803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	va_end(va);
133903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1340a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	/* POSIX special builtins cause non-interactive shells to exit */
134150012061ca3ad8e8a7f88c72130a5e22d797897eElliott Hughes	if (builtin_spec) {
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		builtin_argv0 = NULL;
1343a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		/* may not want to use LERROR here */
13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unwind(LERROR);
13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called when something that shouldn't happen does */
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinternal_errorf(const char *fmt, ...)
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
135503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_INTERNAL, fmt, va);
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(LERROR);
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinternal_warningf(const char *fmt, ...)
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
136603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	vwarningf(VWARNINGF_INTERNAL, fmt, va);
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* used by error reporting functions to print "ksh: .kshrc[25]: " */
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruerror_prefix(bool fileline)
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Avoid foo: foo[2]: ... */
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!fileline || !source || !source->file ||
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    strcmp(source->file, kshname) != 0)
137777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		shf_fprintf(shl_out, Tf_sD_, kshname + (*kshname == '-'));
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fileline && source && source->file != NULL) {
1379b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		shf_fprintf(shl_out, "%s[%lu]: ", source->file,
1380b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		    (unsigned long)(source->errline ?
1381b27ce95e41e941ad22b3dc392d8328251d3a057eElliott Hughes		    source->errline : source->line));
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source->errline = 0;
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* printf to shl_out (stderr) with flush */
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushellf(const char *fmt, ...)
13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
139203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!initio_done)
139303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* shl_out may not be set up yet... */
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_vfprintf(shl_out, fmt, va);
13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_flush(shl_out);
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* printf to shl_stdout (stdout) */
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushprintf(const char *fmt, ...)
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_list va;
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!shl_stdout_ok)
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		internal_errorf("shl_stdout not valid");
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_start(va, fmt);
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_vfprintf(shl_stdout, fmt, va);
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	va_end(va);
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucan_seek(int fd)
14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct stat statb;
14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ?
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    SHF_UNBUF : 0);
14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1424c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DF
1425c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserint shl_dbg_fd;
1426c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define NSHF_IOB 4
1427c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#else
1428c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define NSHF_IOB 3
1429c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1430c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstruct shf shf_iob[NSHF_IOB];
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitio(void)
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1435c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DF
1436c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	const char *lfp;
1437c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1438c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
143903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* force buffer allocation */
144003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	shf_fdopen(1, SHF_WR, shl_stdout);
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_fdopen(2, SHF_WR, shl_out);
1442811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	shf_fdopen(2, SHF_WR, shl_xtrace);
1443c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DF
1444c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
144596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if ((lfp = getenv("HOME")) == NULL || !mksh_abspath(lfp))
1446a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			errorf("can't get home directory");
144777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		lfp = shf_smprintf(Tf_sSs, lfp, "mksh-dbg.txt");
1448c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1449c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1450c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((shl_dbg_fd = open(lfp, O_WRONLY | O_APPEND | O_CREAT, 0600)) < 0)
1451a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		errorf("can't open debug output file %s", lfp);
1452c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (shl_dbg_fd < FDBASE) {
1453c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		int nfd;
1454c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1455c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE);
1456c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		close(shl_dbg_fd);
1457c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if ((shl_dbg_fd = nfd) == -1)
1458a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes			errorf("can't dup debug output file");
1459c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1460c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	fcntl(shl_dbg_fd, F_SETFD, FD_CLOEXEC);
1461c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_fdopen(shl_dbg_fd, SHF_WR, shl_dbg);
1462c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	DF("=== open ===");
1463c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1464c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	initio_done = true;
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* A dup2() with error checking */
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_dup2(int ofd, int nfd, bool errok)
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF))
1474a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		errorf(Ttoo_many_files);
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef __ultrix
147703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*XXX imake style */
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rv >= 0)
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fcntl(nfd, F_SETFD, 0);
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
148603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Move fd from user space (0 <= fd < 10) to shell space (fd >= 10),
148703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * set close-on-exec flag. See FDBASE in sh.h, maybe 24 not 10 here.
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushort
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusavefd(int fd)
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int nfd = fd;
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fd < FDBASE && (nfd = fcntl(fd, F_DUPFD, FDBASE)) < 0 &&
149596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes	    (errno == EBADF || errno == EPERM))
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (nfd < 0 || nfd > SHRT_MAX)
1498a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes		errorf(Ttoo_many_files);
14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fcntl(nfd, F_SETFD, FD_CLOEXEC);
15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((short)nfd);
15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestfd(int fd, int ofd)
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fd == 2)
1507c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		shf_flush(&shf_iob[/* fd */ 2]);
150803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (ofd < 0)
150903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* original fd closed */
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(fd);
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (fd != ofd) {
151203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*XXX: what to do if this dup fails? */
151303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ksh_dup2(ofd, fd, true);
15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(ofd);
15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruopenpipe(int *pv)
15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int lpv[2];
15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (pipe(lpv) < 0)
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		errorf("can't create pipe - try again");
15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	pv[0] = savefd(lpv[0]);
15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (pv[0] != lpv[0])
15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(lpv[0]);
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	pv[1] = savefd(lpv[1]);
15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (pv[1] != lpv[1])
15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(lpv[1]);
1531a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#ifdef __OS2__
1532a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	setmode(pv[0], O_BINARY);
1533a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes	setmode(pv[1], O_BINARY);
1534a3c3f96fb829bbed2d01b359890bf8b729fa5c54Elliott Hughes#endif
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruclosepipe(int *pv)
15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	close(pv[0]);
15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	close(pv[1]);
15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
154403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
154503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucheck_fd(const char *name, int mode, const char **emsgp)
15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
155177740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	int fd, fl;
15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
155377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if (!name[0] || name[1])
155477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes		goto illegal_fd_name;
155577740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if (name[0] == 'p')
15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (coproc_getfd(mode, emsgp));
155777740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if (!ksh_isdigit(name[0])) {
155877740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes illegal_fd_name:
15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (emsgp)
15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*emsgp = "illegal file descriptor name";
15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
156377740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes
156477740fcd3dfcd2a78a8ad0ea0f0314dd6b23ecb6Elliott Hughes	if ((fl = fcntl((fd = ksh_numdig(name[0])), F_GETFL, 0)) < 0) {
15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (emsgp)
15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*emsgp = "bad file descriptor";
15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fl &= O_ACCMODE;
157003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
157103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * X_OK is a kludge to disable this check for dups (x<&1):
15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * historical shells never did this check (XXX don't know what
15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * POSIX has to say).
15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(mode & X_OK) && fl != O_RDWR && (
15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ((mode & R_OK) && fl != O_RDONLY) ||
15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ((mode & W_OK) && fl != O_WRONLY))) {
15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (emsgp)
15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*emsgp = (fl == O_WRONLY) ?
15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "fd not open for reading" :
15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "fd not open for writing";
15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (-1);
15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (fd);
15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called once from main */
15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_init(void)
15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	coproc.read = coproc.readw = coproc.write = -1;
15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	coproc.njobs = 0;
15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	coproc.id = 0;
15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called by c_read() when eof is read - close fd if it is the co-process fd */
15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_read_close(int fd)
15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (coproc.read >= 0 && fd == coproc.read) {
16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		coproc_readw_close(fd);
16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(coproc.read);
16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		coproc.read = -1;
16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
160703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
160803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by c_read() and by iosetup() to close the other side of the
16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * read pipe, so reads will actually terminate.
16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_readw_close(int fd)
16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) {
16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(coproc.readw);
16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		coproc.readw = -1;
16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
162003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
162103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by c_print when a write to a fd fails with EPIPE and by iosetup
16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * when co-process input is dup'd
16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_write_close(int fd)
16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (coproc.write >= 0 && fd == coproc.write) {
16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(coproc.write);
16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		coproc.write = -1;
16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
163303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
163403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called to check for existence of/value of the co-process file descriptor.
16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (Used by check_fd() and by c_read/c_print to deal with -p option).
16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_getfd(int mode, const char **emsgp)
16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd = (mode & R_OK) ? coproc.read : coproc.write;
16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fd >= 0)
16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (fd);
16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (emsgp)
16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*emsgp = "no coprocess";
16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (-1);
16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
164903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
165003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * called to close file descriptors related to the coprocess (if any)
16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Should be called with SIGCHLD blocked.
16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_cleanup(int reuse)
16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* This to allow co-processes to share output pipe */
16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!reuse || coproc.readw < 0 || coproc.read < 0) {
16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (coproc.read >= 0) {
16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			close(coproc.read);
16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			coproc.read = -1;
16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (coproc.readw >= 0) {
16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			close(coproc.readw);
16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			coproc.readw = -1;
16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (coproc.write >= 0) {
16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(coproc.write);
16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		coproc.write = -1;
16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct temp *
16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumaketemp(Area *ap, Temp_type type, struct temp **tlist)
16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
1676c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	char *cp;
167703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
1678811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	int i, j;
1679c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct temp *tp;
16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *dir;
1681c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct stat sb;
16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR;
1684c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* add "/shXXXXXX.tmp" plus NUL */
1685c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	len = strlen(dir);
1686c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14);
1687c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap);
1688c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->shf = NULL;
16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->pid = procpid;
1691c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	tp->type = type;
1692c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1693c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) {
1694c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		tp->tffn[0] = '\0';
1695c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto maketemp_out;
1696c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1697c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1698c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cp = (void *)tp;
1699c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cp += offsetof(struct temp, tffn[0]);
1700c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	memcpy(cp, dir, len);
1701c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cp += len;
1702c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	memcpy(cp, "/shXXXXXX.tmp", 14);
1703c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* point to the first of six Xes */
1704c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cp += 3;
1705c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1706c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* cyclically attempt to open a temporary file */
170796b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes	do {
170896b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		/* generate random part of filename */
170996b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		len = 0;
171096b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		do {
171196b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes			cp[len++] = digits_lc[rndget() % 36];
171296b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		} while (len < 6);
171396b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes
171496b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		/* check if this one works */
171596b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		if ((i = binopen3(tp->tffn, O_CREAT | O_EXCL | O_RDWR,
171696b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes		    0600)) < 0 && errno != EEXIST)
1717c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto maketemp_out;
171896b43632c2aa206ac1ec0eb70b34847d58d52633Elliott Hughes	} while (i < 0);
1719c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1720c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (type == TT_FUNSUB) {
1721c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* map us high and mark as close-on-exec */
1722811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		if ((j = savefd(i)) != i) {
1723c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			close(i);
1724811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser			i = j;
1725c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
1726811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser
1727811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		/* operation mode for the shf */
1728811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		j = SHF_RD;
1729811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	} else
1730811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser		j = SHF_WR;
17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1732c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* shf_fdopen cannot fail, so no fd leak */
1733811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser	tp->shf = shf_fdopen(i, j, NULL);
1734c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1735c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser maketemp_out:
17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->next = *tlist;
17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*tlist = tp;
17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (tp);
17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * We use a similar collision resolution algorithm as Python 2.5.4
17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * but with a slightly tweaked implementation written from scratch.
17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
174603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define	INIT_TBLSHIFT	3	/* initial table shift (2^3 = 8) */
17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PERTURB_SHIFT	5	/* see Python 2.5.4 Objects/dictobject.c */
17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
174903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void tgrow(struct table *);
17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int tnamecmp(const void *, const void *);
17515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
175303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condratgrow(struct table *tp)
17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
175503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t i, j, osize, mask, perturb;
17565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tblp, **pp;
17575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl **ntblp, **otblp = tp->tbls;
17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
175903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (tp->tshift > 29)
176003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		internal_errorf("hash table size limit reached");
176103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
176203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* calculate old size, new shift and new size */
176303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	osize = (size_t)1 << (tp->tshift++);
176403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = osize << 1;
176503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
176603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ntblp = alloc2(i, sizeof(struct tbl *), tp->areap);
176703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* multiplication cannot overflow: alloc2 checked that */
176803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	memset(ntblp, 0, i * sizeof(struct tbl *));
176903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1770c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* table can get very full when reaching its size limit */
1771c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	tp->nfree = (tp->tshift == 30) ? 0x3FFF0000UL :
1772c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    /* but otherwise, only 75% */
1773c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    ((i * 3) / 4);
17745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->tbls = ntblp;
17755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (otblp == NULL)
17765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
177703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
177803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	mask = i - 1;
17795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = 0; i < osize; i++)
17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((tblp = otblp[i]) != NULL) {
17815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((tblp->flag & DEFINED)) {
17825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* search for free hash table slot */
1783c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				j = perturb = tblp->ua.hval;
17845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto find_first_empty_slot;
17855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_next_empty_slot:
17865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				j = (j << 2) + j + perturb + 1;
17875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				perturb >>= PERTURB_SHIFT;
17885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_first_empty_slot:
178903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				pp = &ntblp[j & mask];
17905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*pp != NULL)
17915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					goto find_next_empty_slot;
17925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* found an empty hash table slot */
17935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*pp = tblp;
17945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				tp->nfree--;
17955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (!(tblp->flag & FINUSE)) {
17965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(tblp, tp->areap);
17975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
17985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
17995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(otblp, tp->areap);
18005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
180303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraktinit(Area *ap, struct table *tp, uint8_t initshift)
18045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->areap = ap;
18065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->tbls = NULL;
180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	tp->tshift = ((initshift > INIT_TBLSHIFT) ?
180803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    initshift : INIT_TBLSHIFT) - 1;
180903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	tgrow(tp);
18105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* table, name (key) to search for, hash(name), rv pointer to tbl ptr */
181303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct tbl *
18145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktscan(struct table *tp, const char *name, uint32_t h, struct tbl ***ppp)
18155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t j, perturb, mask;
18175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl **pp, *p;
18185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
181903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	mask = ((size_t)1 << (tp->tshift)) - 1;
18205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* search for hash table slot matching name */
1821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	j = perturb = h;
18225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	goto find_first_slot;
18235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_next_slot:
18245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	j = (j << 2) + j + perturb + 1;
18255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	perturb >>= PERTURB_SHIFT;
18265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_first_slot:
18275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	pp = &tp->tbls[j & mask];
18285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p = *pp) != NULL && (p->ua.hval != h || !(p->flag & DEFINED) ||
18295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    strcmp(p->name, name)))
18305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto find_next_slot;
18315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* p == NULL if not found, correct found entry otherwise */
18325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ppp)
18335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*ppp = pp;
18345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (p);
18355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* table, name (key) to enter, hash(n) */
18385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
18395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktenter(struct table *tp, const char *n, uint32_t h)
18405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl **pp, *p;
184203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len;
18435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Search:
18455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p = ktscan(tp, n, h, &pp)))
18465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (p);
18475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
184803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (tp->nfree == 0) {
18495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* too full */
185003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tgrow(tp);
18515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto Search;
18525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
18535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* create new tbl entry */
185503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	len = strlen(n);
185603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	checkoktoadd(len, offsetof(struct tbl, name[0]) + 1);
185703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap);
18585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->flag = 0;
18595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->type = 0;
18605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->areap = tp->areap;
18615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->ua.hval = h;
18625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->u2.field = 0;
18635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->u.array = NULL;
18645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	memcpy(p->name, n, len);
18655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* enter in tp->tbls */
18675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tp->nfree--;
18685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*pp = p;
18695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (p);
18705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
18735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktwalk(struct tstate *ts, struct table *tp)
18745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
187503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ts->left = (size_t)1 << (tp->tshift);
18765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ts->next = tp->tbls;
18775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl *
18805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktnext(struct tstate *ts)
18815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (--ts->left >= 0) {
18835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *p = *ts->next++;
18845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p != NULL && (p->flag & DEFINED))
18855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (p);
18865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
18875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (NULL);
18885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
18915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutnamecmp(const void *p1, const void *p2)
18925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
18935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct tbl *a = *((const struct tbl * const *)p1);
18945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct tbl *b = *((const struct tbl * const *)p2);
18955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (strcmp(a->name, b->name));
18975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
18985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
18995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl **
19005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktsort(struct table *tp)
19015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
19025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t i;
19035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl **p, **sp, **dp;
19045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
190503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
190603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * since the table is never entirely full, no need to reserve
190703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * additional space for the trailing NULL appended below
190803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 */
190903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = (size_t)1 << (tp->tshift);
191003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	p = alloc2(i, sizeof(struct tbl *), ATEMP);
19115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sp = tp->tbls;		/* source */
19125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	dp = p;			/* dest */
19135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (i--)
19145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((*dp = *sp++) != NULL && (((*dp)->flag & DEFINED) ||
19155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    ((*dp)->flag & ARRAY)))
19165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			dp++;
191703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	qsort(p, (i = dp - p), sizeof(struct tbl *), tnamecmp);
19185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p[i] = NULL;
19195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (p);
19205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
19215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
19225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH
19235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
19245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querux_sigwinch(int sig MKSH_A_UNUSED)
19255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
19265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* this runs inside interrupt context, with errno saved */
19275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
19285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	got_winch = 1;
19295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
19305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DF
1933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid
1934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten GlaserDF(const char *fmt, ...)
1935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
1936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	va_list args;
1937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct timeval tv;
1938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mirtime_mjd mjd;
1939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_lockfd(shl_dbg_fd);
1941c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_TIME(tv);
1942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	timet2mjd(&mjd, tv.tv_sec);
1943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_fprintf(shl_dbg, "[%02u:%02u:%02u (%u) %u.%06u] ",
1944c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    (unsigned)mjd.sec / 3600, ((unsigned)mjd.sec / 60) % 60,
1945c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    (unsigned)mjd.sec % 60, (unsigned)getpid(),
1946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
1947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	va_start(args, fmt);
1948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_vfprintf(shl_dbg, fmt, args);
1949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	va_end(args);
1950c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_putc('\n', shl_dbg);
1951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_flush(shl_dbg);
1952c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_unlkfd(shl_dbg_fd);
1953c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
1954c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1956c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid
1957c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserx_mkraw(int fd, mksh_ttyst *ocb, bool forread)
1958c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
1959c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_ttyst cb;
1960c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1961c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (ocb)
1962c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_tcget(fd, ocb);
1963c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	else
1964c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		ocb = &tty_state;
1965c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1966c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cb = *ocb;
1967c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (forread) {
1968737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		cb.c_iflag &= ~(ISTRIP);
1969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		cb.c_lflag &= ~(ICANON) | ECHO;
1970c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else {
1971737fdce098f804459a925438e48dd711c31bbc9eElliott Hughes		cb.c_iflag &= ~(INLCR | ICRNL | ISTRIP);
1972c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		cb.c_lflag &= ~(ISIG | ICANON | ECHO);
1973c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
1974c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(VLNEXT) && defined(_POSIX_VDISABLE)
1975c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* OSF/1 processes lnext when ~icanon */
1976c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cb.c_cc[VLNEXT] = _POSIX_VDISABLE;
1977c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1978c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* SunOS 4.1.x & OSF/1 processes discard(flush) when ~icanon */
1979c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(VDISCARD) && defined(_POSIX_VDISABLE)
1980c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cb.c_cc[VDISCARD] = _POSIX_VDISABLE;
1981c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
1982c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cb.c_cc[VTIME] = 0;
1983c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	cb.c_cc[VMIN] = 1;
1984c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
1985c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_tcset(fd, &cb);
1986c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
1987