103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* $OpenBSD: main.c,v 1.47 2011/09/07 11:33:25 otto Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */ 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */ 45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: table.c,v 1.13 2009/01/17 22:06:44 millert Exp $ */ 55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define EXTERN 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_LANGINFO_CODESET 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <langinfo.h> 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SETLOCALE_CTYPE 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <locale.h> 345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/main.c,v 1.200 2011/10/07 19:51:28 tg Exp $"); 375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruextern char **environ; 395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSHRC_PATH 415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MKSHRC_PATH "~/.mkshrc" 425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_DEFAULT_TMPDIR 455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MKSH_DEFAULT_TMPDIR "/tmp" 465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid chvt_reinit(void); 495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void reclaim(void); 505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void remove_temps(struct temp *); 5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic mksh_uari_t rndsetup(void); 525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH 535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void x_sigwinch(int); 545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char initifs[] = "IFS= \t\n"; 575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char initsubs[] = 595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "${PS2=> } ${PS3=#? } ${PS4=+ } ${SECONDS=0} ${TMOUT=0}"; 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *initcoms[] = { 6203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Ttypeset, "-r", initvsn, NULL, 6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Ttypeset, "-x", "HOME", "PATH", "RANDOM", "SHELL", NULL, 6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Ttypeset, "-i10", "SECONDS", "TMOUT", NULL, 6503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Talias, 665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "integer=typeset -i", 6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Tlocal_typeset, 6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not "alias -t --": hash -r needs to work */ 6903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "hash=alias -t", 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "type=whence -v", 7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if !defined(ANDROID) && !defined(MKSH_UNEMPLOYED) 7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not in Android for political reasons */ 7303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not in ARGE mksh due to no job control */ 7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "stop=kill -STOP", 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "suspend=kill -STOP $$", 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "autoload=typeset -fu", 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "functions=typeset -f", 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "history=fc -l", 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "nameref=typeset -n", 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "nohup=nohup ", 8203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Tr_fc_e_dash, 835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "source=PATH=$PATH:. command .", 845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "login=exec login", 855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, 865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this is what AT&T ksh seems to track, with the addition of emacs */ 8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Talias, "-tU", 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls", 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL, 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *restr_com[] = { 9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Ttypeset, "-r", "PATH", "ENV", "SHELL", NULL 9503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}; 9603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int initio_done; 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* top-level parsing and execution environment */ 10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic struct env env; 10103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct env *e = &env; 10203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic mksh_uari_t 10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrarndsetup(void) 10503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 10603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra register uint32_t h; 10703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct { 10803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ALLOC_ITEM alloc_INT; 10903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra void *dataptr, *stkptr, *mallocptr; 11003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigjmp_buf jbuf; 11103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct timeval tv; 11203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct timezone tz; 11303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } *bufptr; 11403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 11503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 11603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM); 11703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef DEBUG 11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* clear the allocated space, for valgrind */ 11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memset(cp, 0, sizeof(*bufptr) - ALLOC_SIZE); 12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 12103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undo what alloc() did to the malloc result address */ 12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bufptr = (void *)(cp - ALLOC_SIZE); 12303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* PIE or something similar provides us with deltas here */ 12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bufptr->dataptr = &rndsetupstate; 12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ASLR in at least Windows, Linux, some BSDs */ 12603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bufptr->stkptr = &bufptr; 12703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* randomised malloc in BSD (and possibly others) */ 12803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bufptr->mallocptr = bufptr; 12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* glibc pointer guard */ 13003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigsetjmp(bufptr->jbuf, 1); 13103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* introduce variation */ 13203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra gettimeofday(&bufptr->tv, &bufptr->tz); 13303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 13403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZATInit(h); 13503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* variation through pid, ppid, and the works */ 13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate)); 13703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* some variation, some possibly entropy, depending on OE */ 13803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZATUpdateMem(h, bufptr, sizeof(*bufptr)); 13903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZAATFinish(h); 14003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 14103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(cp, APERM); 14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return ((mksh_uari_t)h); 14303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchvt_reinit(void) 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshpid = procpid = getpid(); 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksheuid = geteuid(); 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshpgrp = getpgrp(); 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshppid = getppid(); 1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char *empty_argv[] = { 15503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "mksh", NULL 15603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}; 15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 15803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint 15903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condramain(int argc, const char *argv[]) 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int argi, i; 16203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Source *s = NULL; 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct block *l; 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char restricted, errexit, utf_flag; 16503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 16603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *ccp, **wp; 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *vp; 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat s_stdin; 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(_PATH_DEFPATH) && defined(_CS_PATH) 17003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ssize_t k; 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do things like getpgrp() et al. */ 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chvt_reinit(); 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* make sure argv[] is sane */ 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*argv) { 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv = empty_argv; 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argc = 1; 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshname = argv[0]; 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* initialise permanent Area */ 18403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ainit(&aperm); 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* set up base environment */ 18703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra env.type = E_NONE; 18803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ainit(&env.area); 18903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* set up global l->vars and l->funs */ 19003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra newblock(); 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Do this first so output routines (eg, errorf, shellf) can work */ 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru initio(); 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* determine the basename (without '-' or path) of the executable */ 19603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = kshname; 19703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto begin_parse_kshname; 19803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((i = ccp[argi++])) { 19903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == '/') { 20003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp += argi; 20103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra begin_parse_kshname: 20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra argi = 0; 20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*ccp == '-') 20403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ccp; 20503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 20603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 20703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ccp) 20803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = empty_argv[0]; 20903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 21003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* define built-in commands and see if we were called as one */ 21103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktinit(APERM, &builtins, 21203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* currently 50 builtins -> 80% of 64 (2^6) */ 21303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 6); 21403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra for (i = 0; mkshbuiltins[i].name != NULL; i++) 21503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!strcmp(ccp, builtin(mkshbuiltins[i].name, 21603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra mkshbuiltins[i].func))) 21703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Flag(FAS_BUILTIN) = 1; 21803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 21903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FAS_BUILTIN)) { 22003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check for -T option early */ 22103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra argi = parse_args(argv, OF_FIRSTTIME, NULL); 22203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (argi < 0) 22303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (1); 22403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 22503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef MKSH_BINSHREDUCED 22603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* set FSH if we're called as -sh or /bin/sh or so */ 22703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!strcmp(ccp, "sh")) 22803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra change_flag(FSH, OF_FIRSTTIME, 1); 22903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 23003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru initvar(); 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru initctypes(); 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru inittraps(); 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc_init(); 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* set up variable and command dictionaries */ 24103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktinit(APERM, &taliases, 0); 24203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktinit(APERM, &aliases, 0); 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NOPWNAM 24403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktinit(APERM, &homedirs, 0); 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* define shell keywords */ 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru initkeywords(); 2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru init_histvec(); 2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _PATH_DEFPATH 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru def_path = _PATH_DEFPATH; 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _CS_PATH 25603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((k = confstr(_CS_PATH, NULL, 0)) > 0 && 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1) 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru def_path = cp; 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this is uniform across all OSes unless it 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * breaks somewhere; don't try to optimise, 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * e.g. add stuff for Interix or remove /usr 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for HURD, because e.g. Debian GNU/HURD is 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * "keeping a regular /usr"; this is supposed 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to be a sane 'basic' default PATH 2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru def_path = "/bin:/usr/bin:/sbin:/usr/sbin"; 2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 27203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 27303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set PATH to def_path (will set the path global variable). 2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (import of environment below will probably change this setting). 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = global("PATH"); 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* setstr can't fail here */ 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(vp, def_path, KSH_RETURN_ERROR); 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 28003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 28103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Turn on nohup by default for now - will change to off 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * by default once people are aware of its existence 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (AT&T ksh does not have a nohup option - it always sends 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the hup). 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FNOHUP) = 1; 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 28803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 28903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Turn on brace expansion by default. AT&T kshs that have 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * alternation always have it on. 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FBRACEEXPAND) = 1; 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 29403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 29503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set edit mode to emacs by default, may be overridden 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * by the environment or the user. Also, we want tab completion 29703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * on in vi by default. 29803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag(FEMACS, OF_SPECIAL, 1); 3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FVITABCOMPLETE) = 1; 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* import environment */ 3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (environ != NULL) 3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (wp = (const char **)environ; *wp != NULL; wp++) 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru typeset(*wp, IMPORT | EXPORT, 0, 0, 0); 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 30903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* for security */ 31003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra typeset(initifs, 0, 0, 0, 0); 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* assign default shell variable values */ 3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru substitute(initsubs, 0); 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Figure out the current working directory and set $PWD */ 31603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp = global("PWD"); 31703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = str_val(vp); 31803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Try to use existing $PWD if it is valid */ 31903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra set_current_wd((cp[0] == '/' && test_eval(NULL, TO_FILEQ, cp, ".", 32003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra true)) ? cp : NULL); 32103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (current_wd[0]) 32203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_path(current_wd); 32303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Only set pwd if we know where we are or if it had a bogus value */ 32403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (current_wd[0] || *cp) 32503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* setstr can't fail here */ 32603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(vp, current_wd, KSH_RETURN_ERROR); 3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (wp = initcoms; *wp != NULL; wp++) { 3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shcomexec(wp); 3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*wp != NULL) 3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp++; 3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 33303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n(global("COLUMNS"), 0); 33403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n(global("LINES"), 0); 33503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n(global("OPTIND"), 1); 33603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 33703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshuid = getuid(); 33803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshgid = getgid(); 33903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshegid = getegid(); 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru safe_prompt = ksheuid ? "$ " : "# "; 3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp = global("PS1"); 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Set PS1 if unset or we are root and prompt doesn't contain a # */ 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(vp->flag & ISSET) || 3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!ksheuid && !strchr(str_val(vp), '#'))) 3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* setstr can't fail here */ 3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(vp, safe_prompt, KSH_RETURN_ERROR); 34803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp); 3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= INT_U; 35003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("PPID")), (mksh_uari_t)kshppid); 3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= INT_U; 35203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid); 3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= INT_U; 35403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid); 3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru vp->flag |= INT_U; 35603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid); 35703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp->flag |= INT_U; 35803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid); 35903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp->flag |= INT_U; 36003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp = global("RANDOM")), rndsetup()); 36103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp->flag |= INT_U; 36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setint_n((vp_pipest = global("PIPESTATUS")), 0); 3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Set this before parsing arguments */ 36503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid; 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this to note if monitor is set on command line (see below) */ 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FMONITOR) = 127; 3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this to note if utf-8 mode is set on command line (see below) */ 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru UTFMODE = 2; 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 37403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!Flag(FAS_BUILTIN)) { 37503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra argi = parse_args(argv, OF_CMDLINE, NULL); 37603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (argi < 0) 37703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (1); 37803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 37903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 38003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef DEBUG 38103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* test wraparound of arithmetic types */ 38203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { 38303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile long xl; 38403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile unsigned long xul; 38503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile int xi; 38603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile unsigned int xui; 38703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile mksh_ari_t xa; 38803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile mksh_uari_t xua, xua2; 38903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile uint8_t xc; 39003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 39103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xa = 2147483647; 39203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xua = 2147483647; 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++xa; 39403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++xua; 39503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xua2 = xa; 39603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xl = xa; 39703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xul = xua; 39803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xa = 0; 39903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xua = 0; 40003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra --xa; 40103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra --xua; 40203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xi = xa; 40303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xui = xua; 40403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xa = -1; 40503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xua = xa; 40603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++xa; 40703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++xua; 40803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xc = 0; 40903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra --xc; 41003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((xua2 != 2147483648UL) || 41103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (xl != -2147483648L) || (xul != 2147483648UL) || 41203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (xi != -1) || (xui != 4294967295U) || 41303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (xa != 0) || (xua != 0) || (xc != 255)) 41403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("integer wraparound test failed"); 41503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 41603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* process this later only, default to off (hysterical raisins) */ 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru utf_flag = UTFMODE; 4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru UTFMODE = 0; 4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 42203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FAS_BUILTIN)) { 42303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* auto-detect from environment variables, always */ 42403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra utf_flag = 3; 42503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (Flag(FCOMMAND)) { 4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SSTRING, ATEMP); 4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(s->start = s->str = argv[argi++])) 42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s %s", "-c", "requires an argument"); 4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT 4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */ 4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--")) 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++argi; 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[argi]) 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshname = argv[argi++]; 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (argi < argc && !Flag(FSTDIN)) { 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SFILE, ATEMP); 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->file = argv[argi++]; 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->u.shf = shf_open(s->file, O_RDONLY, 0, 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SHF_MAPHI | SHF_CLEXEC); 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s->u.shf == NULL) { 44203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = false; 4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(true, "%s: %s", s->file, strerror(errno)); 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* mandated by SUSv4 */ 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exstat = 127; 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LERROR); 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshname = s->file; 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FSTDIN) = 1; 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SSTDIN, ATEMP); 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->file = "<stdin>"; 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL); 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (isatty(0) && isatty(2)) { 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FTALKING) = Flag(FTALKING_I) = 1; 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* The following only if isatty(0) */ 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->flags |= SF_TTY; 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->u.shf->flags |= SHF_INTERRUPT; 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->file = NULL; 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this bizarreness is mandated by POSIX */ 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FTALKING)) 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru reset_nonblock(0); 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* initialise job control */ 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_init(); 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Do this after j_init(), as tty_fd is not initialised until then */ 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FTALKING)) { 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (utf_flag == 2) { 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_ASSUME_UTF8 47503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* auto-detect from locale or environment */ 47603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra utf_flag = 4; 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif MKSH_ASSUME_UTF8 47803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra utf_flag = 1; 4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 48003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* always disable UTF-8 (for interactive) */ 48103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra utf_flag = 0; 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru x_init(); 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGWINCH].flags |= TF_SHELL_USES; 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGWINCH], x_sigwinch, 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l = e->loc; 49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FAS_BUILTIN)) { 49503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argc = argc; 49603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argv = argv; 49703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argv[0] = ccp; 49803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 49903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argc = argc - argi; 50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argv = &argv[argi - 1]; 50103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra l->argv[0] = kshname; 50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra getopts_reset(1); 50303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 50403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 50503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* divine the initial state of the utf8-mode Flag */ 50603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define isuc(x) (((x) != NULL) && \ 50703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (stristr((x), "UTF-8") || stristr((x), "utf8"))) 50803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = null; 50903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (utf_flag) { 51003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 51103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* auto-detect from locale or environment */ 51203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 4: 51303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SETLOCALE_CTYPE 51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = setlocale(LC_CTYPE, ""); 51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_LANGINFO_CODESET 51603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!isuc(ccp)) 51703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = nl_langinfo(CODESET); 51803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 51903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!isuc(ccp)) 52003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = null; 52103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* FALLTHROUGH */ 52203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 52303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 52403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* auto-detect from environment */ 52503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 3: 52603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* these were imported from environ earlier */ 52703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ccp == null) 52803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = str_val(global("LC_ALL")); 52903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ccp == null) 53003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = str_val(global("LC_CTYPE")); 53103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ccp == null) 53203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = str_val(global("LANG")); 53303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra UTFMODE = isuc(ccp); 53403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 53503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 53603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not set on command line, not FTALKING */ 53703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 2: 53803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* unknown values */ 53903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra default: 54003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra utf_flag = 0; 54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* FALLTHROUGH */ 54203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 54303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* known values */ 54403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 1: 54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0: 54603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra UTFMODE = utf_flag; 54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 54803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 54903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef isuc 5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Disable during .profile/ENV reading */ 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restricted = Flag(FRESTRICTED); 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FRESTRICTED) = 0; 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errexit = Flag(FERREXIT); 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FERREXIT) = 0; 5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 55703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 55803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Do this before profile/$ENV so that if it causes problems in them, 5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * user will know why things broke. 5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!current_wd[0] && Flag(FTALKING)) 56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "can't determine current directory"); 5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FLOGIN)) { 56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra include(MKSH_SYSTEM_PROFILE, 0, NULL, 1); 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!Flag(FPRIVILEGED)) 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru include(substitute("$HOME/.profile", 0), 0, 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, 1); 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FPRIVILEGED)) 57103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra include(MKSH_SUID_PROFILE, 0, NULL, 1); 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (Flag(FTALKING)) { 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *env_file; 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* include $ENV */ 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru env_file = substitute(substitute("${ENV:-" MKSHRC_PATH "}", 0), 5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru DOTILDE); 5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*env_file != '\0') 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru include(env_file, 0, NULL, 1); 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (restricted) { 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shcomexec(restr_com); 5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* After typeset command... */ 5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FRESTRICTED) = 1; 5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FERREXIT) = errexit; 5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 58903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FTALKING)) 5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_init(s); 59103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 59203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* set after ENV */ 59303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Flag(FTRACKALL) = 1; 5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 59503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra alarm_init(); 5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FAS_BUILTIN)) 59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (shcomexec(l->argv)); 5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* doesn't return */ 60103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shell(s, true); 60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* NOTREACHED */ 60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (0); 6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinclude(const char *name, int argc, const char **argv, int intr_ok) 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *volatile s = NULL; 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct shf *shf; 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char **volatile old_argv; 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int old_argc; 6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf == NULL) 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv) { 6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_argv = e->loc->argv; 6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_argc = e->loc->argc; 6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_argv = NULL; 6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_argc = 0; 6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newenv(E_INCL); 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = sigsetjmp(e->jbuf, 0); 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i) { 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(s ? s->u.shf : NULL); 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (old_argv) { 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argv = old_argv; 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argc = old_argc; 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (i) { 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LRETURN: 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LERROR: 63703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* see below */ 63803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (exstat & 0xFF); 6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LINTR: 64003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 64103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * intr_ok is set if we are including .profile or $ENV. 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * If user ^Cs out, we don't want to kill the shell... 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (intr_ok && (exstat - 128) != SIGTERM) 6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LEXIT: 6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LLEAVE: 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LSHELL: 6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 65303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("%s %d", "include", i); 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv) { 6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argv = argv; 6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argc = argc; 6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SFILE, ATEMP); 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->u.shf = shf; 6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(s->file, name, ATEMP); 6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = shell(s, false); 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(s->u.shf); 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (old_argv) { 6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argv = old_argv; 6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argc = old_argc; 6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 67003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* & 0xff to ensure value not -1 */ 67103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (i & 0xFF); 6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* spawn a command into a shell optionally keeping track of the line number */ 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucommand(const char *comm, int line) 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *s; 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = pushs(SSTRING, ATEMP); 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = comm; 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->line = line; 6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (shell(s, false)); 6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * run the commands from the input source, returning status. 6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushell(Source * volatile s, volatile int toplevel) 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct op *t; 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int wastty = s->flags & SF_TTY; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int attempts = 13; 6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int interactive = Flag(FTALKING) && toplevel; 69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile bool sfirst = true; 6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *volatile old_source = source; 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newenv(E_PARSE); 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (interactive) 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru really_exit = 0; 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = sigsetjmp(e->jbuf, 0); 7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i) { 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (i) { 70603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case LINTR: 70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we get here if SIGINT not caught or ignored */ 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LERROR: 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LSHELL: 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (interactive) { 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == LINTR) 7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shellf("\n"); 71303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 71403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Reset any eof that was read as part of a 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * multiline command. 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FIGNOREEOF) && s->type == SEOF && 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wastty) 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->type = SSTDIN; 72003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 72103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Used by exit command to get back to 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * top level shell. Kind of strange since 7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * interactive is set if we are reading from 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a tty, but to have stopped jobs, one only 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * needs FMONITOR set (not FTALKING/SF_TTY)... 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* toss any input we have so far */ 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->start = s->str = null; 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LEXIT: 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LLEAVE: 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LRETURN: 7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = old_source; 7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 73703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep on going */ 73803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unwind(i); 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = old_source; 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 74303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("%s %d", "shell", i); 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 74703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (trap) 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru runtraps(0); 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s->next == NULL) { 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FVERBOSE)) 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->flags |= SF_ECHO; 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->flags &= ~SF_ECHO; 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (interactive) { 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_notify(); 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru set_prompt(PS1, s); 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 76103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t = compile(s, sfirst); 76203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sfirst = false; 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t != NULL && t->type == TEOF) { 7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { 76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shellf("Use 'exit' to leave mksh\n"); 7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->type = SSTDIN; 7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (wastty && !really_exit && 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_stopped_running()) { 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru really_exit = 1; 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s->type = SSTDIN; 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 77203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 77303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * this for POSIX which says EXIT traps 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * shall be taken in the environment 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * immediately after the last command 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * executed. 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (toplevel) 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LEXIT); 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exstat = execute(t, 0, NULL); 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t != NULL && t->type != TEOF && interactive && really_exit) 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru really_exit = 0; 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru reclaim(); 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = old_source; 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (exstat); 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* return to closest error handler or shell(), exit if none found */ 7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunwind(int i) 7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ordering for EXIT vs ERR is a bit odd (this is what AT&T ksh does) */ 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) && 80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[ksh_SIGEXIT].trap)) { 80303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++trap_nested; 80403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(&sigtraps[ksh_SIGEXIT], trap_nested == 1); 80503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra --trap_nested; 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = LLEAVE; 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) { 80803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++trap_nested; 80903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(&sigtraps[ksh_SIGERR], trap_nested == 1); 81003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra --trap_nested; 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = LLEAVE; 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 81303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (e->type) { 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_PARSE: 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_FUNC: 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_INCL: 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_LOOP: 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_ERRH: 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru siglongjmp(e->jbuf, i); 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case E_NONE: 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == LINTR) 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->flags |= EF_FAKE_SIGDIE; 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querunewenv(int type) 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct env *ep; 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp; 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * struct env includes ALLOC_ITEM for alignment constraints 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * so first get the actually used memory, then assign it 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp = alloc(sizeof(struct env) - ALLOC_SIZE, ATEMP); 84303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undo what alloc() did to the malloc result address */ 84403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ep = (void *)(cp - ALLOC_SIZE); 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* initialise public members of struct env (not the ALLOC_ITEM) */ 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ainit(&ep->area); 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->oenv = e; 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->loc = e->loc; 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->savefd = NULL; 8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->temps = NULL; 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->type = type; 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->flags = 0; 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* jump buffer is invalid because flags == 0 */ 8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e = ep; 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruquitenv(struct shf *shf) 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct env *ep = e; 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp; 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->oenv && ep->oenv->loc != ep->loc) 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru popblock(); 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->savefd != NULL) { 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (fd = 0; fd < NUFILE; fd++) 8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* if ep->savefd[fd] < 0, means fd was closed */ 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->savefd[fd]) 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restfd(fd, ep->savefd[fd]); 87103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ep->savefd[2]) 87203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Clear any write errors */ 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_reopen(2, SHF_WR, shl_out); 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 87503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 87603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Bottom of the stack. 8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Either main shell is exiting or cleanup_parents_env() was called. 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->oenv == NULL) { 88003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ep->type == E_NONE) { 88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Main shell exiting? */ 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FTALKING)) 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_finish(); 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_exit(); 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->flags & EF_FAKE_SIGDIE) { 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int sig = exstat - 128; 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 89003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 89103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ham up our death a bit (AT&T ksh 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * only seems to do this for SIGTERM) 8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Don't do it for SIGQUIT, since we'd 8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * dump a core.. 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((sig == SIGINT || sig == SIGTERM) && 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (kshpgrp == kshpid)) { 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[sig], SIG_DFL, 8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_CURR | SS_FORCE); 9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kill(0, sig); 9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf) 9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_close(shf); 9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru reclaim(); 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exit(exstat); 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf) 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_close(shf); 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru reclaim(); 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e = e->oenv; 9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* free the struct env - tricky due to the ALLOC_ITEM inside */ 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp = (void *)ep; 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(cp + ALLOC_SIZE, ATEMP); 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called after a fork to cleanup stuff left over from parents environment */ 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleanup_parents_env(void) 9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct env *ep; 9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru mkssert(e != NULL); 9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Don't clean up temporary files - parent will probably need them. 9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Also, can't easily reclaim memory since variables, etc. could be 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * anywhere. 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* close all file descriptors hiding in savefd */ 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (ep = e; ep; ep = ep->oenv) { 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->savefd) { 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (fd = 0; fd < NUFILE; fd++) 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ep->savefd[fd] > 0) 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(ep->savefd[fd]); 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(ep->savefd, &ep->area); 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ep->savefd = NULL; 9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->oenv = NULL; 9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called just before an execve cleanup stuff temporary files */ 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleanup_proc_env(void) 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct env *ep; 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (ep = e; ep; ep = ep->oenv) 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru remove_temps(ep->temps); 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* remove temp files and free ATEMP Area */ 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureclaim(void) 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru remove_temps(e->temps); 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->temps = NULL; 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afreeall(&e->area); 9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruremove_temps(struct temp *tp) 9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; tp != NULL; tp = tp->next) 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->pid == procpid) 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unlink(tp->name); 9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 97503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 97603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Initialise tty_fd. Used for saving/reseting tty modes upon 9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * foreground job completion and for setting up tty process group. 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutty_init(bool init_ttystate, bool need_tty) 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool do_close = true; 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int tfd; 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tty_fd >= 0) { 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(tty_fd); 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tty_fd = -1; 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 98903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tty_devtty = true; 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef _UWIN 99203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX imake style */ 99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (isatty(3)) { 99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* fd 3 on UWIN _is_ /dev/tty (or our controlling tty) */ 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tfd = 3; 99603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra do_close = false; 99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 99903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((tfd = open("/dev/tty", O_RDWR, 0)) < 0) { 100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tty_devtty = false; 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (need_tty) 100203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s: %s", 100303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "No controlling tty", "open", "/dev/tty", 10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strerror(errno)); 10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tfd < 0) { 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_close = false; 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (isatty(0)) 10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tfd = 0; 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (isatty(2)) 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tfd = 2; 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (need_tty) 101403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "can't find tty fd"); 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((tty_fd = fcntl(tfd, F_DUPFD, FDBASE)) < 0) { 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (need_tty) 102003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s: %s", "j_ttyinit", 102103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "dup of tty fd", "failed", strerror(errno)); 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (fcntl(tty_fd, F_SETFD, FD_CLOEXEC) < 0) { 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (need_tty) 102403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s: %s", "j_ttyinit", 102503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "can't set close-on-exec flag", strerror(errno)); 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(tty_fd); 10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tty_fd = -1; 10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (init_ttystate) 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tcgetattr(tty_fd, &tty_state); 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_close) 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(tfd); 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutty_close(void) 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tty_fd >= 0) { 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(tty_fd); 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tty_fd = -1; 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* A shell error occurred (eg, syntax error, etc.) */ 104403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 104503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_ERRORPREFIX 1 104603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_FILELINE 2 104703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_BUILTIN 4 104803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define VWARNINGF_INTERNAL 8 104903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 105003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void vwarningf(unsigned int, const char *, va_list) 105103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra MKSH_A_FORMAT(__printf__, 2, 0); 105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 105303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void 105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravwarningf(unsigned int flags, const char *fmt, va_list ap) 105503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 105603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*fmt != 1) { 105703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (flags & VWARNINGF_INTERNAL) 105803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_fprintf(shl_out, "internal error: "); 105903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (flags & VWARNINGF_ERRORPREFIX) 106003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra error_prefix(tobool(flags & VWARNINGF_FILELINE)); 106103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((flags & VWARNINGF_BUILTIN) && 106203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not set when main() calls parse_args() */ 106303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra builtin_argv0 && builtin_argv0 != kshname) 106403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_fprintf(shl_out, "%s: ", builtin_argv0); 106503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_vfprintf(shl_out, fmt, ap); 106603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_putchar('\n', shl_out); 106703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_flush(shl_out); 106903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 107003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 107103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condravoid 107203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraerrorfx(int rc, const char *fmt, ...) 107303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 107403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_list va; 107503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra exstat = rc; 107703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 107803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* debugging: note that stdout not valid */ 107903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = false; 108003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 108103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_start(va, fmt); 108203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va); 108303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_end(va); 108403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unwind(LERROR); 108503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 108603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruerrorf(const char *fmt, ...) 10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exstat = 1; 109303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 109403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* debugging: note that stdout not valid */ 109503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = false; 109603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 109703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_start(va, fmt); 109803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va); 109903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_end(va); 11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LERROR); 11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* like errorf(), but no unwind is done */ 11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwarningf(bool fileline, const char *fmt, ...) 11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_start(va, fmt); 111003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_ERRORPREFIX | (fileline ? VWARNINGF_FILELINE : 0), 111103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fmt, va); 11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_end(va); 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 111503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 111603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Used by built-in utilities to prefix shell and utility name to message 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (also unwinds environments for special builtins). 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubi_errorf(const char *fmt, ...) 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 112403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* debugging: note that stdout not valid */ 112503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = false; 112603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exstat = 1; 112803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 112903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_start(va, fmt); 113003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE | 113103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra VWARNINGF_BUILTIN, fmt, va); 113203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra va_end(va); 113303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 113403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 113503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * POSIX special builtins and ksh special builtins cause 11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-interactive shells to exit. 11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * XXX odd use of KEEPASN; also may not want LERROR here 11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (builtin_flag & SPEC_BI) { 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru builtin_argv0 = NULL; 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LERROR); 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called when something that shouldn't happen does */ 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinternal_errorf(const char *fmt, ...) 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_start(va, fmt); 115203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_INTERNAL, fmt, va); 11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_end(va); 11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LERROR); 11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinternal_warningf(const char *fmt, ...) 11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_start(va, fmt); 116303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vwarningf(VWARNINGF_INTERNAL, fmt, va); 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_end(va); 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* used by error reporting functions to print "ksh: .kshrc[25]: " */ 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruerror_prefix(bool fileline) 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Avoid foo: foo[2]: ... */ 11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!fileline || !source || !source->file || 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strcmp(source->file, kshname) != 0) 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-')); 11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fileline && source && source->file != NULL) { 11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shl_out, "%s[%d]: ", source->file, 11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source->errline > 0 ? source->errline : source->line); 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source->errline = 0; 11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* printf to shl_out (stderr) with flush */ 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushellf(const char *fmt, ...) 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 118803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!initio_done) 118903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shl_out may not be set up yet... */ 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_start(va, fmt); 11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_vfprintf(shl_out, fmt, va); 11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_end(va); 11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_flush(shl_out); 11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* printf to shl_stdout (stdout) */ 11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushprintf(const char *fmt, ...) 12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_list va; 12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!shl_stdout_ok) 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("shl_stdout not valid"); 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_start(va, fmt); 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_vfprintf(shl_stdout, fmt, va); 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru va_end(va); 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */ 12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucan_seek(int fd) 12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat statb; 12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ? 12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SHF_UNBUF : 0); 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct shf shf_iob[3]; 12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitio(void) 12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 122503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* force buffer allocation */ 122603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_fdopen(1, SHF_WR, shl_stdout); 12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fdopen(2, SHF_WR, shl_out); 122803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* force buffer allocation */ 122903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_fdopen(2, SHF_WR, shl_spare); 12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru initio_done = 1; 12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* A dup2() with error checking */ 12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_dup2(int ofd, int nfd, bool errok) 12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int rv; 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF)) 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("too many files open in shell"); 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef __ultrix 124303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX imake style */ 12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (rv >= 0) 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fcntl(nfd, F_SETFD, 0); 12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 125203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Move fd from user space (0 <= fd < 10) to shell space (fd >= 10), 125303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * set close-on-exec flag. See FDBASE in sh.h, maybe 24 not 10 here. 12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushort 12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusavefd(int fd) 12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nfd = fd; 12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fd < FDBASE && (nfd = fcntl(fd, F_DUPFD, FDBASE)) < 0 && 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errno == EBADF) 12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nfd < 0 || nfd > SHRT_MAX) 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("too many files open in shell"); 12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fcntl(nfd, F_SETFD, FD_CLOEXEC); 12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((short)nfd); 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestfd(int fd, int ofd) 12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fd == 2) 12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_flush(&shf_iob[fd]); 127403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ofd < 0) 127503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* original fd closed */ 12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (fd != ofd) { 127803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX: what to do if this dup fails? */ 127903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ksh_dup2(ofd, fd, true); 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(ofd); 12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruopenpipe(int *pv) 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int lpv[2]; 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pipe(lpv) < 0) 12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("can't create pipe - try again"); 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pv[0] = savefd(lpv[0]); 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pv[0] != lpv[0]) 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(lpv[0]); 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pv[1] = savefd(lpv[1]); 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pv[1] != lpv[1]) 12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(lpv[1]); 12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruclosepipe(int *pv) 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(pv[0]); 13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(pv[1]); 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 130603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 130703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn 13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor. 13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucheck_fd(const char *name, int mode, const char **emsgp) 13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd, fl; 13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (name[0] == 'p' && !name[1]) 13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (coproc_getfd(mode, emsgp)); 13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (fd = 0; ksh_isdigit(*name); ++name) 13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fd = (fd * 10) + *name - '0'; 13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*name || fd >= FDBASE) { 13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (emsgp) 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *emsgp = "illegal file descriptor name"; 13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fl = fcntl(fd, F_GETFL, 0)) < 0) { 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (emsgp) 13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *emsgp = "bad file descriptor"; 13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fl &= O_ACCMODE; 133003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 133103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * X_OK is a kludge to disable this check for dups (x<&1): 13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * historical shells never did this check (XXX don't know what 13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * POSIX has to say). 13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(mode & X_OK) && fl != O_RDWR && ( 13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((mode & R_OK) && fl != O_RDONLY) || 13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((mode & W_OK) && fl != O_WRONLY))) { 13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (emsgp) 13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *emsgp = (fl == O_WRONLY) ? 13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "fd not open for reading" : 13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "fd not open for writing"; 13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (fd); 13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called once from main */ 13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_init(void) 13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.read = coproc.readw = coproc.write = -1; 13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.njobs = 0; 13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.id = 0; 13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called by c_read() when eof is read - close fd if it is the co-process fd */ 13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_read_close(int fd) 13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.read >= 0 && fd == coproc.read) { 13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc_readw_close(fd); 13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.read); 13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.read = -1; 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 136703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 136803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by c_read() and by iosetup() to close the other side of the 13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * read pipe, so reads will actually terminate. 13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_readw_close(int fd) 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) { 13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.readw); 13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.readw = -1; 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 138003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 138103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called by c_print when a write to a fd fails with EPIPE and by iosetup 13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * when co-process input is dup'd 13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_write_close(int fd) 13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.write >= 0 && fd == coproc.write) { 13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.write); 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.write = -1; 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 139303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 139403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Called to check for existence of/value of the co-process file descriptor. 13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (Used by check_fd() and by c_read/c_print to deal with -p option). 13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_getfd(int mode, const char **emsgp) 13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd = (mode & R_OK) ? coproc.read : coproc.write; 14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fd >= 0) 14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (fd); 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (emsgp) 14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *emsgp = "no coprocess"; 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 140903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 141003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * called to close file descriptors related to the coprocess (if any) 14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Should be called with SIGCHLD blocked. 14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucoproc_cleanup(int reuse) 14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* This to allow co-processes to share output pipe */ 14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!reuse || coproc.readw < 0 || coproc.read < 0) { 14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.read >= 0) { 14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.read); 14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.read = -1; 14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.readw >= 0) { 14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.readw); 14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.readw = -1; 14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.write >= 0) { 14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(coproc.write); 14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.write = -1; 14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct temp * 14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumaketemp(Area *ap, Temp_type type, struct temp **tlist) 14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct temp *tp; 143703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *pathname; 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *dir; 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR; 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKSTEMP 14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(dir) + 6 + 10 + 1; 14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pathname = tempnam(dir, "mksh."); 14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = ((pathname == NULL) ? 0 : strlen(pathname)) + 1; 14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 144903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* reasonably sure that this will not overflow */ 14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = alloc(sizeof(struct temp) + len, ap); 14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->name = (char *)&tp[1]; 14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_MKSTEMP 14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pathname == NULL) 14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->name[0] = '\0'; 14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(tp->name, pathname, len); 145703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra free_ostempnam(pathname); 14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pathname = tp->name; 14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->shf = NULL; 14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = type; 14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKSTEMP 146403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_snprintf(pathname, len, "%s%s", dir, "/mksh.XXXXXXXXXX"); 14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fd = mkstemp(pathname)) >= 0) 14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->name[0] && (fd = open(tp->name, O_CREAT | O_RDWR, 0600)) >= 0) 14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->shf = shf_fdopen(fd, SHF_WR, NULL); 14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->pid = procpid; 14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->next = *tlist; 14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tlist = tp; 14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (tp); 14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * We use a similar collision resolution algorithm as Python 2.5.4 14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * but with a slightly tweaked implementation written from scratch. 14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 148203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define INIT_TBLSHIFT 3 /* initial table shift (2^3 = 8) */ 14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PERTURB_SHIFT 5 /* see Python 2.5.4 Objects/dictobject.c */ 14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 148503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void tgrow(struct table *); 14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int tnamecmp(const void *, const void *); 14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 148903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condratgrow(struct table *tp) 14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 149103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t i, j, osize, mask, perturb; 14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tblp, **pp; 14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl **ntblp, **otblp = tp->tbls; 14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 149503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp->tshift > 29) 149603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("hash table size limit reached"); 149703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 149803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* calculate old size, new shift and new size */ 149903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra osize = (size_t)1 << (tp->tshift++); 150003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = osize << 1; 150103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 150203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ntblp = alloc2(i, sizeof(struct tbl *), tp->areap); 150303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* multiplication cannot overflow: alloc2 checked that */ 150403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memset(ntblp, 0, i * sizeof(struct tbl *)); 150503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 150603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* table can get 80% full except when reaching its limit */ 150703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->nfree = (tp->tshift == 30) ? 0x3FFF0000UL : ((i * 4) / 5); 15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->tbls = ntblp; 15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (otblp == NULL) 15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 151103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 151203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra mask = i - 1; 15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < osize; i++) 15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((tblp = otblp[i]) != NULL) { 15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((tblp->flag & DEFINED)) { 15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* search for free hash table slot */ 151703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra j = (perturb = tblp->ua.hval) & mask; 15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto find_first_empty_slot; 15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_next_empty_slot: 15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j = (j << 2) + j + perturb + 1; 15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru perturb >>= PERTURB_SHIFT; 15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_first_empty_slot: 152303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pp = &ntblp[j & mask]; 15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*pp != NULL) 15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto find_next_empty_slot; 15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* found an empty hash table slot */ 15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *pp = tblp; 15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->nfree--; 15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (!(tblp->flag & FINUSE)) { 15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tblp, tp->areap); 15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(otblp, tp->areap); 15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 153703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraktinit(Area *ap, struct table *tp, uint8_t initshift) 15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->areap = ap; 15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->tbls = NULL; 154103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->tshift = ((initshift > INIT_TBLSHIFT) ? 154203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra initshift : INIT_TBLSHIFT) - 1; 154303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tgrow(tp); 15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* table, name (key) to search for, hash(name), rv pointer to tbl ptr */ 154703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastruct tbl * 15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktscan(struct table *tp, const char *name, uint32_t h, struct tbl ***ppp) 15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t j, perturb, mask; 15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl **pp, *p; 15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 155303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra mask = ((size_t)1 << (tp->tshift)) - 1; 15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* search for hash table slot matching name */ 15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j = (perturb = h) & mask; 15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto find_first_slot; 15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_next_slot: 15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j = (j << 2) + j + perturb + 1; 15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru perturb >>= PERTURB_SHIFT; 15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru find_first_slot: 15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pp = &tp->tbls[j & mask]; 15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = *pp) != NULL && (p->ua.hval != h || !(p->flag & DEFINED) || 15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strcmp(p->name, name))) 15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto find_next_slot; 15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* p == NULL if not found, correct found entry otherwise */ 15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ppp) 15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *ppp = pp; 15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* table, name (key) to enter, hash(n) */ 15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl * 15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktenter(struct table *tp, const char *n, uint32_t h) 15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl **pp, *p; 157603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Search: 15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p = ktscan(tp, n, h, &pp))) 15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 158203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp->nfree == 0) { 15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* too full */ 158403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tgrow(tp); 15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Search; 15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* create new tbl entry */ 158903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra len = strlen(n); 159003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra checkoktoadd(len, offsetof(struct tbl, name[0]) + 1); 159103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap); 15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flag = 0; 15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->type = 0; 15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->areap = tp->areap; 15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->ua.hval = h; 15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->u2.field = 0; 15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->u.array = NULL; 15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(p->name, n, len); 15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* enter in tp->tbls */ 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->nfree--; 16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *pp = p; 16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktwalk(struct tstate *ts, struct table *tp) 16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 160903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ts->left = (size_t)1 << (tp->tshift); 16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ts->next = tp->tbls; 16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl * 16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktnext(struct tstate *ts) 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (--ts->left >= 0) { 16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *p = *ts->next++; 16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p != NULL && (p->flag & DEFINED)) 16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutnamecmp(const void *p1, const void *p2) 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct tbl *a = *((const struct tbl * const *)p1); 16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct tbl *b = *((const struct tbl * const *)p2); 16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (strcmp(a->name, b->name)); 16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl ** 16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruktsort(struct table *tp) 16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t i; 16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl **p, **sp, **dp; 16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 163903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 164003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * since the table is never entirely full, no need to reserve 164103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * additional space for the trailing NULL appended below 164203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 164303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = (size_t)1 << (tp->tshift); 164403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra p = alloc2(i, sizeof(struct tbl *), ATEMP); 16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = tp->tbls; /* source */ 16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp = p; /* dest */ 16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i--) 16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*dp = *sp++) != NULL && (((*dp)->flag & DEFINED) || 16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((*dp)->flag & ARRAY))) 16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dp++; 165103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra qsort(p, (i = dp - p), sizeof(struct tbl *), tnamecmp); 16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p[i] = NULL; 16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef SIGWINCH 16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querux_sigwinch(int sig MKSH_A_UNUSED) 16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this runs inside interrupt context, with errno saved */ 16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru got_winch = 1; 16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 1665