1811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser/* $OpenBSD: exec.c,v 1.50 2013/06/10 21:09:27 millert Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 4c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 5427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes * 2011, 2012, 2013, 2014 65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 26b4542e99ca8562aa584e15df8ef35356ff8c10feElliott Hughes__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $"); 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_DEFAULT_EXECSHELL 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MKSH_DEFAULT_EXECSHELL "/bin/sh" 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int comexec(struct op *, struct tbl * volatile, const char **, 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int volatile, volatile int *); 345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void scriptexec(struct op *, const char **) MKSH_A_NORETURN; 35c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int call_builtin(struct tbl *, const char **, const char *); 365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int iosetup(struct ioword *, struct tbl *); 37c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int herein(struct ioword *, char **); 385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *do_selectargs(const char **, bool); 395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op dbteste_isa(Test_env *, Test_meta); 405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *dbteste_getopnd(Test_env *, Test_op, bool); 415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void dbteste_error(Test_env *, int, const char *); 4203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int search_access(const char *, int); 43c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* XXX: horrible kludge to fit within the framework */ 44c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char *plain_fmt_entry(char *, size_t, unsigned int, const void *); 45c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char *select_fmt_entry(char *, size_t, unsigned int, const void *); 465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * execute command tree 495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraexecute(struct op * volatile t, 5203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* if XEXEC don't fork */ 5303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile int flags, 545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int * volatile xerrok) 555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int rv = 0, dummy = 0; 585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int pv[2]; 5903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char ** volatile ap = NULL; 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char ** volatile up; 6103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *s, *ccp; 625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword **iowp; 635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp = NULL; 6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t == NULL) 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Caller doesn't care if XERROK should propagate. */ 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (xerrok == NULL) 715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xerrok = &dummy; 725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE) 745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* run in sub-process */ 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (exchild(t, flags & ~XTIME, xerrok, -1)); 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newenv(E_EXEC); 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (trap) 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru runtraps(0); 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we want to run an executable, do some variance checks */ 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->type == TCOM) { 8303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check if this is 'var=<<EOF' */ 8403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ( 8503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we have zero arguments, i.e. no programme to run */ 8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->args[0] == NULL && 8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we have exactly one variable assignment */ 8803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->vars[0] != NULL && t->vars[1] == NULL && 8903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we have exactly one I/O redirection */ 9003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->ioact != NULL && t->ioact[0] != NULL && 9103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->ioact[1] == NULL && 9203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* of type "here document" (or "here string") */ 9303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (t->ioact[0]->flag & IOTYPE) == IOHERE && 9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* the variable assignment begins with a valid varname */ 9503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] && 9603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* and has no right-hand side (i.e. "varname=") */ 9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS && 9803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* plus we can have a here document content */ 99c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser herein(t->ioact[0], &cp) == 0 && cp && *cp) { 10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *sp = cp, *dp; 10103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t n = ccp - t->vars[0] + 2, z; 10203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* drop redirection (will be garbage collected) */ 10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->ioact = NULL; 10503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* set variable to its expanded value */ 10703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra z = strlen(cp) + 1; 10803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (notoktomul(z, 2) || notoktoadd(z * 2, n)) 109811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser internal_errorf(Toomem, (size_t)-1); 11003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp = alloc(z * 2 + n, ATEMP); 11103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dp, t->vars[0], n); 11203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra t->vars[0] = dp; 11303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp += n; 11403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*sp) { 11503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = QCHAR; 11603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = *sp++; 11703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = EOS; 11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* free the expanded value */ 12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(cp, APERM); 12103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 12303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Clear subst_exstat before argument expansion. Used by 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * null commands (see comexec() and c_eval()) and by c_set(). 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_exstat = 0; 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* for $LINENO */ 13003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra current_lineno = t->lineno; 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 13303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * POSIX says expand command words first, then redirections, 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and assignments last.. 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE); 1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flags & XTIME) 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Allow option parsing (bizarre, but POSIX) */ 1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru timex_hook(t, &up); 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap = (const char **)up; 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ap[0]) 1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = findcom(ap[0], FC_BI|FC_FUNC); 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~XTIME; 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) { 14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra e->savefd = alloc2(NUFILE, sizeof(short), ATEMP); 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* initialise to not redirected */ 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memset(e->savefd, 0, NUFILE * sizeof(short)); 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* mark for replacement later (unless TPIPE) */ 15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp_pipest->flag |= INT_L; 15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do redirection, to be restored in quitenv() */ 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->ioact != NULL) 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (iowp = t->ioact; *iowp != NULL; iowp++) { 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iosetup(*iowp, tp) < 0) { 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exstat = rv = 1; 16003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 16103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Redirection failures for special commands 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * cause (non-interactive) shell to exit. 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp && tp->type == CSHELL && 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (tp->flag & SPEC_BI)) 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorfz(); 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Deal with FERREXIT, quitenv(), etc. */ 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Break; 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (t->type) { 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TCOM: 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = comexec(t, tp, (const char **)ap, flags, xerrok); 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TPAREN: 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, flags | XFORK, xerrok); 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TPIPE: 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags |= XFORK; 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~XEXEC; 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[0] = savefd(0); 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[1] = savefd(1); 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (t->type == TPIPE) { 1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru openpipe(pv); 18803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* stdout of curr */ 18903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ksh_dup2(pv[1], 1, false); 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /** 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Let exchild() close pv[0] in child 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (if this isn't done, commands like 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (: ; cat /etc/termcap) | sleep 1 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * will hang forever). 1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exchild(t->left, flags | XPIPEO | XCCLOSE, 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, pv[0]); 19803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* stdin of next */ 19903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ksh_dup2(pv[0], 0, false); 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru closepipe(pv); 2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags |= XPIPEI; 2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = t->right; 2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* stdout of last */ 20503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra restfd(1, e->savefd[1]); 20603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no need to re-restore this */ 20703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra e->savefd[1] = 0; 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Let exchild() close 0 in parent, after fork, before wait */ 20903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0); 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags&XBGND) && !(flags&XXCOM)) 2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = i; 2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TLIST: 2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (t->type == TLIST) { 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execute(t->left, flags & XERROK, NULL); 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru t = t->right; 2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t, flags & XERROK, xerrok); 2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TCOPROC: { 22303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK 2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigset_t omask; 2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 22603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 22703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Block sigchild as we are using things changed in the 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * signal handler 2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->type = E_ERRH; 232c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((i = kshsetjmp(e->jbuf))) { 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigprocmask(SIG_SETMASK, &omask, NULL); 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 23803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Already have a (live) co-process? */ 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.job && coproc.write >= 0) 2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("coprocess already exists"); 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Can we re-use the existing co-process pipe? */ 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc_cleanup(true); 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do this before opening pipes, in case these fail */ 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[0] = savefd(0); 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[1] = savefd(1); 2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru openpipe(pv); 2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pv[0] != 0) { 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(pv[0], 0, false); 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(pv[0]); 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.write = pv[1]; 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.job = NULL; 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (coproc.readw >= 0) 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(coproc.readw, 1, false); 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru openpipe(pv); 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.read = pv[0]; 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(pv[1], 1, false); 26403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* closed before first read */ 26503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra coproc.readw = pv[1]; 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc.njobs = 0; 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* create new coprocess id */ 2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++coproc.id; 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 27003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigprocmask(SIG_SETMASK, &omask, NULL); 27203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no more need for error handler */ 27303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra e->type = E_EXEC; 27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 27603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 27703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * exchild() closes coproc.* in child after fork, 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * will also increment coproc.njobs when the 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * job is actually created. 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~XEXEC; 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE, 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru NULL, coproc.readw); 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TASYNC: 28803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 28903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * XXX non-optimal, I think - "(foo &)", forks for (), 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * forks again for async... parent should optimise 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this to "foo &"... 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok); 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TOR: 2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TAND: 2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, XERROK, xerrok); 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((rv == 0) == (t->type == TAND)) 300811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser rv = execute(t->right, flags & XERROK, xerrok); 301811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else { 302811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser flags |= XERROK; 303811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (xerrok) 304811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *xerrok = 1; 305811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TBANG: 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = !execute(t->right, XERROK, xerrok); 3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags |= XERROK; 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (xerrok) 3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xerrok = 1; 3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TDBRACKET: { 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Test_env te; 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.flags = TEF_DBRACKET; 3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.pos.wp = t->args; 3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.isa = dbteste_isa; 3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.getopnd = dbteste_getopnd; 3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.eval = test_eval; 3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te.error = dbteste_error; 3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = test_parse(&te); 3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TFOR: 3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TSELECT: { 3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile bool is_first = true; 332811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap = (t->vars == NULL) ? e->loc->argv + 1 : 3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (const char **)eval((const char **)t->vars, 3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru DOBLANK | DOGLOB | DOTILDE); 3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->type = E_LOOP; 337c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((i = kshsetjmp(e->jbuf))) { 3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((e->flags&EF_BRKCONT_PASS) || 3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (i != LBREAK && i != LCONTIN)) { 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (i == LBREAK) { 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 0; 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Break; 3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 34703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* in case of a continue */ 34803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 0; 3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->type == TFOR) { 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*ap != NULL) { 3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); 3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, flags & XERROK, xerrok); 3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 35403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 35503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* TSELECT */ 3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (;;) { 35703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(ccp = do_selectargs(ap, is_first))) { 3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 1; 3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru is_first = false; 36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(global(t->str), ccp, KSH_UNWIND_ERROR); 3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execute(t->left, flags & XERROK, xerrok); 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TWHILE: 3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TUNTIL: 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->type = E_LOOP; 372c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((i = kshsetjmp(e->jbuf))) { 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((e->flags&EF_BRKCONT_PASS) || 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (i != LBREAK && i != LCONTIN)) { 3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (i == LBREAK) { 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 0; 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Break; 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 38203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* in case of a continue */ 38303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 0; 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((execute(t->left, XERROK, NULL) == 0) == 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (t->type == TWHILE)) 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->right, flags & XERROK, xerrok); 3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TIF: 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TELIF: 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->right == NULL) 39203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* should be error */ 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, XERROK, NULL) == 0 ? 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execute(t->right->left, flags & XERROK, xerrok) : 3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execute(t->right->right, flags & XERROK, xerrok); 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TCASE: 40003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = 0; 40103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = evalstr(t->str, DOTILDE); 40203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra for (t = t->left; t != NULL && t->type == TPAT; t = t->right) { 40303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra for (ap = (const char **)t->vars; *ap; ap++) { 40403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) && 40503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra gmatchx(ccp, s, false))) { 40603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = execute(t->left, flags & XERROK, 40703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xerrok); 40803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = 0; 40903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (t->u.charflag) { 41003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '&': 41103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = 1; 41203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* FALLTHROUGH */ 41303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '|': 41403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto TCASE_next; 41503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 41603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto TCASE_out; 41703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 41803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 41903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = 0; 42003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra TCASE_next: 42103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* empty */; 42203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 42303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra TCASE_out: 4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TBRACE: 4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = execute(t->left, flags & XERROK, xerrok); 4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TFUNCT: 4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = define(t->str, t); 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case TTIME: 43503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 43603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Clear XEXEC so nested execute() call doesn't exit 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (allows "ls -l | time grep foo"). 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = timex(t, flags & ~XEXEC, xerrok); 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 44203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case TEXEC: 44303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* an eval'd TCOM */ 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = t->args[0]; 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru up = makenv(); 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restoresigs(); 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cleanup_proc_env(); 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union mksh_ccphack cargs; 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cargs.ro = t->args; 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execve(t->str, cargs.rw, up); 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = errno; 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (rv == ENOEXEC) 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru scriptexec(t, (const char **)up); 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 458c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errorf("%s: %s", s, cstrerror(rv)); 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Break: 461c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = rv & 0xFF; 46203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (vp_pipest->flag & INT_L) { 46303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unset(vp_pipest, 1); 46403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY | 465427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes ARRAY | INT_U | INT_L; 46603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra vp_pipest->val.i = rv; 46703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 46903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restores IO */ 47003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quitenv(NULL); 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((flags&XEXEC)) 47203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* exit child */ 47303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unwind(LEXIT); 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (rv != 0 && !(flags & XERROK) && 4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (xerrok == NULL || !*xerrok)) { 476c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (Flag(FERREXIT) & 0x80) { 477c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* inside eval */ 478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Flag(FERREXIT) = 0; 479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 480c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser trapsig(ksh_SIGERR); 481c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (Flag(FERREXIT)) 482c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unwind(LERROR); 483c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * execute simple command 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condracomexec(struct op *t, struct tbl * volatile tp, const char **ap, 4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int flags, volatile int *xerrok) 4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile int rv = 0; 4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cp; 4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char **lastp; 50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Must be static (XXX but why?) */ 50103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra static struct op texec; 5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int type_flags; 503c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool keepasn_ok; 5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fcflags = FC_BI|FC_FUNC|FC_PATH; 5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool bourne_function_call = false; 5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct block *l_expand, *l_assign; 5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 50803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 50903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * snag the last argument for $_ XXX not the same as AT&T ksh, 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * which only seems to set $_ after a newline (but not in 5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * functions/dot scripts, but in interactive and script) - 5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * perhaps save last arg here and set it in shell()?. 5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FTALKING) && *(lastp = ap)) { 5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*++lastp) 5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* setstr() can't fail here */ 5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp, 5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru KSH_RETURN_ERROR); 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 52203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /** 52303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Deal with the shell builtins builtin, exec and command since 5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * they can be followed by other commands. This must be done before 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * we know if we should create a local block which must be done 5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * before we can do a path search (in case the assignments change 5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * PATH). 5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Odd cases: 5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * FOO=bar exec >/dev/null FOO is kept but not exported 5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * FOO=bar exec foobar FOO is exported 5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * FOO=bar command exec >/dev/null FOO is neither kept nor exported 5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * FOO=bar command FOO is neither kept nor exported 5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * PATH=... foobar use new PATH in foobar search 5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 535c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser keepasn_ok = true; 5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (tp && tp->type == CSHELL) { 53703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undo effects of command */ 53803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fcflags = FC_BI|FC_FUNC|FC_PATH; 5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->val.f == c_builtin) { 54003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp = *++ap) == NULL || 54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (!strcmp(cp, "--") && (cp = *++ap) == NULL)) { 5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = NULL; 5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((tp = findcom(cp, FC_BI)) == NULL) 54603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); 5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (tp->val.f == c_exec) { 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ap[1] == NULL) 5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap++; 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags |= XEXEC; 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (tp->val.f == c_command) { 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int optc, saw_p = 0; 5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 55603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 55703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Ugly dealing with options in two places (here 55803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * and in c_command(), but such is life) 5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_getopt_reset(&builtin_opt, 0); 5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p') 5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru saw_p = 1; 5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optc != EOF) 56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* command -vV or something */ 56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* don't look for functions */ 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fcflags = FC_BI|FC_PATH; 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (saw_p) { 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FRESTRICTED)) { 57003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s", 57103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "command -p", "restricted"); 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 1; 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Leave; 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fcflags |= FC_DEFPATH; 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap += builtin_opt.optind; 57803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 57903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * POSIX says special builtins lose their status 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if accessed using command. 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 582c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser keepasn_ok = false; 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ap[0]) { 5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ensure command with no args exits with 0 */ 5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru subst_exstat = 0; 5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 58803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NO_EXTERNAL_CAT 58903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (tp->val.f == c_cat) { 59003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 59103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if we have any flags, do not use the builtin 59203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * in theory, we could allow -u, but that would 59303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * mean to use ksh_getopt here and possibly ad- 59403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ded complexity and more code and isn't worth 59503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * additional hassle (and the builtin must call 59603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ksh_getopt already but can't come back here) 59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && 59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* argument, begins with -, is not - or -- */ 60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (ap[1][1] != '-' || ap[1][2] != '\0')) 60103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* don't look for builtins or functions */ 60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fcflags = FC_PATH; 60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 60403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* go on, use the builtin */ 60503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 607c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (tp->val.f == c_trap) { 608c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser t->u.evalflags &= ~DOTCOMEXEC; 609c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC)); 6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 614c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (t->u.evalflags & DOTCOMEXEC) 615c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser flags |= XEXEC; 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l_expand = e->loc; 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN)))) 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type_flags = 0; 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* create new variable/function block */ 6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru newblock(); 6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ksh functions don't keep assignments, POSIX functions do. */ 6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (keepasn_ok && tp && tp->type == CFUNC && 6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !(tp->flag & FKSH)) { 6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bourne_function_call = true; 6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type_flags = EXPORT; 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type_flags = LOCAL|LOCAL_COPY|EXPORT; 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru l_assign = e->loc; 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FEXPORT)) 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru type_flags |= EXPORT; 633811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (Flag(FXTRACE)) 634811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(2, false); 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; t->vars[i]; i++) { 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do NOT lookup in the new var/fn block just created */ 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc = l_expand; 638b4542e99ca8562aa584e15df8ef35356ff8c10feElliott Hughes cp = evalstr(t->vars[i], DOASNTILDE | DOASNFIELD); 6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc = l_assign; 6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FXTRACE)) { 641811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *ccp; 642811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 643811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ccp = skip_varname(cp, true); 644811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (*ccp == '+') 645811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++ccp; 646811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (*ccp == '=') 647811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++ccp; 648811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_write(cp, ccp - cp, shl_xtrace); 649811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser print_value_quoted(shl_xtrace, ccp); 650811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_putc(' ', shl_xtrace); 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 652811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* but assign in there as usual */ 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru typeset(cp, type_flags, 0, 0, 0); 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (bourne_function_call && !(type_flags & EXPORT)) 655427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0); 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 658811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (Flag(FXTRACE)) { 659811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(2, false); 660811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ap[rv = 0]) { 661811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser xtrace_ap_loop: 662811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser print_value_quoted(shl_xtrace, ap[rv]); 663811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (ap[++rv]) { 664811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_putc(' ', shl_xtrace); 665811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser goto xtrace_ap_loop; 666811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 667811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 668811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(1, false); 669811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 670811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cp = *ap) == NULL) { 6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = subst_exstat; 6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Leave; 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (!tp) { 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FRESTRICTED) && vstrchr(cp, '/')) { 67603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s", cp, "restricted"); 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 1; 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Leave; 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = findcom(cp, fcflags); 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (tp->type) { 68403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 68503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* shell built-in */ 68603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CSHELL: 687c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = call_builtin(tp, (const char **)ap, null); 688c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!keepasn_ok && tp->val.f == c_shift) { 689c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser l_expand->argc = l_assign->argc; 690c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser l_expand->argv = l_assign->argv; 691c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 69403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* function call */ 69503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CFUNC: { 6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru volatile unsigned char old_xflag; 69703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra volatile uint32_t old_inuse; 69803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char * volatile old_kshname; 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(tp->flag & ISSET)) { 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *ftp; 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tp->u.fpath) { 70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = (tp->u2.errnov == ENOENT) ? 127 : 126; 70503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s %s: %s", cp, 70603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "can't find", "function definition file", 707c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cstrerror(tp->u2.errnov)); 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 710c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (include(tp->u.fpath, 0, NULL, false) < 0) { 71103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s %s %s: %s", cp, 71203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "can't open", "function definition file", 713811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser tp->u.fpath, cstrerror(errno)); 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 127; 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(ftp = findfunc(cp, hash(cp), false)) || 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !(ftp->flag & ISSET)) { 71903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s %s", cp, 72003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "function not defined by", tp->u.fpath); 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 127; 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ftp; 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 72703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 72803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ksh functions set $0 to function name, POSIX 72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * functions leave $0 unchanged. 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_kshname = kshname; 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & FKSH) 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshname = ap[0]; 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ap[0] = kshname; 7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argv = ap; 7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; *ap++ != NULL; i++) 7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->argc = i - 1; 74003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 74103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ksh-style functions handle getopts sanely, 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Bourne/POSIX functions are insane... 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & FKSH) { 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->flags |= BF_DOGETOPTS; 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->loc->getopts_state = user_opt; 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru getopts_reset(1); 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 750811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser old_xflag = Flag(FXTRACE) ? 1 : 0; 751811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) | 752811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ((tp->flag & TRACE) ? 1 : 0), false); 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_inuse = tp->flag & FINUSE; 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag |= FINUSE; 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->type = E_FUNC; 757c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!(i = kshsetjmp(e->jbuf))) { 758c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser execute(tp->val.t, flags & XERROK, NULL); 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = LRETURN; 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 761811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru kshname = old_kshname; 763811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(old_xflag, false); 7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag = (tp->flag & ~FINUSE) | old_inuse; 765811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 76603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 76703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Were we deleted while executing? If so, free the 76803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * execution tree. TODO: Unfortunately, the table entry 76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * is never re-used until the lookup table is expanded. 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) { 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & ALLOC) { 7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~ALLOC; 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tfree(tp->val.t, tp->areap); 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag = 0; 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (i) { 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LRETURN: 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LERROR: 781c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = exstat & 0xFF; 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LINTR: 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LEXIT: 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LLEAVE: 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case LSHELL: 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(i); 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru quitenv(NULL); 79203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("%s %d", "CFUNC", i); 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* executable command */ 79803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CEXEC: 79903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* tracked alias */ 80003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case CTALIAS: 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(tp->flag&ISSET)) { 80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp->u2.errnov == ENOENT) { 8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 127; 80403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s", cp, "not found"); 80503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 80603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 126; 80703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s: %s", cp, "can't execute", 808c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cstrerror(tp->u2.errnov)); 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* set $_ to programme's full path */ 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* setstr() can't fail here */ 815427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0), 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->val.s, KSH_RETURN_ERROR); 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flags&XEXEC) { 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_exit(); 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags&XBGND) 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru || Flag(FMONITOR) 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ) { 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG); 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG); 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* to fork we set up a TEXEC node and call execute */ 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru texec.type = TEXEC; 83203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* for tprint */ 83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra texec.left = t; 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru texec.str = tp->val.s; 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru texec.args = ap; 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = exchild(&texec, flags, xerrok, -1); 8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Leave: 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flags & XEXEC) { 841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = rv & 0xFF; 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LLEAVE); 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruscriptexec(struct op *tp, const char **ap) 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *sh; 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char *cp; 85303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 64 == MAXINTERP in MirBSD <sys/param.h> */ 85403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char buf[64]; 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union mksh_ccphack args, cap; 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sh = str_val(global("EXECSHELL")); 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sh && *sh) 86103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sh = search_path(sh, path, X_OK, NULL); 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!sh || !*sh) 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sh = MKSH_DEFAULT_EXECSHELL; 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp->args-- = tp->str; 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL 868427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) { 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* read first MAXINTERP octets from file */ 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (read(fd, buf, sizeof(buf)) <= 0) 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* read error -> no good */ 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru buf[0] = '\0'; 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 87403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 87503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip UTF-8 Byte Order Mark, if present */ 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp = (unsigned char *)buf; 87703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF)) 87803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp += 3; 87903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* save begin of shebang for later */ 88003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fd = (char *)cp - buf; /* either 0 or (if BOM) 3 */ 88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 88203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* scan for newline (or CR) or NUL _before_ end of buffer */ 883427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes while ((size_t)((char *)cp - buf) < sizeof(buf)) 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp == '\0' || *cp == '\n' || *cp == '\r') { 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp = '\0'; 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* if the shebang line is longer than MAXINTERP, bail out */ 890427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if ((size_t)((char *)cp - buf) >= sizeof(buf)) 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto noshebang; 89203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 89303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore begin of shebang position (buf+0 or buf+3) */ 89403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = (unsigned char *)(buf + fd); 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* bail out if read error (above) or no shebang */ 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cp[0] != '#') || (cp[1] != '!')) 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto noshebang; 89803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp += 2; 9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip whitespace before shell name */ 9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*cp == ' ' || *cp == '\t') 9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* just whitespace on the line? */ 9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp == '\0') 9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto noshebang; 9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* no, we actually found an interpreter name */ 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sh = (char *)cp; 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* look for end of shell/interpreter name */ 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*cp != ' ' && *cp != '\t' && *cp != '\0') 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* any arguments? */ 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp) { 9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = '\0'; 9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip spaces before arguments */ 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*cp == ' ' || *cp == '\t') 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++cp; 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* pass it all in ONE argument (historic reasons) */ 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp) 9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *tp->args-- = (char *)cp; 9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru noshebang: 922427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if (buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' && 923427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes buf[3] == 'F') 924427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes errorf("%s: not executable: %d-bit ELF file", tp->str, 925427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes 32 * ((uint8_t)buf[4])); 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fd = buf[0] << 8 | buf[1]; 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fd == /* OMAGIC */ 0407) || 9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* NMAGIC */ 0410) || 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* ZMAGIC */ 0413) || 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* QMAGIC */ 0314) || 9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* ECOFF_I386 */ 0x4C01) || 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) || 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* ECOFF_SH */ 0x0500 || fd == 0x0005) || 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* "MZ" */ 0x4D5A) || 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fd == /* gzip */ 0x1F8B)) 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("%s: not executable: magic %04X", tp->str, fd); 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru args.ro = tp->args; 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *args.ro = sh; 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cap.ro = ap; 9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru execve(args.rw[0], args.rw, cap.rw); 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* report both the programme that was run and the bogus interpreter */ 946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errorf("%s: %s: %s", tp->str, sh, cstrerror(errno)); 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querushcomexec(const char **wp) 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp; 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktsearch(&builtins, *wp, hash(*wp)); 955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (call_builtin(tp, wp, "shcomexec")); 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Search function tables for a function. If create set, a table entry 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is created if none is found. 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl * 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufindfunc(const char *name, uint32_t h, bool create) 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct block *l; 9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp = NULL; 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (l = e->loc; l; l = l->next) { 9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktsearch(&l->funs, name, h); 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp) 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!l->next && create) { 9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktenter(&l->funs, name, h); 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag = DEFINED; 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = CFUNC; 9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->val.t = NULL; 9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (tp); 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * define function. Returns 1 if function is being undefined (t == 0) and 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * function did not exist, returns 0 otherwise. 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudefine(const char *name, struct op *t) 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 99003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra uint32_t nhash; 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp; 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool was_set = false; 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra nhash = hash(name); 99503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 99603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (t != NULL && !tobool(t->u.ksh_func)) { 99703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* drop same-name aliases for POSIX functions */ 99803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((tp = ktsearch(&aliases, name, nhash))) 99903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ktdelete(tp); 100003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 100103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 100203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 100303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = findfunc(name, nhash, true); 1004c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* because findfunc:create=true */ 1005c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mkssert(tp != NULL); 10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & ISSET) 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru was_set = true; 100903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 101003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * If this function is currently being executed, we zap 101103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * this table entry so findfunc() won't see it 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & FINUSE) { 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->name[0] = '\0'; 101503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ensure it won't be found */ 101603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->flag &= ~DEFINED; 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag |= FDELETE; 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & ALLOC) { 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~(ISSET|ALLOC); 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tfree(tp->val.t, tp->areap); 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 102703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (t == NULL) { 102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* undefine */ 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ktdelete(tp); 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (was_set ? 0 : 1); 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->val.t = tcopy(t->left, tp->areap); 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag |= (ISSET|ALLOC); 10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t->u.ksh_func) 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag |= FKSH; 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * add builtin 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 104403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraconst char * 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubuiltin(const char *name, int (*func) (const char **)) 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp; 1048811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser uint32_t flag = DEFINED; 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* see if any flags should be set for this builtin */ 1051811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (1) { 105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*name == '=') 105303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* command does variable assignment */ 10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flag |= KEEPASN; 105503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (*name == '*') 105603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX special builtin */ 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flag |= SPEC_BI; 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1060811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser name++; 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktenter(&builtins, name, hash(name)); 1064811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser tp->flag = flag; 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = CSHELL; 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->val.f = func; 106703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (name); 10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * find command 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * either function, hashed command, or built-in (in that order) 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct tbl * 10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufindcom(const char *name, int flags) 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru static struct tbl temp; 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uint32_t h = hash(name); 10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp = NULL, *tbi; 108103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* insert if not found */ 108203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unsigned char insert = Flag(FTRACKALL); 108303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* for function autoloading */ 108403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *fpath; 10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru union mksh_cchack npath; 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vstrchr(name, '/')) { 10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru insert = 0; 10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* prevent FPATH search below */ 10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~FC_FUNC; 10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto Search; 10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL; 109403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 109503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * POSIX says special builtins first, then functions, then 1096811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * regular builtins, then search path... 10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI)) 10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = tbi; 11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tp && (flags & FC_FUNC)) { 11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = findfunc(name, h, false); 11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp && !(tp->flag & ISSET)) { 11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fpath = str_val(global("FPATH"))) == null) { 11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->u.fpath = NULL; 110503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->u2.errnov = ENOENT; 11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 110703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->u.fpath = search_path(name, fpath, R_OK, 110803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra &tp->u2.errnov); 11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1111811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!tp && (flags & FC_NORMBI) && tbi) 11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = tbi; 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) { 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktsearch(&taliases, name, h); 111503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp && (tp->flag & ISSET) && 111603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ksh_access(tp->val.s, X_OK) != 0) { 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag & ALLOC) { 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~ALLOC; 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tp->val.s, APERM); 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~ISSET; 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Search: 11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) && 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (flags & FC_PATH)) { 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tp) { 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (insert && !(flags & FC_DEFPATH)) { 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = ktenter(&taliases, name, h); 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = CTALIAS; 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = &temp; 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = CEXEC; 11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* make ~ISSET */ 113703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->flag = DEFINED; 11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 113903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra npath.ro = search_path(name, 114003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (flags & FC_DEFPATH) ? def_path : path, 114103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra X_OK, &tp->u2.errnov); 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (npath.ro) { 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(tp->val.s, npath.ro, APERM); 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (npath.ro != name) 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(npath.rw, ATEMP); 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag |= ISSET|ALLOC; 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((flags & FC_FUNC) && 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (fpath = str_val(global("FPATH"))) != null && 114903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (npath.ro = search_path(name, fpath, R_OK, 115003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra &tp->u2.errnov)) != NULL) { 115103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 115203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * An undocumented feature of AT&T ksh is that 115303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * it searches FPATH if a command is not found, 115403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * even if the command hasn't been set up as an 115503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * autoloaded function (ie, no typeset -uf). 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp = &temp; 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->type = CFUNC; 115903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* make ~ISSET */ 116003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp->flag = DEFINED; 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->u.fpath = npath.ro; 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (tp); 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * flush executable commands with relative paths 116903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * (just relative or all?) 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 117203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraflushcom(bool all) 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tbl *tp; 11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tstate ts; 11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; ) 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) { 11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tp->flag&ALLOC) { 11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~(ALLOC|ISSET); 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(tp->val.s, APERM); 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tp->flag &= ~ISSET; 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 118703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* check if path is something we want to find */ 118803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 118903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasearch_access(const char *fn, int mode) 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 119103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct stat sb; 119203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 119303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (stat(fn, &sb) < 0) 119403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* file does not exist */ 119503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (ENOENT); 119603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* LINTED use of access */ 119703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (access(fn, mode) < 0) 119803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* file exists, but we can't access it */ 119903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (errno); 120003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (mode == X_OK && (!S_ISREG(sb.st_mode) || 120103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra !(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) 120203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* access(2) may say root can execute everything */ 120303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES); 120403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (0); 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * search for command with PATH 12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char * 121103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasearch_path(const char *name, const char *lpath, 121203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* R_OK or X_OK */ 121303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int mode, 121403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* set if candidate found, but not suitable */ 121503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int *errnop) 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *sp, *p; 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp; 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString xs; 122003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t namelen; 122103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int ec = 0, ev; 12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (vstrchr(name, '/')) { 122403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((ec = search_access(name, mode)) == 0) { 122503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra search_path_ok: 122603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errnop) 122703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *errnop = 0; 12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (name); 122903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 123003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto search_path_err; 12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru namelen = strlen(name) + 1; 12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(xs, xp, 128, ATEMP); 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = lpath; 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (sp != NULL) { 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp = Xstring(xs, xp); 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p = cstrchr(sp, ':'))) 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = sp + strlen(sp); 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p != sp) { 12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(xs, xp, p - sp); 12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, sp, p - sp); 12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += p - sp; 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp++ = '/'; 12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = p; 12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(xs, xp, namelen); 12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, name, namelen); 125003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((ev = search_access(Xstring(xs, xp), mode)) == 0) { 125103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra name = Xclose(xs, xp + namelen); 125203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto search_path_ok; 125303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 125403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* accumulate non-ENOENT errors only */ 125503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ev != ENOENT && ec == 0) 125603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ec = ev; 12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*sp++ == '\0') 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sp = NULL; 12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xfree(xs, xp); 126103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra search_path_err: 126203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errnop) 126303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *errnop = ec ? ec : ENOENT; 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 1268c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasercall_builtin(struct tbl *tp, const char **wp, const char *where) 12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int rv; 12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1272c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!tp) 1273c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser internal_errorf("%s: %s", where, wp[0]); 12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru builtin_argv0 = wp[0]; 12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru builtin_flag = tp->flag; 12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_reopen(1, SHF_WR, shl_stdout); 127703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = true; 12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_getopt_reset(&builtin_opt, GF_ERROR); 12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = (*tp->val.f)(wp); 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_flush(shl_stdout); 128103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shl_stdout_ok = false; 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru builtin_flag = 0; 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru builtin_argv0 = NULL; 12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * set up redirection, saving old fds in e->savefd 12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruiosetup(struct ioword *iop, struct tbl *tp) 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int u = -1; 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp = iop->name; 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int iotype = iop->flag & IOTYPE; 1296c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool do_open = true, do_close = false; 1297c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int flags = 0; 12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct ioword iotmp; 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat statb; 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iotype != IOHERE) 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0)); 13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Used for tracing and error messages to print expanded cp */ 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iotmp = *iop; 13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iotmp.name = (iotype == IOHERE) ? NULL : cp; 13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iotmp.flag |= IONAMEXP; 13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1309811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (Flag(FXTRACE)) { 1310811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(2, false); 1311811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser fptreef(shl_xtrace, 0, "%R", &iotmp); 1312811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(1, false); 1313811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (iotype) { 13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IOREAD: 13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags = O_RDONLY; 13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IOCAT: 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags = O_WRONLY | O_APPEND | O_CREAT; 13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IOWRITE: 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags = O_WRONLY | O_CREAT | O_TRUNC; 132603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 132703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * The stat() is here to allow redirections to 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * things like /dev/null without error. 13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) && 13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode))) 13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags |= O_EXCL; 13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IORDWR: 13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags = O_RDWR | O_CREAT; 13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IOHERE: 1340c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do_open = false; 13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* herein() returns -2 if error has been printed */ 1342c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser u = herein(iop, NULL); 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* cp may have wrong name */ 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case IODUP: { 13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *emsg; 13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1349c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do_open = false; 13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*cp == '-' && !cp[1]) { 135103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* prevent error return below */ 135203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra u = 1009; 1353c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do_close = true; 13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((u = check_fd(cp, 13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK), 13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru &emsg)) < 0) { 1357811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *sp; 1358811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(true, "%s: %s", 1360811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg); 1361811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser afree(sp, ATEMP); 13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (u == iop->unit) 136503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* "dup from" == "dup to" */ 136603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (0); 13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 1368c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_open) { 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FRESTRICTED) && (flags & O_CREAT)) { 137303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s: %s", cp, "restricted"); 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1376427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes u = open(cp, flags | O_BINARY, 0666); 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (u < 0) { 13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* herein() may already have printed message */ 13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (u == -1) { 13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru u = errno; 138203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "can't %s %s: %s", 13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru iotype == IODUP ? "dup" : 13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (iotype == IOREAD || iotype == IOHERE) ? 1385c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "open" : "create", cp, cstrerror(u)); 13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Do not save if it has already been redirected (i.e. "cat >x >y"). */ 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (e->savefd[iop->unit] == 0) { 13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* If these are the same, it means unit was previously closed */ 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (u == iop->unit) 13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[iop->unit] = -1; 13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 139503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 139603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * c_exec() assumes e->savefd[fd] set for any 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * redirections. Ask savefd() not to close iop->unit; 13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * this allows error messages to be seen if iop->unit 13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is 2; also means we can't lose the fd (eg, both 14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * dup2 below and dup2 in restfd() failing). 14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru e->savefd[iop->unit] = savefd(iop->unit); 14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_close) 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(iop->unit); 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (u != iop->unit) { 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_dup2(u, iop->unit, true) < 0) { 1409c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int eno; 1410811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *sp; 14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1412c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser eno = errno; 141303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s %s %s", 141403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "can't finish (dup) redirection", 1415811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (sp = snptreef(NULL, 32, "%R", &iotmp)), 1416c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cstrerror(eno)); 1417811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser afree(sp, ATEMP); 14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iotype != IODUP) 14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(u); 14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (iotype != IODUP) 14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(u); 142403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 142503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Touching any co-process fd in an empty exec 14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * causes the shell to close its copies 14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (tp && tp->type == CSHELL && tp->val.f == c_exec) { 142903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (iop->flag & IORDUP) 143003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* possible exec <&p */ 14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc_read_close(u); 143203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 143303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* possible exec >&p */ 14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru coproc_write_close(u); 14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 143703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (u == 2) 143803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Clear any write errors */ 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_reopen(2, SHF_WR, shl_out); 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 144403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Process here documents by providing the content, either as 144503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * result (globally allocated) string or in a temp file; if 144603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * unquoted, the string is expanded first. 14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 144903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrahereinval(const char *content, int sub, char **resbuf, struct shf *shf) 145003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 1451c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char * volatile ccp = content; 145203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct source *s, *osource; 145303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 145403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra osource = source; 145503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra newenv(E_ERRH); 1456c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (kshsetjmp(e->jbuf)) { 145703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra source = osource; 145803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quitenv(shf); 145903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* special to iosetup(): don't print error */ 146003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-2); 146103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 146203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (sub) { 146303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* do substitutions on the content of heredoc */ 146403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra s = pushs(SSTRING, ATEMP); 1465c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser s->start = s->str = ccp; 146603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra source = s; 1467c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (yylex(sub) != LWORD) 146803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_errorf("%s: %s", "herein", "yylex"); 146903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra source = osource; 147003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = evalstr(yylval.cp, 0); 1471c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 147203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 147303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (resbuf == NULL) 147403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_puts(ccp, shf); 147503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 147603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(*resbuf, ccp, APERM); 147703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 147803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra quitenv(NULL); 147903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (0); 148003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 148103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 148203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 1483c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserherein(struct ioword *iop, char **resbuf) 14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 148503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int fd = -1; 148603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct shf *shf; 14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct temp *h; 14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ksh -c 'cat << EOF' can cause this... */ 1491c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (iop->heredoc == NULL) { 149203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s missing", "here document"); 149303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* special to iosetup(): don't print error */ 149403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-2); 14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1497c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* lexer substitution flags */ 1498c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0; 1499c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 150003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip all the fd setup if we just want the value */ 150103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (resbuf != NULL) 1502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (hereinval(iop->heredoc, i, resbuf, NULL)); 150303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 150403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 150503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Create temp file to hold content (done before newenv 150603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * so temp doesn't get removed too soon). 15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); 1509427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY | O_BINARY, 0)) < 0) { 151003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = errno; 15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(true, "can't %s temporary file %s: %s", 1512c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser !shf ? "create" : "open", h->tffn, cstrerror(i)); 15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf) 15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_close(shf); 151503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* special to iosetup(): don't print error */ 151603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-2); 15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1519c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hereinval(iop->heredoc, i, NULL, shf) == -2) { 15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 152103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* special to iosetup(): don't print error */ 152203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-2); 15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf_close(shf) == EOF) { 15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = errno; 15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 1528c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser warningf(true, "can't %s temporary file %s: %s", 1529c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "write", h->tffn, cstrerror(i)); 153003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* special to iosetup(): don't print error */ 153103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-2); 15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (fd); 15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ksh special - the select command processing section 15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * print the args in column form - assuming that we can 15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * 15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudo_selectargs(const char **ap, bool print_menu) 15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru static const char *read_args[] = { 15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "read", "-r", "REPLY", NULL 15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru }; 15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s; 15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i, argct; 15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (argct = 0; ap[argct]; argct++) 15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 155203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (/* CONSTCOND */ 1) { 155303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 155403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Menu is printed if 15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - this is the first time around the select loop 15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the user enters a blank line 15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the REPLY parameter is empty 15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (print_menu || !*str_val(global("REPLY"))) 15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pr_menu(ap); 15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shellf("%s", str_val(global("PS3"))); 1562c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (call_builtin(findcom("read", FC_BI), read_args, Tselect)) 15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = str_val(global("REPLY")); 1565811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (*s && getn(s, &i)) 15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((i >= 1 && i <= argct) ? ap[i - 1] : null); 1567c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser print_menu = true; 15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct select_menu_info { 15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char * const *args; 15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int num_width; 15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* format a single select menu item */ 15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 1578c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserselect_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) 15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct select_menu_info *smi = 15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (const struct select_menu_info *)arg; 15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1583c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_snprintf(buf, buflen, "%*u) %s", 15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru smi->num_width, i + 1, smi->args[i]); 15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (buf); 15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * print a select style menu 15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1591c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupr_menu(const char * const *ap) 15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct select_menu_info smi; 15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char * const *pp; 159603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t acols = 0, aocts = 0, i; 1597c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned int n; 15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * width/column calculations were done once and saved, but this 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * means select can't be used recursively so we re-calculate 16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * each time (could save in a structure that is returned, but 16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it's probably not worth the bother) 16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * get dimensions of the list 16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (n = 0, pp = ap; *pp; n++, pp++) { 16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = strlen(*pp); 16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i > aocts) 16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru aocts = i; 16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = utf_mbswidth(*pp); 16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i > acols) 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru acols = i; 16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * we will print an index of the form "%d) " in front of 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * each entry, so get the maximum width of this 16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = n, smi.num_width = 1; i >= 10; i /= 10) 16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru smi.num_width++; 16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru smi.args = ap; 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru print_columns(shl_out, n, select_fmt_entry, (void *)&smi, 16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru smi.num_width + 2 + aocts, smi.num_width + 2 + acols, 16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru true); 16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 1632c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserplain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) 16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 163403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strlcpy(buf, ((const char * const *)arg)[i], buflen); 16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (buf); 16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1638c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querupr_list(char * const *ap) 16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 164103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t acols = 0, aocts = 0, i; 1642c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned int n; 16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char * const *pp; 16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (n = 0, pp = ap; *pp; n++, pp++) { 16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = strlen(*pp); 16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i > aocts) 16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru aocts = i; 16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = utf_mbswidth(*pp); 16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i > acols) 16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru acols = i; 16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru print_columns(shl_out, n, plain_fmt_entry, (const void *)ap, 16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru aocts, acols, false); 16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * [[ ... ]] evaluation routines 16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Test if the current token is a whatever. Accepts the current token if 16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it is. Returns 0 if it is not, non-zero if it is (in the case of 16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * TM_UNOP and TM_BINOP, the returned value is a Test_op). 16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op 16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbteste_isa(Test_env *te, Test_meta meta) 16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Test_op ret = TO_NONOP; 1671427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes bool uqword; 16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p; 16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*te->pos.wp) 16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (meta == TM_END ? TO_NONNULL : TO_NONOP); 16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* unquoted word? */ 16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = *te->pos.wp; *p == CHAR; p += 2) 16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru uqword = *p == EOS; 16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (meta == TM_UNOP || meta == TM_BINOP) { 16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (uqword) { 168403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* longer than the longest operator */ 168503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char buf[8]; 16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *q = buf; 168703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1688c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = *te->pos.wp; 1689c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while (*p++ == CHAR && 1690c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (size_t)(q - buf) < sizeof(buf) - 1) 1691c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *q++ = *p++; 16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q = '\0'; 16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = test_isop(meta, buf); 16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (meta == TM_END) 16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = TO_NONOP; 16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 16985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = (uqword && !strcmp(*te->pos.wp, 16995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP; 17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Accept the token? */ 17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ret != TO_NONOP) 17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te->pos.wp++; 17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char * 17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbteste_getopnd(Test_env *te, Test_op op, bool do_eval) 17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *s = *te->pos.wp; 17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!s) 17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te->pos.wp++; 17175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!do_eval) 17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (null); 17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (op == TO_STEQL || op == TO_STNEQ) 17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = evalstr(s, DOTILDE | DOPAT); 17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 17245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = evalstr(s, DOTILDE); 17255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (s); 17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudbteste_error(Test_env *te, int offset, const char *msg) 17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru te->flags |= TEF_ERROR; 17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_warningf("dbteste_error: %s (offset %d)", msg, offset); 17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1735