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