15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: c_ksh.c,v 1.33 2009/02/07 14:03:24 kili Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: c_sh.c,v 1.41 2010/03/27 09:10:01 jmc Exp $	*/
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $	*/
45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $	*/
55155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
8c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser *		 2010, 2011, 2012, 2013
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
3003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SYS_BSDTYPES_H
3103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#include <sys/bsdtypes.h>
3203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SYS_SELECT_H
3403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#include <sys/select.h>
3503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_BSTRING_H
3703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#include <bstring.h>
3803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
4003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
41c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.238 2013/02/18 22:47:32 tg Exp $");
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_KILLPG
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * use killpg if < -1 since -1 does special things
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * for some non-killpg-endowed kills
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define mksh_kill(p,s)	((p) < -1 ? killpg(-(p), (s)) : kill((p), (s)))
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* cross fingers and hope kill is killpg-endowed */
515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define mksh_kill	kill
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* XXX conditions correct? */
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIM_INFINITY) && !defined(MKSH_NO_LIMITS)
5603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define MKSH_NO_LIMITS	1
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NO_LIMITS
6003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define c_ulimit	c_true
6103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
6203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
63c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* getn() that prints error */
64c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int
65c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserbi_getn(const char *as, int *ai)
66c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
67c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int rv;
68c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
69c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (!(rv = getn(as, ai)))
70c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", as, "bad number");
71c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (rv);
72c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int
7503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_true(const char **wp MKSH_A_UNUSED)
7603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
7703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (0);
7803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int
8103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_false(const char **wp MKSH_A_UNUSED)
8203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
8303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (1);
8403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
8503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * A leading = means assignments before command are kept;
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a leading * means a POSIX special builtin;
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a leading + means a POSIX regular builtin
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (* and + should not be combined).
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst struct builtin mkshbuiltins[] = {
935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=.", c_dot},
9403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"*=:", c_true},
955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"[", c_test},
965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=break", c_brkcont},
9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tgbuiltin, c_builtin},
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=continue", c_brkcont},
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=eval", c_eval},
1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=exec", c_exec},
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=exit", c_exitreturn},
10203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"+false", c_false},
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=return", c_exitreturn},
10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tsgset, c_set},
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=shift", c_shift},
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"=times", c_times},
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=trap", c_trap},
1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+=wait", c_wait},
1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+read", c_read},
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"test", c_test},
11103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"+true", c_true},
1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"ulimit", c_ulimit},
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+umask", c_umask},
114c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	{Tsgunset, c_unset},
11503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* no =: AT&T manual wrong */
11603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tpalias, c_alias},
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+cd", c_cd},
11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* dash compatibility hack */
11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"chdir", c_cd},
1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+command", c_command},
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"echo", c_print},
122c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	{Tsgexport, c_typeset},
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+fc", c_fc},
1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+getopts", c_getopts},
12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"=global", c_typeset},
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+jobs", c_jobs},
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+kill", c_kill},
1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"let", c_let},
1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"print", c_print},
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_PRINTF_BUILTIN
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"printf", c_printf},
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"pwd", c_pwd},
134c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	{Tsgreadonly, c_typeset},
13503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{T_typeset, c_typeset},
13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tpunalias, c_unalias},
1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"whence", c_whence},
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+bg", c_fgbg},
1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+fg", c_fgbg},
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
142c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"bind", c_bind},
144c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"cat", c_cat},
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKNOD
1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"mknod", c_mknod},
1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"realpath", c_realpath},
1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"rename", c_rename},
15103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
15203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"sleep", c_sleep},
15303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
15403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef __MirBSD__
15503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* alias to "true" for historical reasons */
15603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"domainname", c_true},
15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{NULL, (int (*)(const char **))NULL}
1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct kill_info {
1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int num_width;
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int name_width;
1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct t_op {
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char op_text[4];
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op op_num;
1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} u_ops[] = {
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-a",	TO_FILAXST },
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-b",	TO_FILBDEV },
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-c",	TO_FILCDEV },
1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-d",	TO_FILID },
1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-e",	TO_FILEXST },
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-f",	TO_FILREG },
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-G",	TO_FILGID },
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-g",	TO_FILSETG },
1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-h",	TO_FILSYM },
1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-H",	TO_FILCDF },
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-k",	TO_FILSTCK },
1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-L",	TO_FILSYM },
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-n",	TO_STNZE },
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-O",	TO_FILUID },
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-o",	TO_OPTION },
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-p",	TO_FILFIFO },
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-r",	TO_FILRD },
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-s",	TO_FILGZ },
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-S",	TO_FILSOCK },
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-t",	TO_FILTT },
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-u",	TO_FILSETU },
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-w",	TO_FILWR },
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-x",	TO_FILEX },
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-z",	TO_STZER },
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"",	TO_NONOP }
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct t_op b_ops[] = {
1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"=",	TO_STEQL },
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"==",	TO_STEQL },
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"!=",	TO_STNEQ },
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"<",	TO_STLT },
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{">",	TO_STGT },
2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-eq",	TO_INTEQ },
2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ne",	TO_INTNE },
2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-gt",	TO_INTGT },
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ge",	TO_INTGE },
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-lt",	TO_INTLT },
2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-le",	TO_INTLE },
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ef",	TO_FILEQ },
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-nt",	TO_FILNT },
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ot",	TO_FILOT },
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"",	TO_NONOP }
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_oexpr(Test_env *, bool);
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_aexpr(Test_env *, bool);
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_nexpr(Test_env *, bool);
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_primary(Test_env *, bool);
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op ptest_isa(Test_env *, Test_meta);
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *ptest_getopnd(Test_env *, Test_op, bool);
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void ptest_error(Test_env *, int, const char *);
221c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char *kill_fmt_entry(char *, size_t, unsigned int, const void *);
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void p_time(struct shf *, bool, long, int, int,
223c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser    const char *, const char *);
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_pwd(const char **wp)
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc;
22903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool physical = tobool(Flag(FPHYSICAL));
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *p, *allocd = NULL;
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != -1)
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'L':
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			physical = false;
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'P':
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			physical = true;
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[0]) {
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("too many arguments");
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p = current_wd[0] ? (physical ? allocd = do_realpath(current_wd) :
2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    current_wd) : NULL;
25103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* LINTED use of access */
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p && access(p, R_OK) < 0)
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p = NULL;
25403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!p && !(p = allocd = ksh_get_wd())) {
25503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", "can't determine current directory",
256c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    cstrerror(errno));
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shprintf("%s\n", p);
2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(allocd, ATEMP);
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *s_ptr;
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int s_get(void);
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void s_put(int);
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_print(const char **wp)
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_NL		BIT(0)	/* print newline */
2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_EXPAND	BIT(1)	/* expand backslash sequences */
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_PMINUSMINUS	BIT(2)	/* print a -- argument */
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_HIST		BIT(3)	/* print to history instead of stdout */
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_COPROC	BIT(4)	/* printing to coprocess: block SIGPIPE */
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd = 1, c;
277c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int flags = PO_EXPAND | PO_NL;
2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *s, *emsg;
2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString xs;
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp;
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[0][0] == 'e') {
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* echo builtin */
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
285c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
286c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (Flag(FSH)) {
287c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/*
288c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * MidnightBSD /bin/sh needs a BSD echo, that is,
289c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * one that supports -e but does not enable it by
290c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * default
291c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 */
292c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			flags = PO_NL;
293c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
294c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
295c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (Flag(FPOSIX) ||
296c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_MIDNIGHTBSD01ASH_COMPAT
297c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    Flag(FSH) ||
298c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
299c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    Flag(FAS_BUILTIN)) {
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* Debian Policy 10.4 compliant "echo" builtin */
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*wp && !strcmp(*wp, "-n")) {
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* we recognise "-n" only as the first arg */
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = 0;
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				wp++;
3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* otherwise, we print everything as-is */
3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = PO_NL;
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nflags = flags;
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/**
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * a compromise between sysV and BSD echo commands:
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * escape sequences are enabled by default, and -n,
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * -e and -E are recognised if they appear in argu-
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * ments with no illegal options (ie, echo -nq will
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * print -nq).
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * Different from sysV echo since options are reco-
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * gnised, different from BSD echo since escape se-
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * quences are enabled by default.
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((s = *wp) && *s == '-' && s[1]) {
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*++s)
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (*s == 'n')
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags &= ~PO_NL;
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else if (*s == 'e')
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags |= PO_EXPAND;
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else if (*s == 'E')
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags &= ~PO_EXPAND;
3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else
3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/*
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * bad option: don't use
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * nflags, print argument
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 */
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*s)
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				wp++;
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = nflags;
3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int optc;
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *opts = "Rnprsu,";
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (optc) {
34903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'R':
35003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* fake BSD echo command */
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_PMINUSMINUS;
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_EXPAND;
3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				opts = "ne";
3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'e':
3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_EXPAND;
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'n':
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_NL;
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'p':
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((fd = coproc_getfd(W_OK, &emsg)) < 0) {
36303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s", "-p", emsg);
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'r':
3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_EXPAND;
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_HIST;
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'u':
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!*(s = builtin_opt.optarg))
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					fd = 0;
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if ((fd = check_fd(s, W_OK, &emsg)) < 0) {
37703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s: %s", "-u", s, emsg);
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '?':
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(builtin_opt.info & GI_MINUSMINUS)) {
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* treat a lone - like -- */
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (wp[builtin_opt.optind] &&
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ksh_isdash(wp[builtin_opt.optind]))
3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				builtin_opt.optind++;
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (flags & PO_PMINUSMINUS)
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			builtin_opt.optind--;
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp += builtin_opt.optind;
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(xs, xp, 128, ATEMP);
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (*wp != NULL) {
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = *wp;
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = *s++) != '\0') {
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xcheck(xs, xp);
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((flags & PO_EXPAND) && c == '\\') {
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s_ptr = s;
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = unbksl(false, s_get, s_put);
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = s_ptr;
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == -1) {
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* rejected by generic function */
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch ((c = *s++)) {
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'c':
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						flags &= ~PO_NL;
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* AT&T brain damage */
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						continue;
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case '\0':
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s--;
4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = '\\';
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					default:
4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xput(xs, xp, '\\');
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if ((unsigned int)c > 0xFF) {
4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* generic function returned Unicode */
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char ts[4];
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
42303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					ts[utf_wctomb(ts, c - 0x100)] = 0;
4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (c = 0; ts[c]; ++c)
4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xput(xs, xp, ts[c]);
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, c);
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*++wp != NULL)
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, ' ');
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & PO_NL)
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, '\n');
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & PO_HIST) {
4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, '\0');
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsave(&source->line, Xstring(xs, xp), true, false);
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xfree(xs, xp);
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int len = Xlength(xs, xp);
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int opipe = 0;
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
44503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
44603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Ensure we aren't killed by a SIGPIPE while writing to
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * a coprocess. AT&T ksh doesn't seem to do this (seems
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * to just check that the co-process is alive which is
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * not enough).
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (coproc.write >= 0 && coproc.write == fd) {
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flags |= PO_COPROC;
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opipe = block_pipe();
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (s = Xstring(xs, xp); len > 0; ) {
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c = write(fd, s, len)) < 0) {
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (flags & PO_COPROC)
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					restore_pipe(opipe);
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (errno == EINTR) {
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* allow user to ^C out */
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					intrcheck();
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (flags & PO_COPROC)
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						opipe = block_pipe();
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s += c;
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			len -= c;
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (flags & PO_COPROC)
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			restore_pipe(opipe);
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_get(void)
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (*s_ptr++);
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_put(int c MKSH_A_UNUSED)
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	--s_ptr;
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_whence(const char **wp)
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tp;
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *id;
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool pflag = false, vflag = false, Vflag = false;
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, optc, fcflags;
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool iam_whence = wp[0][0] == 'w';
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts = iam_whence ? "pv" : "pvV";
4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'v':
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vflag = true;
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'V':
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Vflag = true;
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fcflags = FC_BI | FC_PATH | FC_FUNC;
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!iam_whence) {
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Note that -p on its own is deal with in comexec() */
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (pflag)
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fcflags |= FC_DEFPATH;
52103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
52203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Convert command options to whence options - note that
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * command -pV uses a different path search than whence -v
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * or whence -pv. This should be considered a feature.
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vflag = Vflag;
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (pflag)
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fcflags &= ~(FC_BI | FC_FUNC);
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((vflag || rv == 0) && (id = *wp++) != NULL) {
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h = 0;
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tp = NULL;
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((iam_whence || vflag) && !pflag)
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = ktsearch(&keywords, id, h = hash(id));
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tp && !pflag) {
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = ktsearch(&aliases, id, h ? h : hash(id));
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (tp && !(tp->flag & ISSET))
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				tp = NULL;
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tp)
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = findcom(id, fcflags);
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tp->type != CTALIAS))
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts(id, shl_stdout);
54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vflag)
54803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			switch (tp->type) {
54903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CKEYWD:
55003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CALIAS:
55103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CFUNC:
55203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CSHELL:
55303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(" is a", shl_stdout);
55403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
55503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
55603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (tp->type) {
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CKEYWD:
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
56003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(" reserved word", shl_stdout);
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CALIAS:
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("n %s%s for ",
56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    (tp->flag & EXPORT) ? "exported " : null,
56603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    Talias);
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!iam_whence && !vflag)
56803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s=", Talias, id);
569c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			print_value_quoted(shl_stdout, tp->val.s);
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CFUNC:
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag) {
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (tp->flag & EXPORT)
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts("n exported", shl_stdout);
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (tp->flag & TRACE)
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" traced", shl_stdout);
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!(tp->flag & ISSET)) {
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" undefined", shl_stdout);
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (tp->u.fpath)
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shprintf(" (autoload from %s)",
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    tp->u.fpath);
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
58303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(T_function, shl_stdout);
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSHELL:
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
58803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s %s",
58903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    (tp->flag & SPEC_BI) ? " special" : null,
59003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "shell", Tbuiltin);
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CTALIAS:
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CEXEC:
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (tp->flag & ISSET) {
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (vflag) {
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" is ", shl_stdout);
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (tp->type == CTALIAS)
59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shprintf("a tracked %s%s for ",
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    (tp->flag & EXPORT) ?
60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    "exported " : null,
60103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    Talias);
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(tp->val.s, shl_stdout);
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (vflag)
60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf(" %s\n", "not found");
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%s is *GOK*", id);
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vflag || !rv)
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_putc('\n', shl_stdout);
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Deal with command -vV - command -p dealt with in comexec() */
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_command(const char **wp)
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
62403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
62503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Let c_whence do the work. Note that c_command() must be
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * a distinct function from c_whence() (tested in comexec()).
6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (c_whence(wp));
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
63103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* typeset, global, export, and readonly */
632c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void c_typeset_vardump(struct tbl *, uint32_t, int, bool, bool);
633c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,
634c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser    bool);
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_typeset(const char **wp)
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp, **p;
63903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	uint32_t fset = 0, fclr = 0, flag;
640c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int thing = 0, field = 0, base = 0, i;
641c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct block *l;
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts;
643c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	const char *fieldstr = NULL, *basestr = NULL;
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool localv = false, func = false, pflag = false, istset = true;
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (**wp) {
64703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
64803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* export */
64903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'e':
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fset |= EXPORT;
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		istset = false;
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
65303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
65403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* readonly */
65503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'r':
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fset |= RDONLY;
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		istset = false;
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
65903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
66003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* set */
66103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 's':
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* called with 'typeset -' */
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
66403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
66503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* typeset */
66603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 't':
6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		localv = true;
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* see comment below regarding possible opions */
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opts = istset ? "L#R#UZ#afi#lnprtux" : "p";
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	builtin_opt.flags |= GF_PLUSOPT;
67503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
67603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * AT&T ksh seems to have 0-9 as options which are multiplied
6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * to get a number that is used with -L, -R, -Z or -i (eg, -1R2
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * sets right justify in a field of 12). This allows options
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * does not allow the number to be specified as a separate argument
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Here, the number must follow the RLZi option, but is optional
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * (see the # kludge in ksh_getopt()).
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
684c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while ((i = ksh_getopt(wp, &builtin_opt, opts)) != -1) {
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		flag = 0;
686c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		switch (i) {
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'L':
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = LJUST;
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'R':
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = RJUST;
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'U':
69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
69703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * AT&T ksh uses u, but this conflicts with
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * upper/lower case. If this option is changed,
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * need to change the -U below as well
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = INT_U;
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'Z':
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = ZEROFIL;
7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * this is supposed to set (-a) or unset (+a) the
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * indexed array attribute; it does nothing on an
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * existing regular string or indexed array though
7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'f':
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			func = true;
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'i':
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = INTEGER;
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			basestr = builtin_opt.optarg;
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = LCASEV;
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'n':
72503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			set_refflag = (builtin_opt.info & GI_PLUS) ?
72603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    SRF_DISABLE : SRF_ENABLE;
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
72803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* export, readonly: POSIX -p flag */
7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* typeset: show values as well */
7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (istset)
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'r':
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = RDONLY;
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = TRACE;
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'u':
74203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* upper case / autoload */
74303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			flag = UCASEV_AL;
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'x':
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = EXPORT;
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
749c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errout:
750c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			set_refflag = SRF_NOP;
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (builtin_opt.info & GI_PLUS) {
7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr |= flag;
7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~flag;
7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			thing = '+';
7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= flag;
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr &= ~flag;
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			thing = '-';
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fieldstr && !bi_getn(fieldstr, &field))
765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto errout;
766c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (basestr && (!bi_getn(basestr, &base) || base < 1 || base > 36)) {
767c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", "bad integer base", basestr);
768c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto errout;
769c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (wp[builtin_opt.optind][0] == '-' ||
7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    wp[builtin_opt.optind][0] == '+') &&
7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    wp[builtin_opt.optind][1] == '\0') {
7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		thing = wp[builtin_opt.optind][0];
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		builtin_opt.optind++;
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
77903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
78003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    set_refflag != SRF_NOP)) {
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("only -t, -u and -x options may be used with -f");
782c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto errout;
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind]) {
78503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
78603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Take care of exclusions.
7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * At this point, flags in fset are cleared in fclr and vice
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * versa. This property should be preserved.
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
79003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fset & LCASEV)
79103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* LCASEV has priority over UCASEV_AL */
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~UCASEV_AL;
79303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fset & LJUST)
79403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* LJUST has priority over RJUST */
7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~RJUST;
79603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) {
79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* -Z implies -ZR */
7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= RJUST;
7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr &= ~RJUST;
8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
80103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Setting these attributes clears the others, unless they
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * are also set in this command
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
80603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    INTEGER | INT_U | INT_L)) || set_refflag != SRF_NOP)
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    LCASEV | INTEGER | INT_U | INT_L);
8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set variables and attributes */
812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (wp[builtin_opt.optind] &&
813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    /* not "typeset -p varname" */
814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    !(!func && pflag && !(fset | fclr))) {
815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		int rv = 0;
8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *f;
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (localv && !func)
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= LOCAL;
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = builtin_opt.optind; wp[i]; i++) {
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (func) {
8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				f = findfunc(wp[i], hash(wp[i]),
82303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    tobool(fset & UCASEV_AL));
8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!f) {
8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* AT&T ksh does ++rv: bogus */
8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					rv = 1;
8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (fset | fclr) {
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					f->flag |= fset;
8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					f->flag &= ~fclr;
83203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				} else {
83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					fpFUNCTf(shl_stdout, 0,
83403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    tobool(f->flag & FKSH),
83503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    wp[i], f->val.t);
83603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\n', shl_stdout);
83703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (!typeset(wp[i], fset, fclr, field, base)) {
83903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", wp[i], "not identifier");
840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				goto errout;
8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
84303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		set_refflag = SRF_NOP;
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (rv);
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	set_refflag = SRF_NOP;
8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* list variables and attributes */
84903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
85003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* no difference at this point.. */
85103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	flag = fset | fclr;
8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (func) {
8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (l = e->loc; l; l = l->next) {
8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (p = ktsort(&l->funs); (vp = *p++); ) {
8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (flag && (vp->flag & flag) == 0)
8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (thing == '-')
85803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					fpFUNCTf(shl_stdout, 0,
85903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    tobool(vp->flag & FKSH),
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    vp->name, vp->val.t);
8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
86203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_puts(vp->name, shl_stdout);
86303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shl_stdout);
8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
866c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else if (wp[builtin_opt.optind]) {
867c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		for (i = builtin_opt.optind; wp[i]; i++) {
868c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			varsearch(e->loc, &vp, wp[i], hash(wp[i]));
869c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			c_typeset_vardump(vp, flag, thing, pflag, istset);
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
871c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} else
872c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		c_typeset_vardump_recursive(e->loc, flag, thing, pflag, istset);
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void
877c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserc_typeset_vardump_recursive(struct block *l, uint32_t flag, int thing,
878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser    bool pflag, bool istset)
879c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
880c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct tbl **blockvars, *vp;
881c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
882c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (l->next)
883c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		c_typeset_vardump_recursive(l->next, flag, thing, pflag, istset);
884c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	blockvars = ktsort(&l->vars);
885c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	while ((vp = *blockvars++))
886c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		c_typeset_vardump(vp, flag, thing, pflag, istset);
887c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/*XXX doesn’t this leak? */
888c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
889c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
890c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void
891c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserc_typeset_vardump(struct tbl *vp, uint32_t flag, int thing, bool pflag,
892c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser    bool istset)
893c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{
894c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	struct tbl *tvp;
895c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int any_set = 0;
896c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	char *s;
897c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
898c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (!vp)
899c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return;
900c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
901c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/*
902c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * See if the parameter is set (for arrays, if any
903c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * element is set).
904c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 */
905c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	for (tvp = vp; tvp; tvp = tvp->u.array)
906c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (tvp->flag & ISSET) {
907c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			any_set = 1;
908c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			break;
909c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
910c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
911c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/*
912c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * Check attributes - note that all array elements
913c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * have (should have?) the same attributes, so checking
914c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * the first is sufficient.
915c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 *
916c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * Report an unset param only if the user has
917c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * explicitly given it some attribute (like export);
918c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * otherwise, after "echo $FOO", we would report FOO...
919c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 */
920c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (!any_set && !(vp->flag & USERATTRIB))
921c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return;
922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (flag && (vp->flag & flag) == 0)
923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return;
924c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (!(vp->flag & ARRAY))
925c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* optimise later conditionals */
926c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		any_set = 0;
927c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	do {
928c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/*
929c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * Ignore array elements that aren't set unless there
930c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * are no set elements, in which case the first is
931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * reported on
932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 */
933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (any_set && !(vp->flag & ISSET))
934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			continue;
935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* no arguments */
936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!thing && !flag) {
937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (any_set == 1) {
938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s %s %s\n", Tset, "-A", vp->name);
939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				any_set = 2;
940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			}
941c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/*
942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * AT&T ksh prints things like export, integer,
943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * leftadj, zerofill, etc., but POSIX says must
944c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 * be suitable for re-entry...
945c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			 */
946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shprintf("%s %s", Ttypeset, "");
947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (((vp->flag & (ARRAY | ASSOC)) == ASSOC))
948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-n");
949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & INTEGER))
950c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-i");
951c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & EXPORT))
952c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-x");
953c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & RDONLY))
954c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-r");
955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & TRACE))
956c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-t");
957c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & LJUST))
958c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("-L%d ", vp->u2.field);
959c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & RJUST))
960c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("-R%d ", vp->u2.field);
961c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & ZEROFIL))
962c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-Z");
963c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & LCASEV))
964c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-l");
965c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & UCASEV_AL))
966c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-u");
967c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & INT_U))
968c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shprintf("%s ", "-U");
969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		} else if (pflag) {
970c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shprintf("%s %s", istset ? Ttypeset :
971c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			    (flag & EXPORT) ? Texport : Treadonly, "");
972c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
973c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (any_set)
974c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shprintf("%s[%lu]", vp->name, arrayindex(vp));
975c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		else
976c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_puts(vp->name, shl_stdout);
977c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if ((!thing && !flag && pflag) ||
978c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    (thing == '-' && (vp->flag & ISSET))) {
979c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			s = str_val(vp);
980c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			shf_putc('=', shl_stdout);
981c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* AT&T ksh can't have justified integers... */
982c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if ((vp->flag & (INTEGER | LJUST | RJUST)) == INTEGER)
983c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				shf_puts(s, shl_stdout);
984c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			else
985c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				print_value_quoted(shl_stdout, s);
986c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
987c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		shf_putc('\n', shl_stdout);
988c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
989c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/*
990c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * Only report first 'element' of an array with
991c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 * no set elements.
992c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		 */
993c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!any_set)
994c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			return;
995c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	} while ((vp = vp->u.array));
996c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser}
997c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_alias(const char **wp)
10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct table *t = &aliases;
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, prefix = 0;
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool rflag = false, tflag, Uflag = false, pflag = false;
100403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	uint32_t xflag = 0;
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc;
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	builtin_opt.flags |= GF_PLUSOPT;
10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "dprtUx")) != -1) {
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prefix = builtin_opt.info & GI_PLUS ? '+' : '-';
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'd':
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = NULL;	/* fix "alias -dt" */
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &homedirs;
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'r':
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rflag = true;
10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &taliases;
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'U':
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * kludge for tracked alias initialization
10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * (don't do a path search, just make an entry)
10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Uflag = true;
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'x':
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xflag = EXPORT;
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(builtin_opt.info & GI_MINUSMINUS) && *wp &&
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (wp[0][0] == '-' || wp[0][0] == '+') && wp[0][1] == '\0') {
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prefix = wp[0][0];
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tflag = t == &taliases;
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* "hash -r" means reset all the tracked aliases.. */
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rflag) {
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		static const char *args[] = {
105803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Tunalias, "-ta", NULL
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		};
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tflag || *wp) {
106203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shprintf("%s: -r flag can only be used with -t"
106303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    " and without arguments\n", Talias);
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_getopt_reset(&builtin_opt, GF_ERROR);
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c_unalias(args));
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *ap, **p;
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (p = ktsort(t); (ap = *p++) != NULL; )
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((ap->flag & (ISSET|xflag)) == (ISSET|xflag)) {
10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (pflag)
107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf("%s ", Talias);
10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(ap->name, shl_stdout);
10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (prefix != '+') {
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putc('=', shl_stdout);
1080c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					print_value_quoted(shl_stdout, ap->val.s);
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_putc('\n', shl_stdout);
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *alias = *wp, *val, *newval;
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *xalias = NULL;
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *ap;
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h;
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((val = cstrchr(alias, '='))) {
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strndupx(xalias, alias, val++ - alias, ATEMP);
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			alias = xalias;
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		h = hash(alias);
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (val == NULL && !tflag && !xflag) {
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap = ktsearch(t, alias, h);
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap != NULL && (ap->flag&ISSET)) {
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (pflag)
110103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf("%s ", Talias);
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(ap->name, shl_stdout);
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (prefix != '+') {
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putc('=', shl_stdout);
1105c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					print_value_quoted(shl_stdout, ap->val.s);
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_putc('\n', shl_stdout);
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
110903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s %s\n", alias, Talias,
111003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "not found");
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap = ktenter(t, alias, h);
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->type = tflag ? CTALIAS : CALIAS;
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Are we setting the value or just some flags? */
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((val && !tflag) || (!val && tflag && !Uflag)) {
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap->flag&ALLOC) {
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~(ALLOC|ISSET);
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(ap->val.s, APERM);
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* ignore values for -t (AT&T ksh does this) */
112403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			newval = tflag ?
112503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    search_path(alias, path, X_OK, NULL) :
112603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    val;
11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (newval) {
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(ap->val.s, newval, APERM);
11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag |= ALLOC|ISSET;
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~ISSET;
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->flag |= DEFINED;
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (prefix == '+')
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~xflag;
11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag |= xflag;
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(xalias, ATEMP);
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_unalias(const char **wp)
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct table *t = &aliases;
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *ap;
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, rv = 0;
11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool all = false;
11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "adt")) != -1)
11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			all = true;
11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'd':
11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
115903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* fix "unalias -dt" */
116003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			t = NULL;
11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &homedirs;
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &taliases;
11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap = ktsearch(t, *wp, hash(*wp));
11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ap == NULL) {
118003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* POSIX */
118103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ap->flag&ALLOC) {
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~(ALLOC|ISSET);
11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(ap->val.s, APERM);
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->flag &= ~(DEFINED|ISSET|EXPORT);
11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (all) {
11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tstate ts;
11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (ktwalk(&ts, t); (ap = ktnext(&ts)); ) {
11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap->flag&ALLOC) {
11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~(ALLOC|ISSET);
11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(ap->val.s, APERM);
11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~(DEFINED|ISSET|EXPORT);
12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_let(const char **wp)
12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t val;
12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
121203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[1] == NULL)
121303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* AT&T ksh does this */
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("no arguments");
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (wp++; *wp; wp++)
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!evaluate(*wp, &val, KSH_RETURN_ERROR, true)) {
121803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* distinguish error from zero result */
121903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 2;
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = val == 0;
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_jobs(const char **wp)
12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, flag = 0, nflag = 0, rv = 0;
12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "lpnz")) != -1)
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = 1;
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = 2;
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'n':
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nflag = 1;
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
124203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 'z':
124303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* debugging: print zombies */
12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nflag = -1;
12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!*wp) {
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (j_jobs(NULL, flag, nflag))
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (j_jobs(*wp, flag, nflag))
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED
12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_fgbg(const char **wp)
12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool bg = strcmp(*wp, "bg") == 0;
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0;
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!Flag(FMONITOR)) {
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("job control not enabled");
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp)
12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = j_resume(*wp, bg);
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = j_resume("%%", bg);
12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (bg ? 0 : rv);
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* format a single kill item */
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *
1286c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserkill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct kill_info *ki = (const struct kill_info *)arg;
12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	i++;
1291c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	shf_snprintf(buf, buflen, "%*u %*s %s",
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ki->num_width, i,
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ki->name_width, sigtraps[i].name,
12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    sigtraps[i].mess);
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (buf);
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_kill(const char **wp)
13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *t = NULL;
13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p;
13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool lflag = false;
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, n, rv, sig;
13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* assume old style options if -digits or -UPPERCASE */
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p = wp[1]) && *p == '-' && (ksh_isdigit(p[1]) ||
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ksh_isupper(p[1]))) {
1309c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!(t = gettrap(p + 1, false))) {
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("bad signal '%s'", p + 1);
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = (wp[2] && strcmp(wp[2], "--") == 0) ? 3 : 2;
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int optc;
13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((optc = ksh_getopt(wp, &builtin_opt, "ls:")) != -1)
13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (optc) {
13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'l':
13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				lflag = true;
13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!(t = gettrap(builtin_opt.optarg, true))) {
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					bi_errorf("bad signal '%s'",
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    builtin_opt.optarg);
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '?':
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = builtin_opt.optind;
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((lflag && t) || (!wp[i] && !lflag)) {
13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("usage:\tkill [-s signame | -signum | -signame]"
13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    " { job | pid | pgrp } ...\n"
13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    "\tkill -l [exit_status ...]\n", shl_out);
13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorfz();
13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (lflag) {
13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (wp[i]) {
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (; wp[i]; i++) {
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!bi_getn(wp[i], &n))
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (n > 128 && n < 128 + NSIG)
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					n -= 128;
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (n > 0 && n < NSIG)
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shprintf("%s\n", sigtraps[n].name);
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shprintf("%d\n", n);
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
135703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ssize_t w, mess_cols, mess_octs;
135803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			int j;
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct kill_info ki;
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10)
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ki.num_width++;
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ki.name_width = mess_cols = mess_octs = 0;
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (j = 0; j < NSIG; j++) {
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = strlen(sigtraps[j].name);
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > ki.name_width)
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ki.name_width = w;
13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = strlen(sigtraps[j].mess);
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > mess_octs)
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					mess_octs = w;
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = utf_mbswidth(sigtraps[j].mess);
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > mess_cols)
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					mess_cols = w;
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1376c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			print_columns(shl_stdout, (unsigned int)(NSIG - 1),
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    kill_fmt_entry, (void *)&ki,
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ki.num_width + 1 + ki.name_width + 1 + mess_octs,
13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ki.num_width + 1 + ki.name_width + 1 + mess_cols,
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    true);
13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = 0;
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sig = t ? t->signal : SIGTERM;
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; (p = wp[i]); i++) {
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*p == '%') {
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (j_kill(p, sig))
13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (!getn(p, &n)) {
139103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", p,
139203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "arguments must be jobs or process IDs");
13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (mksh_kill(n, sig) < 0) {
1396c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				bi_errorf("%s: %s", p, cstrerror(errno));
13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetopts_reset(int val)
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val >= 1) {
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_getopt_reset(&user_opt, GF_NONAME | GF_PLUSOPT);
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		user_opt.optind = user_opt.uoptind = val;
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_getopts(const char **wp)
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, optc, rv;
14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts, *var;
14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char buf[3];
14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vq, *voptarg;
14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opts = *wp++;
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!opts) {
142703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("missing %s argument", "options");
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	var = *wp++;
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!var) {
143303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("missing %s argument", "name");
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!*var || *skip_varname(var, true)) {
143703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", var, "is not an identifier");
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (e->loc->next == NULL) {
144203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		internal_warningf("%s: %s", "c_getopts", "no argv");
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Which arguments are we parsing... */
14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL)
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp = e->loc->next->argv;
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*--wp = e->loc->next->argv[0];
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Check that our saved state won't cause a core dump... */
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; wp[argc]; argc++)
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (user_opt.optind > argc ||
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (user_opt.p != 0 &&
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    user_opt.p > strlen(wp[user_opt.optind - 1]))) {
14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("arguments changed since last call");
14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	user_opt.optarg = NULL;
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	optc = ksh_getopt(wp, &user_opt, opts);
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (optc >= 0 && optc != '?' && (user_opt.info & GI_PLUS)) {
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[0] = '+';
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[1] = optc;
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[2] = '\0';
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
146903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
147003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * POSIX says var is set to ? at end-of-options, AT&T ksh
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * sets it to null - we go with POSIX...
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[0] = optc < 0 ? '?' : optc;
14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[1] = '\0';
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* AT&T ksh93 in fact does change OPTIND for unknown options too */
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	user_opt.uoptind = user_opt.optind;
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	voptarg = global("OPTARG");
148103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* AT&T ksh clears ro and int */
148203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	voptarg->flag &= ~RDONLY;
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Paranoia: ensure no bizarre results. */
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (voptarg->flag & INTEGER)
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    typeset("OPTARG", 0, INTEGER, 0, 0);
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (user_opt.optarg == NULL)
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unset(voptarg, 1);
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* This can't fail (have cleared readonly/integer) */
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setstr(voptarg, user_opt.optarg, KSH_RETURN_ERROR);
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = 0;
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq = global(var);
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Error message already printed (integer, readonly) */
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!setstr(vq, buf, KSH_RETURN_ERROR))
149703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rv = 2;
14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Flag(FEXPORT))
14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		typeset(var, EXPORT, 0, 0, 0);
15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (optc < 0 ? 1 : rv);
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_bind(const char **wp)
15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, rv = 0;
15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool macro = false;
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool list = false;
15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *cp;
15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *up;
15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt,
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    "lm"
15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    "l"
15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    )) != -1)
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			list = true;
15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'm':
15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			macro = true;
15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
153703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (*wp == NULL)
153803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* list all */
15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = x_bind(NULL, NULL,
15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    false,
15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    list);
15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cp = cstrchr(*wp, '=')) == NULL)
15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			up = NULL;
15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else {
15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(up, *wp, ATEMP);
15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			up[cp++ - *wp] = '\0';
15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (x_bind(up ? up : *wp, cp,
15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    macro,
15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    false))
15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(up, ATEMP);
15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1563c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_shift(const char **wp)
15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n;
15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t val;
15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (arg) {
15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		evaluate(arg, &val, KSH_UNWIND_ERROR, false);
15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = val;
15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = 1;
15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (n < 0) {
158303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", arg, "bad number");
15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (l->argc < n) {
15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("nothing to shift");
15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argv[n] = l->argv[0];
15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argv += n;
15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argc -= n;
15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_umask(const char **wp)
15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, optc;
16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *cp;
16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool symbolic = false;
16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode_t old_umask;
16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != -1)
16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'S':
16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			symbolic = true;
16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cp = wp[builtin_opt.optind];
16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (cp == NULL) {
16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_umask = umask((mode_t)0);
16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(old_umask);
16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (symbolic) {
16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char buf[18], *p;
16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int j;
16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = ~old_umask;
16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p = buf;
16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (i = 0; i < 3; i++) {
16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = "ugo"[i];
16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = '=';
16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				for (j = 0; j < 3; j++)
16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (old_umask & (1 << (8 - (3*i + j))))
16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*p++ = "rwx"[j];
16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = ',';
16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p[-1] = '\0';
16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%s\n", buf);
16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%#3.3o\n", (unsigned int)old_umask);
16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mode_t new_umask;
16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ksh_isdigit(*cp)) {
16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_umask = new_umask * 8 + (*cp - '0');
16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*cp) {
16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("bad number");
16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* symbolic format */
16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int positions, new_val;
16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char op;
16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = umask((mode_t)0);
165003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* in case of error */
165103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			umask(old_umask);
16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = ~old_umask;
16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			new_umask = old_umask;
16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			positions = 0;
16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*cp) {
16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*cp && vstrchr("augo", *cp))
16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch (*cp++) {
16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'a':
16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0111;
16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'u':
16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0100;
16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'g':
16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0010;
16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'o':
16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0001;
16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!positions)
167203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* default is a */
167303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					positions = 0111;
16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!vstrchr("=+-", op = *cp))
16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				cp++;
16775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_val = 0;
16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*cp && vstrchr("rwxugoXs", *cp))
16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch (*cp++) {
16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'r': new_val |= 04; break;
16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'w': new_val |= 02; break;
16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'x': new_val |= 01; break;
16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'u':
16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 6;
16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'g':
16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 3;
16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'o':
16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 0;
16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'X':
16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (old_umask & 0111)
16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							new_val |= 01;
16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 's':
16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* ignored */
16985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_val = (new_val & 07) * positions;
17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (op) {
17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '-':
17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask &= ~new_val;
17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '=':
17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask = new_val |
17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    (new_umask & ~(positions * 07));
17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '+':
17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask |= new_val;
17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*cp == ',') {
17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					positions = 0;
17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					cp++;
17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (!vstrchr("=+-", *cp))
17165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
17175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*cp) {
17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("bad mask");
17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			new_umask = ~new_umask;
17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
17245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(new_umask);
17255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_dot(const char **wp)
17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *file, *cp, **argv;
17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, i, errcode;
17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((cp = wp[builtin_opt.optind]) == NULL) {
17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("missing argument");
17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
174203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((file = search_path(cp, path, R_OK, &errcode)) == NULL) {
1743c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", cp, cstrerror(errcode));
17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Set positional parameters? */
17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind + 1]) {
17495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argv = wp + builtin_opt.optind;
175003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* preserve $0 */
175103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		argv[0] = e->loc->argv[0];
17525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (argc = 0; argv[argc + 1]; argc++)
17535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
17555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argc = 0;
17565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argv = NULL;
17575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1758c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((i = include(file, argc, argv, false)) < 0) {
17595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* should not happen */
1760c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", cp, cstrerror(errno));
17615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (i);
17645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_wait(const char **wp)
17685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, sig;
17705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
17725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
17745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
17755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (waitfor(NULL, &sig) >= 0)
17765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
17775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = sig;
17785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
17795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
17805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = waitfor(*wp, &sig);
17815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (rv < 0)
178203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* magic exit code: bad job-id */
178303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = sig ? sig : 127;
17845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
17865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1788c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char REPLY[] = "REPLY";
17895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_read(const char **wp)
17915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
179203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define is_ifsws(c) (ctype((c), C_IFS) && ctype((c), C_IFSWS))
179303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c, fd = 0, rv = 0, lastparm = 0;
179403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool savehist = false, intoarray = false, aschars = false;
179503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool rawmode = false, expanding = false;
179603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
179703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char delim = '\n';
179803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t bytesleft = 128, bytesread;
179903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct tbl *vp /* FU gcc */ = NULL, *vq;
180003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp, *allocd = NULL, *xp;
180103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *ccp;
180203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	XString xs;
180303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ptrdiff_t xsave = 0;
1804c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_ttyst tios;
180503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool restore_tios = false;
180603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool hastimeout = false;
180803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct timeval tv, tvlim;
180903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define c_read_opts "Aad:N:n:prst:u,"
181003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
181103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define c_read_opts "Aad:N:n:prsu,"
181203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
18135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
181403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((c = ksh_getopt(wp, &builtin_opt, c_read_opts)) != -1)
181503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (c) {
181603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'a':
181703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		aschars = true;
181803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* FALLTHROUGH */
181903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'A':
182003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		intoarray = true;
182103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
182203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'd':
182303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		delim = builtin_opt.optarg[0];
182403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
182503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'N':
182603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'n':
182703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		readmode = c == 'N' ? BYTES : UPTO;
182803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!bi_getn(builtin_opt.optarg, &c))
182903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
183003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (c == -1) {
183103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			readmode = READALL;
183203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bytesleft = 1024;
183303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
183403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bytesleft = (unsigned int)c;
183503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
183603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'p':
183703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((fd = coproc_getfd(R_OK, &ccp)) < 0) {
183803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", "-p", ccp);
183903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
18405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
184103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
184203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'r':
184303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rawmode = true;
184403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
184503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 's':
184603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		savehist = true;
184703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
184803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
184903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 't':
185003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (parse_usec(builtin_opt.optarg, &tv)) {
1851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			bi_errorf("%s: %s '%s'", Tsynerr, cstrerror(errno),
185203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    builtin_opt.optarg);
185303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
185403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
185503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hastimeout = true;
185603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
185703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
185803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'u':
185903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!builtin_opt.optarg[0])
186003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fd = 0;
186103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		else if ((fd = check_fd(builtin_opt.optarg, R_OK, &ccp)) < 0) {
186203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s: %s", "-u", builtin_opt.optarg, ccp);
186303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
186403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
186503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
186603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case '?':
186703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (2);
186803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
18695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
18705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL)
18715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*--wp = REPLY;
18725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
187303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray && wp[1] != NULL) {
187403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("too many arguments");
187503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (2);
187603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
18775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
187803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((ccp = cstrchr(*wp, '?')) != NULL) {
187903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		strdupx(allocd, *wp, ATEMP);
188003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		allocd[ccp - *wp] = '\0';
188103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		*wp = allocd;
18825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (isatty(fd)) {
188303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
188403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * AT&T ksh says it prints prompt on fd if it's open
18855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * for writing and is a tty, but it doesn't do it
18865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * (it also doesn't check the interactive flag,
188703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * as is indicated in the Korn Shell book).
18885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
188903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(ccp + 1, shl_out);
189003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_flush(shl_out);
18915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
18925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
18935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
189403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xinit(xs, xp, bytesleft, ATEMP);
18955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
189603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (readmode == LINES)
189703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bytesleft = 1;
189803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (isatty(fd)) {
189903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		x_mkraw(fd, &tios, true);
190003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		restore_tios = true;
190103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
19025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
190303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
190403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hastimeout) {
1905c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_TIME(tvlim);
190603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		timeradd(&tvlim, &tv, &tvlim);
190703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
190803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
190903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
191003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_readloop:
191103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
191203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hastimeout) {
191303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fd_set fdset;
191403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
191503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		FD_ZERO(&fdset);
1916c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		FD_SET((unsigned int)fd, &fdset);
1917c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_TIME(tv);
191803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		timersub(&tvlim, &tv, &tv);
191903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (tv.tv_sec < 0) {
192003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* timeout expired globally */
192103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
192203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
192303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
192403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
192503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (select(fd + 1, &fdset, NULL, NULL, &tv)) {
192603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 1:
192703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
192803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 0:
192903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* timeout expired for this call */
193003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
193103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
193203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
1933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			bi_errorf("%s: %s", Tselect, cstrerror(errno));
193403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
193503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
193603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
193703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
193803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
193903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
194003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bytesread = blocking_read(fd, xp, bytesleft);
194103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (bytesread == (size_t)-1) {
194203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* interrupted */
194303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (errno == EINTR && fatal_trap_check()) {
194403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
194503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * Was the offending signal one that would
194603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * normally kill a process? If so, pretend
194703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * the read was killed.
194803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 */
194903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
195003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
195103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
195203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* just ignore the signal */
195303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_readloop;
195403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
195503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
195603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (readmode) {
195703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case READALL:
195803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
195903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
196003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
196103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
196203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
196303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
196403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		XcheckN(xs, xp, bytesleft);
196503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
196603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
196703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case UPTO:
196803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0)
196903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
197003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
197103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
197203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_readdone;
197303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
197403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case BYTES:
197503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
197603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
197703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
197803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp = Xstring(xs, xp);
197903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
198003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
198103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
198203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((bytesleft -= bytesread) == 0)
198303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
198403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
198503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case LINES:
198603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
198703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
198803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
198903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
199003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
199103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((c = *xp) == '\0' && !aschars && delim != '\0') {
199203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* skip any read NULs unless delimiter */
199303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
199403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
199503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (expanding) {
199603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = false;
199703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == delim) {
199803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (Flag(FTALKING_I) && isatty(fd)) {
199903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
200003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * set prompt in case this is
200103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * called from .profile or $ENV
200203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 */
200303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					set_prompt(PS2, NULL);
200403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					pprompt(prompt, 0);
20055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
200603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* drop the backslash */
200703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				--xp;
200803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* and the delimiter */
20095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
20105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
201103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (c == delim) {
201203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
201303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (!rawmode && c == '\\') {
201403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = true;
201503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
201603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
201703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++xp;
201803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
201903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
202003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	goto c_read_readloop;
202103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
202203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_readdone:
202303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bytesread = Xlength(xs, xp);
202403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xput(xs, xp, '\0');
202503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
202603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*-
202703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * state: we finished reading the input and NUL terminated it
202803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Xstring(xs, xp) -> xp-1 = input string without trailing delim
202903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * rv = 1 if EOF, 0 otherwise (errors handled already)
203003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 */
203103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
203203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (rv == 1) {
203303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* clean up coprocess if needed, on EOF */
203403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		coproc_read_close(fd);
203503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (readmode == READALL)
203603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* EOF is no error here */
203703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 0;
203803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
203903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
204003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (savehist)
204103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		histsave(&source->line, Xstring(xs, xp), true, false);
204203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
204303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ccp = cp = Xclose(xs, xp);
204403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	expanding = false;
204503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	XinitN(xs, 128, ATEMP);
204603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray) {
20475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = global(*wp);
20485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & RDONLY) {
204903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitro:
2050c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			bi_errorf("read-only: %s", *wp);
205103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_spliterr:
205203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
205303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			afree(cp, ATEMP);
205403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
205503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
205603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* exporting an array is currently pointless */
205703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		unset(vp, 1);
205803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* counter for array index */
205903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		c = 0;
206003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
206103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!aschars) {
206203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip initial IFS whitespace */
206303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesread && is_ifsws(*ccp)) {
206403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++ccp;
206503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
206603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
206703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* trim trailing IFS whitespace */
206803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesread && is_ifsws(ccp[bytesread - 1])) {
206903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
207003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
207103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
207203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitloop:
207303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xp = Xstring(xs, xp);
207403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* generate next word */
207503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!bytesread) {
207603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* no more input */
207703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (intoarray)
207803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitdone;
207903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* zero out next parameters */
208003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_gotword;
208103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
208203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (aschars) {
208303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, '1');
208403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, '#');
208503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bytesleft = utf_ptradj(ccp);
208603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesleft && bytesread) {
208703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			*xp++ = *ccp++;
208803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesleft;
208903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
209003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
209103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (xp[-1] == '\0') {
209203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp[-1] = '0';
209303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp[-3] = '2';
209403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
209503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_gotword;
209603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
209703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
209803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!intoarray && wp[1] == NULL)
209903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		lastparm = 1;
210003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
210103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitlast:
210203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* copy until IFS character */
210303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread) {
210403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char ch;
210503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
210603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ch = *ccp;
210703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (expanding) {
210803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = false;
210903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitcopy;
211003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (ctype(ch, C_IFS)) {
211103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
211203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (!rawmode && ch == '\\') {
211303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = true;
211403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else {
211503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitcopy:
211603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Xcheck(xs, xp);
211703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Xput(xs, xp, ch);
21185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
211903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
212003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
212103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
212203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xsave = Xsavepos(xs, xp);
212303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* copy word delimiter: IFSWS+IFS,IFSWS */
212403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread) {
212503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char ch;
212603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
212703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ch = *ccp;
212803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!ctype(ch, C_IFS))
212903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
213003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
213103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, ch);
213203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
213303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
213403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!ctype(ch, C_IFSWS))
213503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
213603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
213703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread && is_ifsws(*ccp)) {
213803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
213903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, *ccp);
214003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
214103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
214203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
214303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* if no more parameters, rinse and repeat */
214403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (lastparm && bytesread) {
214503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++lastparm;
214603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_splitlast;
214703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
214803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get rid of the delimiter unless we pack the rest */
214903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (lastparm < 2)
215003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp = Xrestpos(xs, xp, xsave);
215103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_gotword:
215203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xput(xs, xp, '\0');
215303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray) {
215403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq = arraysearch(vp, c++);
215503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
215603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq = global(*wp);
215703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* must be checked before exporting */
215803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vq->flag & RDONLY)
215903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitro;
21605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (Flag(FEXPORT))
21615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			typeset(*wp, EXPORT, 0, 0, 0);
21625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
216303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!setstr(vq, Xstring(xs, xp), KSH_RETURN_ERROR))
216403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_spliterr;
216503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (aschars) {
216603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		setint_v(vq, vq, false);
216703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* protect from UTFMODE changes */
216803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq->type = 0;
21695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
217003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray || *++wp != NULL)
217103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_splitloop;
217203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
217303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitdone:
217403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* free up */
217503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(cp, ATEMP);
21765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
217703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_out:
217803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(allocd, ATEMP);
217903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xfree(xs, xp);
218003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (restore_tios)
2181c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_tcset(fd, &tios);
218203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
218303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef is_ifsws
21845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
21855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
21875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_eval(const char **wp)
21885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
21895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct source *s, *saves = source;
21905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char savef;
21915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
21925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
21945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
21955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = pushs(SWORDS, ATEMP);
21965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->u.strv = wp + builtin_opt.optind;
21975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*-
21995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * The following code handles the case where the command is
22005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * empty due to failed command substitution, for example by
22015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	eval "$(false)"
22025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * This has historically returned 1 by AT&T ksh88. In this
22035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * case, shell() will not set or change exstat because the
22045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * compiled tree is empty, so it will use the value we pass
22055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * from subst_exstat, which is cleared in execute(), so it
22065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * should have been 0 if there were no substitutions.
22075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *
22085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * POSIX however says we don't do this, even though it is
22095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * traditionally done. AT&T ksh93 agrees with POSIX, so we
22105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * do. The following is an excerpt from SUSv4 [1003.2-2008]:
22115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *
22125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.9.1: Simple Commands
22135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	... If there is a command name, execution shall
22145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	continue as described in 2.9.1.1 [Command Search
22155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	and Execution]. If there is no command name, but
22165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	the command contained a command substitution, the
22175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	command shall complete with the exit status of the
22185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	last command substitution performed.
22195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.9.1.1: Command Search and Execution
22205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	(1) a. If the command name matches the name of a
22215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	special built-in utility, that special built-in
22225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	utility shall be invoked.
22235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.14.5: eval
22245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	If there are no arguments, or only null arguments,
22255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	eval shall return a zero exit status; ...
22265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
2227c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* AT&T ksh88: use subst_exstat */
2228c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* exstat = subst_exstat; */
2229c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* SUSv4: OR with a high value never written otherwise */
2230c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	exstat |= 0x4000;
22315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	savef = Flag(FERREXIT);
2233c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	Flag(FERREXIT) |= 0x80;
22345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = shell(s, false);
22355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FERREXIT) = savef;
22365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = saves;
22375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(s, ATEMP);
2238c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (exstat & 0x4000)
2239c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* detect old exstat, use 0 in that case */
2240c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		rv = 0;
22415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
22425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
22435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
22455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_trap(const char **wp)
22465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
22475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
22485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *s;
22495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
22505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
22525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
22535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
22545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
22565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
22575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (p->trap != NULL) {
22585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts("trap -- ", shl_stdout);
2259c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				print_value_quoted(shl_stdout, p->trap);
22605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shprintf(" %s\n", p->name);
22615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
22625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
22635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
22645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
22665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Use case sensitive lookup for first arg so the
22675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * command 'exit' isn't confused with the pseudo-signal
22685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 'EXIT'.
22695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
227003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get command */
227103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL;
22725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (s != NULL && s[0] == '-' && s[1] == '\0')
22735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = NULL;
22745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set/clear traps */
227603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = 0;
227703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (*wp != NULL)
227803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((p = gettrap(*wp++, true)) == NULL) {
227903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s '%s'", builtin_argv0,
228003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "bad signal", wp[-1]);
228103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++i;
228203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
228303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			settrap(p, s);
228403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (i);
22855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
22865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
22885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_exitreturn(const char **wp)
22895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
22905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n, how = LEXIT;
22915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
22925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
2294c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto c_exitreturn_err;
22955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
22965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (arg) {
22985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!getn(arg, &n)) {
22995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = 1;
230003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s", arg, "bad number");
23015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
2302c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			exstat = n & 0xFF;
230303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else if (trap_exstat != -1)
230403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		exstat = trap_exstat;
230503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0][0] == 'r') {
230603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* return */
23075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct env *ep;
23085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
230903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
231003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * need to tell if this is exit or return so trap exit will
23115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * work right (POSIX)
23125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
23135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (ep = e; ep; ep = ep->oenv)
23145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (STOP_RETURN(ep->type)) {
23155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				how = LRETURN;
23165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
23175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
23185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how == LEXIT && !really_exit && j_stopped_running()) {
2321c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		really_exit = true;
23225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		how = LSHELL;
23235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
232503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get rid of any i/o redirections */
232603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	quitenv(NULL);
23275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(how);
23285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* NOTREACHED */
2329c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
2330c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c_exitreturn_err:
2331c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (1);
23325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
23335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
23355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_brkcont(const char **wp)
23365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2337c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	unsigned int quit;
2338c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int n;
23395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep, *last_ep = NULL;
23405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
23415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
2343c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto c_brkcont_err;
23445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
23455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!arg)
23475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = 1;
23485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (!bi_getn(arg, &n))
2349c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto c_brkcont_err;
2350c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if (n <= 0) {
23515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* AT&T ksh does this for non-interactive shells only - weird */
235203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", arg, "bad value");
2353c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto c_brkcont_err;
23545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2355c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	quit = (unsigned int)n;
23565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */
23585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv)
23595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ep->type == E_LOOP) {
23605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (--quit == 0)
23615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
23625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ep->flags |= EF_BRKCONT_PASS;
23635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			last_ep = ep;
23645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
23655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (quit) {
236703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
236803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * AT&T ksh doesn't print a message - just does what it
23695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * can. We print a message 'cause it helps in debugging
23705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * scripts, but don't generate an error (ie, keep going).
23715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
2372c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if ((unsigned int)n == quit) {
237303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s %s", wp[0], "can't", wp[0]);
23745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
23755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
237603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
237703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * POSIX says if n is too big, the last enclosing loop
23785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * shall be used. Doesn't say to print an error but we
23795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * do anyway 'cause the user messed up.
23805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
23815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (last_ep)
23825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			last_ep->flags &= ~EF_BRKCONT_PASS;
2383c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		warningf(true, "%s: can only %s %u level(s)",
2384c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		    wp[0], wp[0], (unsigned int)n - quit);
23855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
23885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* NOTREACHED */
2389c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
2390c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c_brkcont_err:
2391c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (1);
23925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
23935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
23955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_set(const char **wp)
23965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
23975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argi;
23985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool setargs;
23995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
24005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **owp;
24015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[1] == NULL) {
240303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		static const char *args[] = { Tset, "-", NULL };
24045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c_typeset(args));
24055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
24065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	argi = parse_args(wp, OF_SET, &setargs);
24085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argi < 0)
24095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
24105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set $# and $* */
24115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (setargs) {
24125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp += argi - 1;
24135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		owp = wp;
241403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* save $0 */
241503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		wp[0] = l->argv[0];
24165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*++wp != NULL)
24175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(*wp, *wp, &l->area);
24185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argc = wp - owp - 1;
241903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argv = alloc2(l->argc + 2, sizeof(char *), &l->area);
24205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (wp = l->argv; (*wp++ = *owp++) != NULL; )
24215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
24225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
24235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*-
24245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * POSIX says set exit status is 0, but old scripts that use
24255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * getopt(1) use the construct
24265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	set -- $(getopt ab:c "$@")
24275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * which assumes the exit value set will be that of the $()
24285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * (subst_exstat is cleared in execute() so that it will be 0
24295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * if there are no command substitutions).
24305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Switched ksh (!posix !sh) to POSIX in mksh R39b.
24315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
2432c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH_LEGACY_MODE
2433c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	return (subst_exstat);
2434c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#else
24355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (Flag(FSH) ? subst_exstat : 0);
2436c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
24375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
24385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
24405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_unset(const char **wp)
24415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *id;
244303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int optc, rv = 0;
24445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool unset_var = true;
24455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != -1)
24475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
24485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'f':
24495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unset_var = false;
24505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
24515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'v':
24525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unset_var = true;
24535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
24545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
245503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*XXX not reached due to GF_ERROR */
245603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
24575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
24585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
24595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; (id = *wp) != NULL; wp++)
246003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (unset_var) {
246103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* unset variable */
24625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct tbl *vp;
24635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *cp = NULL;
24645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			size_t n;
24655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			n = strlen(id);
24675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (n > 3 && id[n-3] == '[' && id[n-2] == '*' &&
24685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    id[n-1] == ']') {
24695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strndupx(cp, id, n - 3, ATEMP);
24705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				id = cp;
24715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				optc = 3;
24725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
24735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				optc = vstrchr(id, '[') ? 0 : 1;
24745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp = global(id);
24765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(cp, ATEMP);
24775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((vp->flag&RDONLY)) {
2479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				warningf(true, "read-only: %s", vp->name);
248003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
248103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else
248203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				unset(vp, optc);
248303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
248403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* unset function */
24855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			define(id, NULL);
248603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
24875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
24885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
24905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querup_time(struct shf *shf, bool posix, long tv_sec, int tv_usec, int width,
24915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    const char *prefix, const char *suffix)
24925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tv_usec /= 10000;
24945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (posix)
24955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%s%*ld.%02d%s", prefix, width,
24965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tv_sec, tv_usec, suffix);
24975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
24985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%s%*ldm%d.%02ds%s", prefix, width,
24995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tv_sec / 60, (int)(tv_sec % 60), tv_usec, suffix);
25005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
25015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
25035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_times(const char **wp MKSH_A_UNUSED)
25045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
25055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rusage usage;
25065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_SELF, &usage);
25085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_utime.tv_sec,
25095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_utime.tv_usec, 0, null, " ");
25105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_stime.tv_sec,
25115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_stime.tv_usec, 0, null, "\n");
25125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_CHILDREN, &usage);
25145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_utime.tv_sec,
25155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_utime.tv_usec, 0, null, " ");
25165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_stime.tv_sec,
25175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_stime.tv_usec, 0, null, "\n");
25185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
25205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
25215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
25235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * time pipeline (really a statement, not a built-in command)
25245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
25255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
25265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutimex(struct op *t, int f, volatile int *xerrok)
25275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
25285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_NOARGS	BIT(0)
25295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_NOREAL	BIT(1)		/* don't report real time */
25305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_POSIX	BIT(2)		/* report in POSIX format */
25315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, tf = 0;
25325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rusage ru0, ru1, cru0, cru1;
25335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct timeval usrtime, systime, tv0, tv1;
25345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2535c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mksh_TIME(tv0);
25365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_SELF, &ru0);
25375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_CHILDREN, &cru0);
25385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->left) {
25395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
25405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * Two ways of getting cpu usage of a command: just use t0
25415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * and t1 (which will get cpu usage from other jobs that
25425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * finish while we are executing t->left), or get the
25435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * cpu usage of t->left. AT&T ksh does the former, while
25445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * pdksh tries to do the later (the j_usrtime hack doesn't
25455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * really work as it only counts the last job).
25465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
25475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timerclear(&j_usrtime);
25485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timerclear(&j_systime);
25495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = execute(t->left, f | XTIME, xerrok);
25505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (t->left->type == TCOM)
25515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tf |= t->left->str[0];
2552c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_TIME(tv1);
25535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getrusage(RUSAGE_SELF, &ru1);
25545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getrusage(RUSAGE_CHILDREN, &cru1);
25555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
25565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tf = TF_NOARGS;
25575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
255803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (tf & TF_NOARGS) {
255903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* ksh93 - report shell times (shell+kids) */
25605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tf |= TF_NOREAL;
25615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&ru0.ru_utime, &cru0.ru_utime, &usrtime);
25625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&ru0.ru_stime, &cru0.ru_stime, &systime);
25635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
25645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&ru1.ru_utime, &ru0.ru_utime, &usrtime);
25655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&usrtime, &j_usrtime, &usrtime);
25665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&ru1.ru_stime, &ru0.ru_stime, &systime);
25675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&systime, &j_systime, &systime);
25685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(tf & TF_NOREAL)) {
25715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&tv1, &tv0, &tv1);
25725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tf & TF_POSIX)
25735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p_time(shl_out, true, tv1.tv_sec, tv1.tv_usec,
25745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    5, "real ", "\n");
25755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
25765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p_time(shl_out, false, tv1.tv_sec, tv1.tv_usec,
25775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    5, null, " real ");
25785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tf & TF_POSIX)
25805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, true, usrtime.tv_sec, usrtime.tv_usec,
25815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, "user ", "\n");
25825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
25835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, false, usrtime.tv_sec, usrtime.tv_usec,
25845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, null, " user ");
25855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tf & TF_POSIX)
25865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, true, systime.tv_sec, systime.tv_usec,
25875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, "sys  ", "\n");
25885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
25895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, false, systime.tv_sec, systime.tv_usec,
25905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, null, " system\n");
25915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_flush(shl_out);
25925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
25945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
25955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
25975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutimex_hook(struct op *t, char **volatile *app)
25985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
25995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **wp = *app;
26005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, i, j;
26015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Getopt opt;
26025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ksh_getopt_reset(&opt, 0);
260403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* start at the start */
260503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	opt.optind = 0;
26065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt((const char **)wp, &opt, ":p")) != -1)
26075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
26085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
26095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t->str[0] |= TF_POSIX;
26105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
26115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
261203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorf("time: -%s %s", opt.optarg,
261303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "unknown option");
26145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ':':
261503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorf("time: -%s %s", opt.optarg,
261603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "requires an argument");
26175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Copy command words down over options. */
26195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (opt.optind != 0) {
26205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0; i < opt.optind; i++)
26215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(wp[i], ATEMP);
26225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0, j = opt.optind; (wp[i] = wp[j]); i++, j++)
26235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
26245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!wp[0])
26265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t->str[0] |= TF_NOARGS;
26275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*app = wp;
26285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
26295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* exec with no args - args case is taken care of in comexec() */
26315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
26325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_exec(const char **wp MKSH_A_UNUSED)
26335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
26345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
26355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* make sure redirects stay in place */
26375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (e->savefd != NULL) {
26385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0; i < NUFILE; i++) {
26395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (e->savefd[i] > 0)
26405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				close(e->savefd[i]);
2641c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_LEGACY_MODE
26425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
26435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * keep all file descriptors > 2 private for ksh,
26445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * but not for POSIX or legacy/kludge sh
26455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
26465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!Flag(FPOSIX) && !Flag(FSH) && i > 2 &&
26475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    e->savefd[i])
26485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fcntl(i, F_SETFD, FD_CLOEXEC);
2649c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
26505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->savefd = NULL;
26525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
26545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
26555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKNOD
26575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
26585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_mknod(const char **wp)
26595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
26605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, optc, rv = 0;
26615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool ismkfifo = false;
26625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **argv;
26635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	void *set = NULL;
26645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode_t mode = 0, oldmode = 0;
26655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "m:")) != -1) {
26675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
26685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'm':
26695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			set = setmode(builtin_opt.optarg);
26705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (set == NULL) {
26715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("invalid file mode");
26725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
26735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
26745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			mode = getmode(set, (mode_t)(DEFFILEMODE));
267503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			free_ossetmode(set);
26765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
26775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
26785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_usage;
26795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	argv = &wp[builtin_opt.optind];
26825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argv[0] == NULL)
26835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto c_mknod_usage;
26845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; argv[argc]; argc++)
26855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
26865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argc == 2 && argv[1][0] == 'p')
26875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ismkfifo = true;
26885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (argc != 4 || (argv[1][0] != 'b' && argv[1][0] != 'c'))
26895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto c_mknod_usage;
26905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (set != NULL)
26925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		oldmode = umask((mode_t)0);
26935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
26945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mode = DEFFILEMODE;
26955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode |= (argv[1][0] == 'b') ? S_IFBLK :
26975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (argv[1][0] == 'c') ? S_IFCHR : 0;
26985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!ismkfifo) {
27005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unsigned long majnum, minnum;
27015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		dev_t dv;
27025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *c;
27035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		majnum = strtoul(argv[2], &c, 0);
27055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == argv[2]) || (*c != '\0')) {
270603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("non-numeric %s %s '%s'", "device", "major", argv[2]);
27075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
27085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		minnum = strtoul(argv[3], &c, 0);
27105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == argv[3]) || (*c != '\0')) {
271103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("non-numeric %s %s '%s'", "device", "minor", argv[3]);
27125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
27135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		dv = makedev(majnum, minnum);
27155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned long)(major(dv)) != majnum) {
271603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s %s too large: %lu", "device", "major", majnum);
27175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
27185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned long)(minor(dv)) != minnum) {
272003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s %s too large: %lu", "device", "minor", minnum);
27215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
27225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (mknod(argv[0], mode, dv))
27245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_failed;
27255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (mkfifo(argv[0], mode)) {
27265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_failed:
2727c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", argv[0], cstrerror(errno));
27285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_err:
27295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = 1;
27305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
27315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (set)
27335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(oldmode);
27345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
27355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_usage:
273603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bi_errorf("%s: %s", "usage", "mknod [-m mode] name b|c major minor");
273703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bi_errorf("%s: %s", "usage", "mknod [-m mode] name p");
27385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
27395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
27405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
27415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
274203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*-
2743c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser   test(1) roughly accepts the following grammar:
27445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	oexpr	::= aexpr | aexpr "-o" oexpr ;
27455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	aexpr	::= nexpr | nexpr "-a" aexpr ;
27465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	nexpr	::= primary | "!" nexpr ;
27475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	primary	::= unary-operator operand
27485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| operand binary-operator operand
27495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| operand
27505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| "(" oexpr ")"
27515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
27525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unary-operator ::= "-a"|"-r"|"-w"|"-x"|"-e"|"-f"|"-d"|"-c"|"-b"|"-p"|
27545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			   "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|
27555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			   "-L"|"-h"|"-S"|"-H";
27565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
27585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "-nt"|"-ot"|"-ef"|
2759c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			    "<"|">"	# rules used for [[ ... ]] expressions
27605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ;
2761c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	operand ::= <anything>
27625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru*/
27635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
276403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* POSIX says > 1 for errors */
2765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define T_ERR_EXIT 2
27665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
27685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_test(const char **wp)
27695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2770c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int argc, rv, invert = 0;
27715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_env te;
2772c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	Test_op op;
2773c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	const char *lhs, **swp;
27745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.flags = 0;
27765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.isa = ptest_isa;
27775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.getopnd = ptest_getopnd;
27785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.eval = test_eval;
27795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.error = ptest_error;
27805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; wp[argc]; argc++)
27825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
2783c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mkssert(argc > 0);
2784c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	mkssert(wp[0] != NULL);
27855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (strcmp(wp[0], "[") == 0) {
27875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (strcmp(wp[--argc], "]") != 0) {
27885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("missing ]");
27895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (T_ERR_EXIT);
27905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
27925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.pos.wp = wp + 1;
27945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.wp_end = wp + argc;
27955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
2797c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * Attempt to conform to POSIX special cases. This is pretty
2798c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * dumb code straight-forward from the 2008 spec, but unless
2799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * the old pdksh code doesn't live from so many assumptions.
2800c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	 * It does, though, inline some calls to '(*te.funcname)()'.
28015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
2802c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	switch (argc - 1) {
2803c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 0:
2804c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (1);
2805c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 1:
2806c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ptest_one:
2807c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		op = TO_STNZE;
2808c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		goto ptest_unary;
2809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 2:
2810c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ptest_two:
2811c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ptest_isa(&te, TM_NOT)) {
2812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			++invert;
2813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto ptest_one;
2814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if ((op = ptest_isa(&te, TM_UNOP))) {
2816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ptest_unary:
2817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			rv = test_eval(&te, op, *te.pos.wp++, NULL, true);
2818c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ptest_out:
2819c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			return ((invert & 1) ? rv : !rv);
2820c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* let the parser deal with anything else */
2822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
2823c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 3:
2824c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ptest_three:
2825c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		swp = te.pos.wp;
2826c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* use inside knowledge of ptest_getopnd inlined below */
2827c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		lhs = *te.pos.wp++;
2828c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if ((op = ptest_isa(&te, TM_BINOP))) {
2829c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* test lhs op rhs */
2830c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			rv = test_eval(&te, op, lhs, *te.pos.wp++, true);
2831c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto ptest_out;
2832c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2833c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* back up to lhs */
2834c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		te.pos.wp = swp;
2835c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ptest_isa(&te, TM_NOT)) {
2836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			++invert;
2837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto ptest_two;
2838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2839c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ptest_isa(&te, TM_OPAREN)) {
2840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			swp = te.pos.wp;
2841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* skip operand, without evaluation */
2842c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te.pos.wp++;
2843c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* check for closing parenthesis */
2844c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			op = ptest_isa(&te, TM_CPAREN);
2845c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* back up to operand */
2846c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te.pos.wp = swp;
2847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* if there was a closing paren, handle it */
2848c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (op)
2849c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				goto ptest_one;
2850c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* backing up is done before calling the parser */
2851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2852c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* let the parser deal with it */
2853c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
2854c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case 4:
2855c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ptest_isa(&te, TM_NOT)) {
2856c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			++invert;
2857c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			goto ptest_three;
2858c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2859c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (ptest_isa(&te, TM_OPAREN)) {
2860c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			swp = te.pos.wp;
2861c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* skip two operands, without evaluation */
2862c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te.pos.wp++;
2863c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te.pos.wp++;
2864c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* check for closing parenthesis */
2865c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			op = ptest_isa(&te, TM_CPAREN);
2866c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* back up to first operand */
2867c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te.pos.wp = swp;
2868c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* if there was a closing paren, handle it */
2869c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			if (op)
2870c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				goto ptest_two;
2871c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* backing up is done before calling the parser */
2872c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2873c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* defer this to the parser */
2874c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
28755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
28765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2877c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* "The results are unspecified." */
2878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	te.pos.wp = wp + 1;
28795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (test_parse(&te));
28805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
28815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
28835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Generic test routines.
28845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
28855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTest_op
28875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_isop(Test_meta meta, const char *s)
28885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
28895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char sc1;
28905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct t_op *tbl;
28915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tbl = meta == TM_UNOP ? u_ops : b_ops;
28935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*s) {
28945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sc1 = s[1];
28955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; tbl->op_text[0]; tbl++)
28965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (sc1 == tbl->op_text[1] && !strcmp(s, tbl->op_text))
28975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (tbl->op_num);
28985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
28995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (TO_NONOP);
29005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
29015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
29025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
29035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
29045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    bool do_eval)
29055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
29065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, s;
29075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t k;
29085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct stat b1, b2;
29095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t v1, v2;
29105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
29115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!do_eval)
29125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
29135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2914c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef DEBUG
2915c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	switch (op) {
2916c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	/* Binary operators */
2917c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_STEQL:
2918c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_STNEQ:
2919c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_STLT:
2920c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_STGT:
2921c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTEQ:
2922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTNE:
2923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTGT:
2924c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTGE:
2925c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTLT:
2926c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_INTLE:
2927c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_FILEQ:
2928c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_FILNT:
2929c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	case TO_FILOT:
2930c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* consistency check, but does not happen in practice */
2931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!opnd2) {
2932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			te->flags |= TEF_ERROR;
2933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			return (1);
2934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		}
2935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
2936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	default:
2937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* for completeness of switch */
2938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		break;
2939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
2940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
2941c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
294203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (op) {
294303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
29445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
29455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Unary Operators
29465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
294703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
294803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -n */
294903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STNZE:
29505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (*opnd1 != '\0');
295103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
295203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -z */
295303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STZER:
29545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (*opnd1 == '\0');
295503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
295603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -o */
295703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_OPTION:
29585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((i = *opnd1) == '!' || i == '?')
29595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opnd1++;
29605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((k = option(opnd1)) == (size_t)-1)
29615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
29625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (i == '?' ? 1 : i == '!' ? !Flag(k) : Flag(k));
296303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
296403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -r */
296503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILRD:
296603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* LINTED use of access */
296703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (access(opnd1, R_OK) == 0);
296803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
296903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -w */
297003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILWR:
297103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* LINTED use of access */
297203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (access(opnd1, W_OK) == 0);
297303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
297403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -x */
297503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEX:
297603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (ksh_access(opnd1, X_OK) == 0);
297703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
297803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -a */
297903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILAXST:
298003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -e */
298103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEXST:
29825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0);
298303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
298403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -r */
298503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILREG:
29865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode));
298703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
298803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -d */
298903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILID:
29905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode));
299103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
299203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -c */
299303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILCDEV:
29945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode));
299503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
299603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -b */
299703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILBDEV:
29985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode));
299903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
300003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -p */
300103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILFIFO:
30025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode));
300303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
300403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -h or -L */
300503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSYM:
3006c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH__NO_SYMLINK
3007c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (0);
3008c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#else
30095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode));
3010c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
301103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
301203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -S */
301303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSOCK:
30145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode));
301503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
301603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -H => HP context dependent files (directories) */
301703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILCDF:
301803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef S_ISCDF
301903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{
302003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char *nv;
302103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
302203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
302303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Append a + to filename and check to see if result is
302403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * a setuid directory. CDF stuff in general is hookey,
302503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * since it breaks for, e.g., the following sequence:
302603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * echo hi >foo+; mkdir foo; echo bye >foo/default;
302703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * chmod u+s foo (foo+ refers to the file with hi in it,
302803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * there is no way to get at the file with bye in it;
302903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * please correct me if I'm wrong about this).
303003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 */
303103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
303203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		nv = shf_smprintf("%s+", opnd1);
303303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = (stat(nv, &b1) == 0 && S_ISCDF(b1.st_mode));
303403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		afree(nv, ATEMP);
303503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (i);
303603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
303703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
30385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
303903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
304003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
304103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -u */
304203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSETU:
30435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
30445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISUID) == S_ISUID);
304503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
304603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -g */
304703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSETG:
30485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
30495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISGID) == S_ISGID);
305003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
305103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -k */
305203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSTCK:
30535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef S_ISVTX
30545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
30555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISVTX) == S_ISVTX);
30565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
30575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
30585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
305903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
306003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -s */
306103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILGZ:
3062c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (stat(opnd1, &b1) == 0 && (off_t)b1.st_size > (off_t)0);
306303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
306403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -t */
306503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILTT:
30665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (opnd1 && !bi_getn(opnd1, &i)) {
30675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			te->flags |= TEF_ERROR;
30685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			i = 0;
30695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
30705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			i = isatty(opnd1 ? i : 0);
30715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (i);
307203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
307303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -O */
307403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILUID:
3075c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (stat(opnd1, &b1) == 0 && (uid_t)b1.st_uid == ksheuid);
307603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
307703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -G */
307803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILGID:
3079c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (stat(opnd1, &b1) == 0 && (gid_t)b1.st_gid == getegid());
308003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
30815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
30825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Binary Operators
30835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
308403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
308503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* = */
308603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STEQL:
30875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_DBRACKET)
30885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (gmatchx(opnd1, opnd2, false));
30895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) == 0);
309003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
309103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* != */
309203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STNEQ:
30935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_DBRACKET)
30945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (!gmatchx(opnd1, opnd2, false));
30955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) != 0);
309603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
309703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* < */
309803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STLT:
30995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) < 0);
310003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
310103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* > */
310203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STGT:
31035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) > 0);
310403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
310503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -eq */
310603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTEQ:
310703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ne */
310803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTNE:
310903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ge */
311003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTGE:
311103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -gt */
311203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTGT:
311303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -le */
311403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTLE:
311503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -lt */
311603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTLT:
31175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) ||
31185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) {
31195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* error already printed.. */
31205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			te->flags |= TEF_ERROR;
31215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
31225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
312303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (op) {
31245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTEQ:
31255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 == v2);
31265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTNE:
31275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 != v2);
31285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTGE:
31295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 >= v2);
31305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTGT:
31315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 > v2);
31325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTLE:
31335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 <= v2);
31345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTLT:
31355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 < v2);
313603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
313703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* NOTREACHED */
313803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
31395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
314003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* NOTREACHED */
314103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
314203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -nt */
314303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILNT:
314403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
314503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * ksh88/ksh93 succeed if file2 can't be stated
31465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (subtly different from 'does not exist').
31475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
31485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
31495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((s = stat(opnd2, &b2)) == 0 &&
31505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_mtime > b2.st_mtime) || s < 0));
315103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
315203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ot */
315303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILOT:
315403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
315503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * ksh88/ksh93 succeed if file1 can't be stated
31565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (subtly different from 'does not exist').
31575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
31585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd2, &b2) == 0 &&
31595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((s = stat(opnd1, &b1)) == 0 &&
31605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_mtime < b2.st_mtime) || s < 0));
316103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
316203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ef */
316303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEQ:
31645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 &&
31655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
316603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
316703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* all other cases */
316803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_NONOP:
316903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_NONNULL:
317003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* throw the error */
317103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
31725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
31735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(*te->error)(te, 0, "internal error: unknown op");
31745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
31755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
31765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
31785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_parse(Test_env *te)
31795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
31815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = test_oexpr(te, 1);
31835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && !(*te->isa)(te, TM_END))
31855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(*te->error)(te, 0, "unexpected operator/operand");
31865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((te->flags & TEF_ERROR) ? T_ERR_EXIT : !rv);
31885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
31895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
31915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_oexpr(Test_env *te, bool do_eval)
31925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
31945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((rv = test_aexpr(te, do_eval)))
31965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		do_eval = false;
31975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_OR))
31985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (test_oexpr(te, do_eval) || rv);
31995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
32005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
32035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_aexpr(Test_env *te, bool do_eval)
32045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
32065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(rv = test_nexpr(te, do_eval)))
32085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		do_eval = false;
32095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_AND))
32105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (test_aexpr(te, do_eval) && rv);
32115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
32125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
32155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_nexpr(Test_env *te, bool do_eval)
32165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_NOT))
32185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (!test_nexpr(te, do_eval));
32195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (test_primary(te, do_eval));
32205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
32235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_primary(Test_env *te, bool do_eval)
32245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opnd1, *opnd2;
32265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
32275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op op;
32285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->flags & TEF_ERROR)
32305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
32315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((*te->isa)(te, TM_OPAREN)) {
32325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = test_oexpr(te, do_eval);
32335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_ERROR)
32345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
32355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(*te->isa)(te, TM_CPAREN)) {
323603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			(*te->error)(te, 0, "missing )");
32375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
32385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
32395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (rv);
32405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
32415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
32425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Binary should have precedence over unary in this case
32435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * so that something like test \( -f = -f \) is accepted
32445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
32455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((te->flags & TEF_DBRACKET) || (&te->pos.wp[1] < te->wp_end &&
32465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    !test_isop(TM_BINOP, te->pos.wp[1]))) {
32475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((op = (*te->isa)(te, TM_UNOP))) {
32485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* unary expression */
32495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opnd1 = (*te->getopnd)(te, op, do_eval);
32505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!opnd1) {
32515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				(*te->error)(te, -1, "missing argument");
32525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (0);
32535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
32545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return ((*te->eval)(te, op, opnd1, NULL, do_eval));
32565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
32575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
32585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opnd1 = (*te->getopnd)(te, TO_NONOP, do_eval);
32595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!opnd1) {
32605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(*te->error)(te, 0, "expression expected");
32615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
32625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
32635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((op = (*te->isa)(te, TM_BINOP))) {
32645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* binary expression */
32655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		opnd2 = (*te->getopnd)(te, op, do_eval);
32665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!opnd2) {
32675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			(*te->error)(te, -1, "missing second argument");
32685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
32695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
32705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return ((*te->eval)(te, op, opnd1, opnd2, do_eval));
32725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
32735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((*te->eval)(te, TO_STNZE, opnd1, NULL, do_eval));
32745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
32775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Plain test (test and [ .. ]) specific routines.
32785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
32795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
32815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Test if the current token is a whatever. Accepts the current token if
32825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it is. Returns 0 if it is not, non-zero if it is (in the case of
32835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * TM_UNOP and TM_BINOP, the returned value is a Test_op).
32845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
32855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op
32865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_isa(Test_env *te, Test_meta meta)
32875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Order important - indexed by Test_meta values */
3289c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	static const char * const tokens[] = {
32905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		"-o", "-a", "!", "(", ")"
32915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	};
32925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op rv;
32935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->pos.wp >= te->wp_end)
32955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (meta == TM_END ? TO_NONNULL : TO_NONOP);
32965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (meta == TM_UNOP || meta == TM_BINOP)
32985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = test_isop(meta, *te->pos.wp);
32995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (meta == TM_END)
33005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = TO_NONOP;
33015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
33025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = !strcmp(*te->pos.wp, tokens[(int)meta]) ?
33035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    TO_NONNULL : TO_NONOP;
33045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Accept the token? */
33065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rv != TO_NONOP)
33075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		te->pos.wp++;
33085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
33105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
33115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *
33135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_getopnd(Test_env *te, Test_op op, bool do_eval MKSH_A_UNUSED)
33145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
33155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->pos.wp >= te->wp_end)
33165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (op == TO_FILTT ? "1" : NULL);
33175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (*te->pos.wp++);
33185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
33195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
33215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_error(Test_env *te, int ofs, const char *msg)
33225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
33235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *op;
33245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te->flags |= TEF_ERROR;
33265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((op = te->pos.wp + ofs >= te->wp_end ? NULL : te->pos.wp[ofs]))
33275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s: %s", op, msg);
33285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
33295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s", msg);
33305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
33315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NO_LIMITS
33335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SOFT	0x1
33345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define HARD	0x2
33355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct limits {
33375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *name;
33385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int resource;		/* resource to get/set */
3339c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	unsigned int factor;	/* multiply by to get rlim_{cur,max} values */
33405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char option;
33415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
33425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void print_ulimit(const struct limits *, int);
33445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int set_ulimit(const struct limits *, const char *, int);
33455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Magic to divine the 'm' and 'v' limits */
33475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AS
33495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
33505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    !defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
33515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_AS
33525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(RLIMIT_VMEM)
33535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
33545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_AS
33555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
33565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_VMEM
33575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_RSS
33625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef ULIMIT_V_IS_VMEM
33635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_RSS
33645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
33655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_VMEM
33665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
33675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_RSS
33685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)
33705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#undef ULIMIT_M_IS_RSS
33715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
33755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_VMEM
33765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
33795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    (!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
33805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_VMEM
33815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
33845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    (RLIMIT_VMEM == RLIMIT_AS)
33855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#undef ULIMIT_M_IS_VMEM
33865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
33905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_ulimit(const char **wp)
33915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
33925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static const struct limits limits[] = {
33935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* do not use options -H, -S or -a or change the order */
33945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_CPU
33955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "time(cpu-seconds)", RLIMIT_CPU, 1, 't' },
33965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_FSIZE
33985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
33995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_CORE
34015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
34025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_DATA
34045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "data(KiB)", RLIMIT_DATA, 1024, 'd' },
34055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_STACK
34075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "stack(KiB)", RLIMIT_STACK, 1024, 's' },
34085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_MEMLOCK
34105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l' },
34115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NOFILE
34135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
34145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NPROC
34165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "processes", RLIMIT_NPROC, 1, 'p' },
34175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SWAP
34195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "swap(KiB)", RLIMIT_SWAP, 1024, 'w' },
34205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_LOCKS
34225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "flocks", RLIMIT_LOCKS, -1, 'L' },
34235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_TIME
34255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "humantime(seconds)", RLIMIT_TIME, 1, 'T' },
34265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NOVMON
34285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "vnodemonitors", RLIMIT_NOVMON, 1, 'V' },
34295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SIGPENDING
34315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "sigpending", RLIMIT_SIGPENDING, 1, 'i' },
34325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_MSGQUEUE
34345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q' },
34355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AIO_MEM
34375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M' },
34385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AIO_OPS
34405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "AIOoperations", RLIMIT_AIO_OPS, 1, 'O' },
34415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_TCACHE
34435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "cachedthreads", RLIMIT_TCACHE, 1, 'C' },
34445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SBSIZE
34465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B' },
34475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_PTHREAD
34495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "threadsperprocess", RLIMIT_PTHREAD, 1, 'P' },
34505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NICE
34525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "maxnice", RLIMIT_NICE, 1, 'e' },
34535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_RTPRIO
34555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "maxrtprio", RLIMIT_RTPRIO, 1, 'r' },
34565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_RSS)
34585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "resident-set(KiB)", RLIMIT_RSS, 1024, 'm' },
34595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(ULIMIT_M_IS_VMEM)
34605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "memory(KiB)", RLIMIT_VMEM, 1024, 'm' },
34615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_V_IS_VMEM)
34635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v' },
34645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(ULIMIT_V_IS_AS)
34655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "address-space(KiB)", RLIMIT_AS, 1024, 'v' },
34665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ NULL, 0, 0, 0 }
34685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	};
3469c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	static const char opts[] = "a"
3470c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_SBSIZE
3471c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "B"
3472c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3473c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_TCACHE
3474c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "C"
3475c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3476c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_CORE
3477c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "c"
3478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_DATA
3480c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "d"
3481c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3482c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_NICE
3483c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "e"
3484c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3485c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_FSIZE
3486c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "f"
3487c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3488c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "H"
3489c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_SIGPENDING
3490c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "i"
3491c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3492c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_LOCKS
3493c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "L"
3494c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3495c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_MEMLOCK
3496c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "l"
3497c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3498c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_AIO_MEM
3499c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "M"
3500c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3501c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(ULIMIT_M_IS_RSS) || defined(ULIMIT_M_IS_VMEM)
3502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "m"
3503c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_NOFILE
3505c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "n"
3506c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3507c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_AIO_OPS
3508c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "O"
3509c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3510c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_PTHREAD
3511c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "P"
3512c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3513c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_NPROC
3514c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "p"
3515c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3516c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_MSGQUEUE
3517c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "q"
3518c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3519c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_RTPRIO
3520c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "r"
3521c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3522c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "S"
3523c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_STACK
3524c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "s"
3525c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3526c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_TIME
3527c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "T"
3528c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3529c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_CPU
3530c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "t"
3531c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3532c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_NOVMON
3533c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "V"
3534c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3535c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(ULIMIT_V_IS_VMEM) || defined(ULIMIT_V_IS_AS)
3536c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "v"
3537c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3538c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef RLIMIT_SWAP
3539c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    "w"
3540c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3541c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	    ;
35425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int how = SOFT | HARD, optc, what = 'f';
35435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool all = false;
35445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct limits *l;
35455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
35475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
35485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'H':
35495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			how = HARD;
35505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
35515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'S':
35525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			how = SOFT;
35535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
35545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
35555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			all = true;
35565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
35575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
3558c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			bi_errorf("usage: ulimit [-%s] [value]", opts);
35595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
35605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
35615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			what = optc;
35625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
35635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (l = limits; l->name && l->option != what; l++)
35655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
35665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!l->name) {
35675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		internal_warningf("ulimit: %c", what);
35685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
35695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
35705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind]) {
35725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (all || wp[builtin_opt.optind + 1]) {
35735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("too many arguments");
35745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
35755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
35765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (set_ulimit(l, wp[builtin_opt.optind], how));
35775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
35785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!all)
35795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		print_ulimit(l, how);
35805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else for (l = limits; l->name; l++) {
35815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shprintf("%-20s ", l->name);
35825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		print_ulimit(l, how);
35835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
35845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
35855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
35865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
35885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruset_ulimit(const struct limits *l, const char *v, int how)
35895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
35905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rlim_t val = (rlim_t)0;
35915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rlimit limit;
35925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (strcmp(v, "unlimited") == 0)
35945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = (rlim_t)RLIM_INFINITY;
35955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
3596c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		mksh_uari_t rval;
35975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3598c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
35995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
36005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
36015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * Avoid problems caused by typos that evaluate misses due
36025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * to evaluating unset parameters to 0...
36035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * If this causes problems, will have to add parameter to
36045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * evaluate() to control if unset params are 0 or an error.
36055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
36065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!rval && !ksh_isdigit(v[0])) {
36075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("invalid %s limit: %s", l->name, v);
36085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
36095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
36105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = (rlim_t)((rlim_t)rval * l->factor);
36115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
36125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (getrlimit(l->resource, &limit) < 0) {
361403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* some can't be read, e.g. Linux RLIMIT_LOCKS */
36155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_cur = RLIM_INFINITY;
36165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_max = RLIM_INFINITY;
36175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
36185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & SOFT)
36195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_cur = val;
36205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & HARD)
36215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_max = val;
36225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!setrlimit(l->resource, &limit))
36235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
36245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (errno == EPERM)
36255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s exceeds allowable %s limit", v, l->name);
36265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
3627c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
36285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
36295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
36305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
36325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprint_ulimit(const struct limits *l, int how)
36335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
36345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rlim_t val = (rlim_t)0;
36355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rlimit limit;
36365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (getrlimit(l->resource, &limit)) {
36385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("unknown\n", shl_stdout);
36395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
36405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
36415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & SOFT)
36425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = limit.rlim_cur;
36435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (how & HARD)
36445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = limit.rlim_max;
36455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val == (rlim_t)RLIM_INFINITY)
36465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("unlimited\n", shl_stdout);
36475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
3648c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		shprintf("%lu\n", (unsigned long)(val / l->factor));
36495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
36505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
36515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
36535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_rename(const char **wp)
36545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
36555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
36565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
365703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
365803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
365903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
366003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
366103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
366203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
366303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* check for exactly two arguments */
366403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] == NULL	/* first argument */ ||
366503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    wp[1] == NULL	/* second argument */ ||
366603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    wp[2] != NULL	/* no further args please */)
366703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
366803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if ((rv = rename(wp[0], wp[1])) != 0) {
36695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = errno;
3670c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", "failed", cstrerror(rv));
36715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
36725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
36745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
36755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
36765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
36775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_realpath(const char **wp)
36785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
36795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
36805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *buf;
36815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
368203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
368303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
368403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
368503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
368603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
36875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
368803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* check for exactly one argument */
368903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] == NULL || wp[1] != NULL)
369003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
369103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if ((buf = do_realpath(wp[0])) == NULL) {
36925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = errno;
3693c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s", wp[0], cstrerror(rv));
36945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned int)rv > 255)
36955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 255;
36965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
36975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shprintf("%s\n", buf);
36985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(buf, ATEMP);
369903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rv = 0;
37005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
37015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
37025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
37035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
370403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
370503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint
370603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_cat(const char **wp)
370703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
3708c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	int fd = STDIN_FILENO, rv, eno;
370903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t n, w;
371003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *fn = "<stdin>";
371103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *buf, *cp;
371203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define MKSH_CAT_BUFSIZ 4096
371303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
371403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* parse options: POSIX demands we support "-u" as no-op */
371503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((rv = ksh_getopt(wp, &builtin_opt, "u")) != -1) {
371603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (rv) {
371703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 'u':
371803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* we already operate unbuffered */
371903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
372003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
372103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf(Tsynerr);
372203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (1);
372303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
372403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
372503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	wp += builtin_opt.optind;
372603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	rv = 0;
372703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
3728c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	if ((buf = malloc_osfunc(MKSH_CAT_BUFSIZ)) == NULL) {
3729c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf(Toomem, (unsigned long)MKSH_CAT_BUFSIZ);
3730c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		return (1);
3731c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser	}
3732c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser
373303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	do {
373403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (*wp) {
373503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fn = *wp++;
373603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (fn[0] == '-' && fn[1] == '\0')
373703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				fd = STDIN_FILENO;
373803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if ((fd = open(fn, O_RDONLY)) < 0) {
3739c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				eno = errno;
3740c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				bi_errorf("%s: %s", fn, cstrerror(eno));
374103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
374203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				continue;
374303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
374403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
374503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (/* CONSTCOND */ 1) {
374603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			n = blocking_read(fd, (cp = buf), MKSH_CAT_BUFSIZ);
3747c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			eno = errno;
3748c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			/* give the user a chance to ^C out */
3749c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			intrcheck();
375003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (n == -1) {
3751c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				if (eno == EINTR) {
375203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* interrupted, try again */
375303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					continue;
375403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
375503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* an error occured during reading */
3756c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser				bi_errorf("%s: %s", fn, cstrerror(eno));
375703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
375803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
375903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else if (n == 0)
376003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* end of file reached */
376103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
376203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (n) {
376303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				w = write(STDOUT_FILENO, cp, n);
376403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (w == -1) {
376503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (errno == EINTR)
376603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						/* interrupted, try again */
376703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						continue;
376803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* an error occured during writing */
3769c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					eno = errno;
377003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s", "<stdout>",
3771c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser					    cstrerror(eno));
377203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					rv = 1;
377303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (fd != STDIN_FILENO)
377403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						close(fd);
377503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					goto out;
377603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
377703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				n -= w;
377803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				cp += w;
377903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
378003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
378103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fd != STDIN_FILENO)
378203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			close(fd);
378303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} while (*wp);
378403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
378503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra out:
378603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	free_osfunc(buf);
378703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
378803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
378903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
379003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
379103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint
379203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_sleep(const char **wp)
379303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
379403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct timeval tv;
379503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int rv = 1;
379603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
379703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
379803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
379903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
380003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
380103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
380203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
380303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!wp[0] || wp[1])
380403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
380503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (parse_usec(wp[0], &tv))
3806c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		bi_errorf("%s: %s '%s'", Tsynerr, cstrerror(errno), wp[0]);
380703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else {
380803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK
3809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		sigset_t omask, bmask;
381003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
3811c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* block a number of signals from interrupting us, though */
3812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigemptyset(&bmask);
3813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGPIPE);
3814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGCHLD);
3815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef SIGWINCH
3816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGWINCH);
3817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3818c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef SIGINFO
3819c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGINFO);
3820c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef SIGUSR1
3822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGUSR1);
3823c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3824c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef SIGUSR2
3825c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		(void)sigaddset(&bmask, SIGUSR2);
3826c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif
3827c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		sigprocmask(SIG_BLOCK, &bmask, &omask);
382803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3829c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		if (select(1, NULL, NULL, NULL, &tv) == 0 || errno == EINTR)
383003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
383103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * strictly speaking only for SIGALRM, but the
383203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * execution may be interrupted by other signals
383303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 */
383403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 0;
383503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		else
3836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser			bi_errorf("%s: %s", Tselect, cstrerror(errno));
383703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK
3838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser		/* this will re-schedule signal delivery */
383903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigprocmask(SIG_SETMASK, &omask, NULL);
384003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
384103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
384203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
384303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
384403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3845