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,
803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *		 2010, 2011
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
4103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.197 2011/09/07 15:24:15 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
6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if defined(ANDROID)
6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int c_android_lsmod(const char **);
655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int
6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_true(const char **wp MKSH_A_UNUSED)
6903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
7003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (0);
7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int
7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_false(const char **wp MKSH_A_UNUSED)
7503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
7603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (1);
7703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
7803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
7903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
8003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * A leading = means assignments before command are kept;
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a leading * means a POSIX special builtin;
825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a leading + means a POSIX regular builtin
835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (* and + should not be combined).
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst struct builtin mkshbuiltins[] = {
865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=.", c_dot},
8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"*=:", c_true},
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"[", c_test},
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=break", c_brkcont},
9003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tgbuiltin, c_builtin},
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=continue", c_brkcont},
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=eval", c_eval},
935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=exec", c_exec},
945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=exit", c_exitreturn},
9503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"+false", c_false},
965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=return", c_exitreturn},
9703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tsgset, c_set},
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=shift", c_shift},
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"=times", c_times},
1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=trap", c_trap},
1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+=wait", c_wait},
1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+read", c_read},
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"test", c_test},
10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"+true", c_true},
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"ulimit", c_ulimit},
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+umask", c_umask},
1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=unset", c_unset},
10803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* no =: AT&T manual wrong */
10903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tpalias, c_alias},
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+cd", c_cd},
11103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* dash compatibility hack */
11203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"chdir", c_cd},
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+command", c_command},
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"echo", c_print},
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=export", c_typeset},
1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+fc", c_fc},
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+getopts", c_getopts},
11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"=global", c_typeset},
1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+jobs", c_jobs},
1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+kill", c_kill},
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"let", c_let},
1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"print", c_print},
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_PRINTF_BUILTIN
1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"printf", c_printf},
1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"pwd", c_pwd},
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"*=readonly", c_typeset},
12803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{T_typeset, c_typeset},
12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{Tpunalias, c_unalias},
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"whence", c_whence},
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+bg", c_fgbg},
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"+fg", c_fgbg},
1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"bind", c_bind},
13603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"cat", c_cat},
1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKNOD
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"mknod", c_mknod},
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"realpath", c_realpath},
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"rename", c_rename},
14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
14303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"sleep", c_sleep},
14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
14503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef __MirBSD__
14603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* alias to "true" for historical reasons */
14703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"domainname", c_true},
14803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
14903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if defined(ANDROID)
15003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{"lsmod", c_android_lsmod},
15103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{NULL, (int (*)(const char **))NULL}
1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct kill_info {
1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int num_width;
1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int name_width;
1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct t_op {
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char op_text[4];
1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op op_num;
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} u_ops[] = {
1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-a",	TO_FILAXST },
1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-b",	TO_FILBDEV },
1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-c",	TO_FILCDEV },
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-d",	TO_FILID },
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-e",	TO_FILEXST },
1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-f",	TO_FILREG },
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-G",	TO_FILGID },
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-g",	TO_FILSETG },
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-h",	TO_FILSYM },
1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-H",	TO_FILCDF },
1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-k",	TO_FILSTCK },
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-L",	TO_FILSYM },
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-n",	TO_STNZE },
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-O",	TO_FILUID },
1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-o",	TO_OPTION },
1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-p",	TO_FILFIFO },
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-r",	TO_FILRD },
1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-s",	TO_FILGZ },
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-S",	TO_FILSOCK },
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-t",	TO_FILTT },
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-u",	TO_FILSETU },
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-w",	TO_FILWR },
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-x",	TO_FILEX },
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-z",	TO_STZER },
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"",	TO_NONOP }
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct t_op b_ops[] = {
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"=",	TO_STEQL },
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"==",	TO_STEQL },
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"!=",	TO_STNEQ },
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"<",	TO_STLT },
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{">",	TO_STGT },
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-eq",	TO_INTEQ },
1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ne",	TO_INTNE },
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-gt",	TO_INTGT },
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ge",	TO_INTGE },
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-lt",	TO_INTLT },
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-le",	TO_INTLE },
2025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ef",	TO_FILEQ },
2035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-nt",	TO_FILNT },
2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"-ot",	TO_FILOT },
2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{"",	TO_NONOP }
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_oexpr(Test_env *, bool);
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_aexpr(Test_env *, bool);
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_nexpr(Test_env *, bool);
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int test_primary(Test_env *, bool);
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op ptest_isa(Test_env *, Test_meta);
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *ptest_getopnd(Test_env *, Test_op, bool);
2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void ptest_error(Test_env *, int, const char *);
21503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic char *kill_fmt_entry(char *, size_t, int, const void *);
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void p_time(struct shf *, bool, long, int, int,
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    const char *, const char *)
21803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra    MKSH_A_NONNULL((__nonnull__ (6, 7)));
2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_pwd(const char **wp)
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc;
22403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool physical = tobool(Flag(FPHYSICAL));
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *p, *allocd = NULL;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != -1)
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'L':
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			physical = false;
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'P':
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			physical = true;
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[0]) {
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("too many arguments");
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p = current_wd[0] ? (physical ? allocd = do_realpath(current_wd) :
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    current_wd) : NULL;
24603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* LINTED use of access */
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p && access(p, R_OK) < 0)
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p = NULL;
24903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!p && !(p = allocd = ksh_get_wd())) {
25003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", "can't determine current directory",
25103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    strerror(errno));
2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shprintf("%s\n", p);
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(allocd, ATEMP);
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *s_ptr;
2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int s_get(void);
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void s_put(int);
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_print(const char **wp)
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_NL		BIT(0)	/* print newline */
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_EXPAND	BIT(1)	/* expand backslash sequences */
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_PMINUSMINUS	BIT(2)	/* print a -- argument */
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_HIST		BIT(3)	/* print to history instead of stdout */
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define PO_COPROC	BIT(4)	/* printing to coprocess: block SIGPIPE */
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd = 1, c;
2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int flags = PO_EXPAND|PO_NL;
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *s, *emsg;
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	XString xs;
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *xp;
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[0][0] == 'e') {
2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* echo builtin */
2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
28003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (Flag(FPOSIX) || Flag(FSH) || Flag(FAS_BUILTIN)) {
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* Debian Policy 10.4 compliant "echo" builtin */
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*wp && !strcmp(*wp, "-n")) {
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* we recognise "-n" only as the first arg */
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = 0;
2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				wp++;
2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* otherwise, we print everything as-is */
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = PO_NL;
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int nflags = flags;
2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/**
2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * a compromise between sysV and BSD echo commands:
2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * escape sequences are enabled by default, and -n,
2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * -e and -E are recognised if they appear in argu-
2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * ments with no illegal options (ie, echo -nq will
2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * print -nq).
2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * Different from sysV echo since options are reco-
2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * gnised, different from BSD echo since escape se-
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * quences are enabled by default.
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((s = *wp) && *s == '-' && s[1]) {
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*++s)
3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (*s == 'n')
3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags &= ~PO_NL;
3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else if (*s == 'e')
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags |= PO_EXPAND;
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else if (*s == 'E')
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						nflags &= ~PO_EXPAND;
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					else
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/*
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * bad option: don't use
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * nflags, print argument
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 */
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*s)
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				wp++;
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags = nflags;
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int optc;
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *opts = "Rnprsu,";
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (optc) {
33003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case 'R':
33103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* fake BSD echo command */
3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_PMINUSMINUS;
3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_EXPAND;
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				opts = "ne";
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'e':
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_EXPAND;
3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'n':
3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_NL;
3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'p':
3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((fd = coproc_getfd(W_OK, &emsg)) < 0) {
34403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s", "-p", emsg);
3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'r':
3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags &= ~PO_EXPAND;
3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				flags |= PO_HIST;
3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'u':
3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!*(s = builtin_opt.optarg))
3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					fd = 0;
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else if ((fd = check_fd(s, W_OK, &emsg)) < 0) {
35803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s: %s", "-u", s, emsg);
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '?':
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(builtin_opt.info & GI_MINUSMINUS)) {
3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* treat a lone - like -- */
3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (wp[builtin_opt.optind] &&
3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ksh_isdash(wp[builtin_opt.optind]))
3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				builtin_opt.optind++;
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (flags & PO_PMINUSMINUS)
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			builtin_opt.optind--;
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp += builtin_opt.optind;
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Xinit(xs, xp, 128, ATEMP);
3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (*wp != NULL) {
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = *wp;
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((c = *s++) != '\0') {
3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xcheck(xs, xp);
3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((flags & PO_EXPAND) && c == '\\') {
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s_ptr = s;
3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				c = unbksl(false, s_get, s_put);
3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = s_ptr;
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (c == -1) {
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* rejected by generic function */
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch ((c = *s++)) {
3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'c':
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						flags &= ~PO_NL;
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* AT&T brain damage */
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						continue;
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case '\0':
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						s--;
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						c = '\\';
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					default:
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xput(xs, xp, '\\');
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if ((unsigned int)c > 0xFF) {
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* generic function returned Unicode */
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					char ts[4];
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
40403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					ts[utf_wctomb(ts, c - 0x100)] = 0;
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					for (c = 0; ts[c]; ++c)
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						Xput(xs, xp, ts[c]);
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, c);
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*++wp != NULL)
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Xput(xs, xp, ' ');
4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & PO_NL)
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, '\n');
4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & PO_HIST) {
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xput(xs, xp, '\0');
4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsave(&source->line, Xstring(xs, xp), true, false);
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xfree(xs, xp);
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int len = Xlength(xs, xp);
4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int opipe = 0;
4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
42603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
42703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Ensure we aren't killed by a SIGPIPE while writing to
4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * a coprocess. AT&T ksh doesn't seem to do this (seems
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * to just check that the co-process is alive which is
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * not enough).
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (coproc.write >= 0 && coproc.write == fd) {
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flags |= PO_COPROC;
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opipe = block_pipe();
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (s = Xstring(xs, xp); len > 0; ) {
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((c = write(fd, s, len)) < 0) {
4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (flags & PO_COPROC)
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					restore_pipe(opipe);
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (errno == EINTR) {
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* allow user to ^C out */
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					intrcheck();
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (flags & PO_COPROC)
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						opipe = block_pipe();
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s += c;
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			len -= c;
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (flags & PO_COPROC)
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			restore_pipe(opipe);
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_get(void)
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (*s_ptr++);
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querus_put(int c MKSH_A_UNUSED)
4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	--s_ptr;
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_whence(const char **wp)
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *tp;
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *id;
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool pflag = false, vflag = false, Vflag = false;
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, optc, fcflags;
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool iam_whence = wp[0][0] == 'w';
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts = iam_whence ? "pv" : "pvV";
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'v':
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vflag = true;
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'V':
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Vflag = true;
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fcflags = FC_BI | FC_PATH | FC_FUNC;
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!iam_whence) {
4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Note that -p on its own is deal with in comexec() */
5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (pflag)
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fcflags |= FC_DEFPATH;
50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
50303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Convert command options to whence options - note that
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * command -pV uses a different path search than whence -v
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * or whence -pv. This should be considered a feature.
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vflag = Vflag;
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (pflag)
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fcflags &= ~(FC_BI | FC_FUNC);
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((vflag || rv == 0) && (id = *wp++) != NULL) {
5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h = 0;
5145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tp = NULL;
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((iam_whence || vflag) && !pflag)
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = ktsearch(&keywords, id, h = hash(id));
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tp && !pflag) {
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = ktsearch(&aliases, id, h ? h : hash(id));
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (tp && !(tp->flag & ISSET))
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				tp = NULL;
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tp)
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tp = findcom(id, fcflags);
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tp->type != CTALIAS))
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_puts(id, shl_stdout);
52803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vflag)
52903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			switch (tp->type) {
53003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CKEYWD:
53103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CALIAS:
53203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CFUNC:
53303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			case CSHELL:
53403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(" is a", shl_stdout);
53503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
53603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
53703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (tp->type) {
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CKEYWD:
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(" reserved word", shl_stdout);
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CALIAS:
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("n %s%s for ",
54603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    (tp->flag & EXPORT) ? "exported " : null,
54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    Talias);
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!iam_whence && !vflag)
54903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s=", Talias, id);
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			print_value_quoted(tp->val.s);
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CFUNC:
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag) {
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (tp->flag & EXPORT)
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts("n exported", shl_stdout);
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (tp->flag & TRACE)
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" traced", shl_stdout);
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!(tp->flag & ISSET)) {
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" undefined", shl_stdout);
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (tp->u.fpath)
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shprintf(" (autoload from %s)",
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    tp->u.fpath);
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_puts(T_function, shl_stdout);
5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CSHELL:
5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (vflag)
56903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s %s",
57003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    (tp->flag & SPEC_BI) ? " special" : null,
57103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "shell", Tbuiltin);
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CTALIAS:
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case CEXEC:
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (tp->flag & ISSET) {
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (vflag) {
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_puts(" is ", shl_stdout);
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (tp->type == CTALIAS)
57903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						shprintf("a tracked %s%s for ",
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						    (tp->flag & EXPORT) ?
58103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    "exported " : null,
58203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						    Talias);
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(tp->val.s, shl_stdout);
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (vflag)
58703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf(" %s\n", "not found");
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%s is *GOK*", id);
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vflag || !rv)
5965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_putc('\n', shl_stdout);
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Deal with command -vV - command -p dealt with in comexec() */
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_command(const char **wp)
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
60503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Let c_whence do the work. Note that c_command() must be
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * a distinct function from c_whence() (tested in comexec()).
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (c_whence(wp));
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
61203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* typeset, global, export, and readonly */
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_typeset(const char **wp)
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l;
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vp, **p;
61803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	uint32_t fset = 0, fclr = 0, flag;
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int thing = 0, field, base, optc;
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts;
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *fieldstr, *basestr;
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool localv = false, func = false, pflag = false, istset = true;
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (**wp) {
62503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
62603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* export */
62703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'e':
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fset |= EXPORT;
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		istset = false;
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
63103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
63203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* readonly */
63303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'r':
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fset |= RDONLY;
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		istset = false;
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
63703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
63803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* set */
63903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 's':
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* called with 'typeset -' */
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
64203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
64303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* typeset */
64403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 't':
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		localv = true;
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* see comment below regarding possible opions */
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opts = istset ? "L#R#UZ#afi#lnprtux" : "p";
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fieldstr = basestr = NULL;
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	builtin_opt.flags |= GF_PLUSOPT;
65403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*
65503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * AT&T ksh seems to have 0-9 as options which are multiplied
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * to get a number that is used with -L, -R, -Z or -i (eg, -1R2
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * sets right justify in a field of 12). This allows options
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * does not allow the number to be specified as a separate argument
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Here, the number must follow the RLZi option, but is optional
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * (see the # kludge in ksh_getopt()).
6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1) {
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		flag = 0;
6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'L':
6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = LJUST;
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'R':
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = RJUST;
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'U':
67503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
67603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * AT&T ksh uses u, but this conflicts with
6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * upper/lower case. If this option is changed,
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * need to change the -U below as well
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = INT_U;
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'Z':
6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = ZEROFIL;
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fieldstr = builtin_opt.optarg;
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * this is supposed to set (-a) or unset (+a) the
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * indexed array attribute; it does nothing on an
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * existing regular string or indexed array though
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'f':
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			func = true;
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'i':
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = INTEGER;
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			basestr = builtin_opt.optarg;
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = LCASEV;
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'n':
70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			set_refflag = (builtin_opt.info & GI_PLUS) ?
70503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    SRF_DISABLE : SRF_ENABLE;
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* export, readonly: POSIX -p flag */
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* typeset: show values as well */
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (istset)
7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				continue;
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'r':
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = RDONLY;
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = TRACE;
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'u':
72103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* upper case / autoload */
72203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			flag = UCASEV_AL;
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'x':
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = EXPORT;
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (builtin_opt.info & GI_PLUS) {
7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr |= flag;
7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~flag;
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			thing = '+';
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= flag;
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr &= ~flag;
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			thing = '-';
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	field = 0;
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fieldstr && !bi_getn(fieldstr, &field))
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	base = 0;
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (basestr && !bi_getn(basestr, &base))
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (wp[builtin_opt.optind][0] == '-' ||
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    wp[builtin_opt.optind][0] == '+') &&
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    wp[builtin_opt.optind][1] == '\0') {
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		thing = wp[builtin_opt.optind][0];
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		builtin_opt.optind++;
7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
75603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
75703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    set_refflag != SRF_NOP)) {
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("only -t, -u and -x options may be used with -f");
75903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		set_refflag = SRF_NOP;
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind]) {
76303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Take care of exclusions.
7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * At this point, flags in fset are cleared in fclr and vice
7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * versa. This property should be preserved.
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
76803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fset & LCASEV)
76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* LCASEV has priority over UCASEV_AL */
7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~UCASEV_AL;
77103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fset & LJUST)
77203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* LJUST has priority over RJUST */
7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset &= ~RJUST;
77403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) {
77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* -Z implies -ZR */
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= RJUST;
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr &= ~RJUST;
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
77903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
78003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Setting these attributes clears the others, unless they
7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * are also set in this command
7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
78403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    INTEGER | INT_U | INT_L)) || set_refflag != SRF_NOP)
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    LCASEV | INTEGER | INT_U | INT_L);
7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set variables and attributes */
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind]) {
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int i, rv = 0;
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *f;
7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (localv && !func)
7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			fset |= LOCAL;
7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = builtin_opt.optind; wp[i]; i++) {
7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (func) {
7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				f = findfunc(wp[i], hash(wp[i]),
79903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    tobool(fset & UCASEV_AL));
8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!f) {
8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* AT&T ksh does ++rv: bogus */
8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					rv = 1;
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (fset | fclr) {
8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					f->flag |= fset;
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					f->flag &= ~fclr;
80803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				} else {
80903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					fpFUNCTf(shl_stdout, 0,
81003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    tobool(f->flag & FKSH),
81103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    wp[i], f->val.t);
81203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_putc('\n', shl_stdout);
81303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else if (!typeset(wp[i], fset, fclr, field, base)) {
81503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", wp[i], "not identifier");
81603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				set_refflag = SRF_NOP;
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
82003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		set_refflag = SRF_NOP;
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (rv);
8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* list variables and attributes */
82503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
82603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* no difference at this point.. */
82703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	flag = fset | fclr;
8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (func) {
8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (l = e->loc; l; l = l->next) {
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (p = ktsort(&l->funs); (vp = *p++); ) {
8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (flag && (vp->flag & flag) == 0)
8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (thing == '-')
83403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					fpFUNCTf(shl_stdout, 0,
83503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    tobool(vp->flag & FKSH),
8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    vp->name, vp->val.t);
8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
83803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shf_puts(vp->name, shl_stdout);
83903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shf_putc('\n', shl_stdout);
8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (l = e->loc; l; l = l->next) {
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (p = ktsort(&l->vars); (vp = *p++); ) {
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				struct tbl *tvp;
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bool any_set = false;
8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * See if the parameter is set (for arrays, if any
8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * element is set).
8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				for (tvp = vp; tvp; tvp = tvp->u.array)
8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (tvp->flag & ISSET) {
8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						any_set = true;
8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/*
8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * Check attributes - note that all array elements
8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * have (should have?) the same attributes, so checking
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * the first is sufficient.
8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 *
8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * Report an unset param only if the user has
8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * explicitly given it some attribute (like export);
8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 * otherwise, after "echo $FOO", we would report FOO...
8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				 */
8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!any_set && !(vp->flag & USERATTRIB))
8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (flag && (vp->flag & flag) == 0)
8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					continue;
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				for (; vp; vp = vp->u.array) {
87103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
87203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * Ignore array elements that aren't
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * set unless there are no set elements,
87403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * in which case the first is reported on
87503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 */
8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if ((vp->flag&ARRAY) && any_set &&
8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    !(vp->flag & ISSET))
8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						continue;
8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* no arguments */
8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (thing == 0 && flag == 0) {
88103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						/*
88203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						 * AT&T ksh prints things
8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * like export, integer,
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * leftadj, zerofill, etc.,
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * but POSIX says must
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 * be suitable for re-entry...
8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						 */
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shf_puts("typeset ", shl_stdout);
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (((vp->flag&(ARRAY|ASSOC))==ASSOC))
89003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-n");
8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&INTEGER))
89203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-i");
8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&EXPORT))
89403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-x");
8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&RDONLY))
89603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-r");
8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&TRACE))
89803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-t");
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&LJUST))
9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shprintf("-L%d ", vp->u2.field);
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&RJUST))
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shprintf("-R%d ", vp->u2.field);
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&ZEROFIL))
90403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-Z");
9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&LCASEV))
90603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-l");
9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&UCASEV_AL))
90803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-u");
9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&INT_U))
91003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							shprintf("%s ", "-U");
9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shf_puts(vp->name, shl_stdout);
9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (pflag) {
9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							char *s = str_val(vp);
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shf_putc('=', shl_stdout);
91603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							/*
91703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 * AT&T ksh can't have
91803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 * justified integers...
91903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 */
9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							if ((vp->flag &
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    (INTEGER|LJUST|RJUST)) ==
9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    INTEGER)
9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								shf_puts(s, shl_stdout);
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							else
9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								print_value_quoted(s);
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shf_putc('\n', shl_stdout);
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (vp->flag & ARRAY)
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							break;
9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					} else {
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (pflag)
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shf_puts(istset ?
9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    "typeset " :
9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    (flag & EXPORT) ?
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    "export " :
9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    "readonly ",
9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    shl_stdout);
9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if ((vp->flag&ARRAY) && any_set)
9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shprintf("%s[%lu]",
9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    vp->name,
9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    arrayindex(vp));
9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						else
9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shf_puts(vp->name, shl_stdout);
9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (thing == '-' && (vp->flag&ISSET)) {
9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							char *s = str_val(vp);
9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							shf_putc('=', shl_stdout);
94803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							/*
94903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 * AT&T ksh can't have
95003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 * justified integers...
95103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra							 */
9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							if ((vp->flag &
9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    (INTEGER|LJUST|RJUST)) ==
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							    INTEGER)
9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								shf_puts(s, shl_stdout);
9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							else
9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru								print_value_quoted(s);
9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						}
9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						shf_putc('\n', shl_stdout);
9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
96103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
96203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * Only report first 'element' of an array with
9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 * no set elements.
9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					 */
9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (!any_set)
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_alias(const char **wp)
9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct table *t = &aliases;
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, prefix = 0;
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool rflag = false, tflag, Uflag = false, pflag = false;
98003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	uint32_t xflag = 0;
9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc;
9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	builtin_opt.flags |= GF_PLUSOPT;
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "dprtUx")) != -1) {
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prefix = builtin_opt.info & GI_PLUS ? '+' : '-';
9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'd':
9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = NULL;	/* fix "alias -dt" */
9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &homedirs;
9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			pflag = true;
9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'r':
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rflag = true;
9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &taliases;
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'U':
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * kludge for tracked alias initialization
10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * (don't do a path search, just make an entry)
10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			Uflag = true;
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'x':
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xflag = EXPORT;
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(builtin_opt.info & GI_MINUSMINUS) && *wp &&
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (wp[0][0] == '-' || wp[0][0] == '+') && wp[0][1] == '\0') {
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		prefix = wp[0][0];
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tflag = t == &taliases;
10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* "hash -r" means reset all the tracked aliases.. */
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rflag) {
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		static const char *args[] = {
103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Tunalias, "-ta", NULL
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		};
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!tflag || *wp) {
103803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shprintf("%s: -r flag can only be used with -t"
103903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    " and without arguments\n", Talias);
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_getopt_reset(&builtin_opt, GF_ERROR);
10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c_unalias(args));
10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *ap, **p;
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (p = ktsort(t); (ap = *p++) != NULL; )
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((ap->flag & (ISSET|xflag)) == (ISSET|xflag)) {
10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (pflag)
105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf("%s ", Talias);
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(ap->name, shl_stdout);
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (prefix != '+') {
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putc('=', shl_stdout);
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					print_value_quoted(ap->val.s);
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_putc('\n', shl_stdout);
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *alias = *wp, *val, *newval;
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *xalias = NULL;
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tbl *ap;
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		uint32_t h;
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((val = cstrchr(alias, '='))) {
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strndupx(xalias, alias, val++ - alias, ATEMP);
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			alias = xalias;
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		h = hash(alias);
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (val == NULL && !tflag && !xflag) {
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap = ktsearch(t, alias, h);
10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap != NULL && (ap->flag&ISSET)) {
10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (pflag)
107703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					shprintf("%s ", Talias);
10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts(ap->name, shl_stdout);
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (prefix != '+') {
10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shf_putc('=', shl_stdout);
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					print_value_quoted(ap->val.s);
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_putc('\n', shl_stdout);
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else {
108503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				shprintf("%s %s %s\n", alias, Talias,
108603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "not found");
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap = ktenter(t, alias, h);
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->type = tflag ? CTALIAS : CALIAS;
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Are we setting the value or just some flags? */
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((val && !tflag) || (!val && tflag && !Uflag)) {
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap->flag&ALLOC) {
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~(ALLOC|ISSET);
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(ap->val.s, APERM);
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* ignore values for -t (AT&T ksh does this) */
110003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			newval = tflag ?
110103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    search_path(alias, path, X_OK, NULL) :
110203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    val;
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (newval) {
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(ap->val.s, newval, APERM);
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag |= ALLOC|ISSET;
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~ISSET;
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->flag |= DEFINED;
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (prefix == '+')
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~xflag;
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag |= xflag;
11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(xalias, ATEMP);
11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_unalias(const char **wp)
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct table *t = &aliases;
11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *ap;
11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, rv = 0;
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool all = false;
11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "adt")) != -1)
11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			all = true;
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'd':
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
113503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* fix "unalias -dt" */
113603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			t = NULL;
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &homedirs;
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 't':
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t = &taliases;
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_NOPWNAM
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t == NULL)
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap = ktsearch(t, *wp, hash(*wp));
11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ap == NULL) {
115603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* POSIX */
115703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			continue;
11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ap->flag&ALLOC) {
11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~(ALLOC|ISSET);
11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(ap->val.s, APERM);
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ap->flag &= ~(DEFINED|ISSET|EXPORT);
11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (all) {
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct tstate ts;
11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (ktwalk(&ts, t); (ap = ktnext(&ts)); ) {
11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ap->flag&ALLOC) {
11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ap->flag &= ~(ALLOC|ISSET);
11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				afree(ap->val.s, APERM);
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ap->flag &= ~(DEFINED|ISSET|EXPORT);
11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_let(const char **wp)
11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t val;
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
118803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[1] == NULL)
118903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* AT&T ksh does this */
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("no arguments");
11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (wp++; *wp; wp++)
11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!evaluate(*wp, &val, KSH_RETURN_ERROR, true)) {
119403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* distinguish error from zero result */
119503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 2;
11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = val == 0;
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_jobs(const char **wp)
12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, flag = 0, nflag = 0, rv = 0;
12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "lpnz")) != -1)
12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = 1;
12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			flag = 2;
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'n':
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nflag = 1;
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
121803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 'z':
121903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* debugging: print zombies */
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nflag = -1;
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!*wp) {
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (j_jobs(NULL, flag, nflag))
12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (j_jobs(*wp, flag, nflag))
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_fgbg(const char **wp)
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool bg = strcmp(*wp, "bg") == 0;
12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0;
12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!Flag(FMONITOR)) {
12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("job control not enabled");
12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp)
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = j_resume(*wp, bg);
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = j_resume("%%", bg);
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (bg ? 0 : rv);
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* format a single kill item */
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char *
126203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrakill_fmt_entry(char *buf, size_t buflen, int i, const void *arg)
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct kill_info *ki = (const struct kill_info *)arg;
12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	i++;
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_snprintf(buf, buflen, "%*d %*s %s",
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ki->num_width, i,
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ki->name_width, sigtraps[i].name,
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    sigtraps[i].mess);
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (buf);
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_kill(const char **wp)
12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *t = NULL;
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p;
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool lflag = false;
12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, n, rv, sig;
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* assume old style options if -digits or -UPPERCASE */
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p = wp[1]) && *p == '-' && (ksh_isdigit(p[1]) ||
12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ksh_isupper(p[1]))) {
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(t = gettrap(p + 1, true))) {
12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("bad signal '%s'", p + 1);
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = (wp[2] && strcmp(wp[2], "--") == 0) ? 3 : 2;
12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int optc;
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((optc = ksh_getopt(wp, &builtin_opt, "ls:")) != -1)
12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			switch (optc) {
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 'l':
12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				lflag = true;
12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case 's':
12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!(t = gettrap(builtin_opt.optarg, true))) {
13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					bi_errorf("bad signal '%s'",
13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    builtin_opt.optarg);
13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			case '?':
13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		i = builtin_opt.optind;
13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((lflag && t) || (!wp[i] && !lflag)) {
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("usage:\tkill [-s signame | -signum | -signame]"
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    " { job | pid | pgrp } ...\n"
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    "\tkill -l [exit_status ...]\n", shl_out);
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorfz();
13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (lflag) {
13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (wp[i]) {
13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (; wp[i]; i++) {
13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!bi_getn(wp[i], &n))
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (1);
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (n > 128 && n < 128 + NSIG)
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					n -= 128;
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (n > 0 && n < NSIG)
13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shprintf("%s\n", sigtraps[n].name);
13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				else
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					shprintf("%d\n", n);
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
133303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			ssize_t w, mess_cols, mess_octs;
133403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			int j;
13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct kill_info ki;
13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10)
13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				ki.num_width++;
13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ki.name_width = mess_cols = mess_octs = 0;
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (j = 0; j < NSIG; j++) {
13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = strlen(sigtraps[j].name);
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > ki.name_width)
13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					ki.name_width = w;
13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = strlen(sigtraps[j].mess);
13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > mess_octs)
13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					mess_octs = w;
13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				w = utf_mbswidth(sigtraps[j].mess);
13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (w > mess_cols)
13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					mess_cols = w;
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			print_columns(shl_stdout, NSIG - 1,
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    kill_fmt_entry, (void *)&ki,
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ki.num_width + 1 + ki.name_width + 1 + mess_octs,
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ki.num_width + 1 + ki.name_width + 1 + mess_cols,
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    true);
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = 0;
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sig = t ? t->signal : SIGTERM;
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; (p = wp[i]); i++) {
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*p == '%') {
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (j_kill(p, sig))
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (!getn(p, &n)) {
136703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", p,
136803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "arguments must be jobs or process IDs");
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (mksh_kill(n, sig) < 0) {
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("%s: %s", p, strerror(errno));
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				rv = 1;
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetopts_reset(int val)
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val >= 1) {
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_getopt_reset(&user_opt, GF_NONAME | GF_PLUSOPT);
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		user_opt.optind = user_opt.uoptind = val;
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_getopts(const char **wp)
13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, optc, rv;
13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opts, *var;
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char buf[3];
13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct tbl *vq, *voptarg;
13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opts = *wp++;
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!opts) {
140303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("missing %s argument", "options");
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	var = *wp++;
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!var) {
140903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("missing %s argument", "name");
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!*var || *skip_varname(var, true)) {
141303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", var, "is not an identifier");
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (e->loc->next == NULL) {
141803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		internal_warningf("%s: %s", "c_getopts", "no argv");
14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Which arguments are we parsing... */
14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL)
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp = e->loc->next->argv;
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*--wp = e->loc->next->argv[0];
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Check that our saved state won't cause a core dump... */
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; wp[argc]; argc++)
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (user_opt.optind > argc ||
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (user_opt.p != 0 &&
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    user_opt.p > strlen(wp[user_opt.optind - 1]))) {
14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("arguments changed since last call");
14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	user_opt.optarg = NULL;
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	optc = ksh_getopt(wp, &user_opt, opts);
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (optc >= 0 && optc != '?' && (user_opt.info & GI_PLUS)) {
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[0] = '+';
14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[1] = optc;
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[2] = '\0';
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
144503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
144603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * POSIX says var is set to ? at end-of-options, AT&T ksh
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * sets it to null - we go with POSIX...
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[0] = optc < 0 ? '?' : optc;
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		buf[1] = '\0';
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* AT&T ksh93 in fact does change OPTIND for unknown options too */
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	user_opt.uoptind = user_opt.optind;
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	voptarg = global("OPTARG");
145703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* AT&T ksh clears ro and int */
145803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	voptarg->flag &= ~RDONLY;
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Paranoia: ensure no bizarre results. */
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (voptarg->flag & INTEGER)
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    typeset("OPTARG", 0, INTEGER, 0, 0);
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (user_opt.optarg == NULL)
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unset(voptarg, 1);
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* This can't fail (have cleared readonly/integer) */
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setstr(voptarg, user_opt.optarg, KSH_RETURN_ERROR);
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = 0;
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	vq = global(var);
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Error message already printed (integer, readonly) */
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!setstr(vq, buf, KSH_RETURN_ERROR))
147303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rv = 2;
14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Flag(FEXPORT))
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		typeset(var, EXPORT, 0, 0, 0);
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (optc < 0 ? 1 : rv);
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_bind(const char **wp)
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, rv = 0;
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool macro = false;
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool list = false;
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *cp;
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *up;
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt,
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    "lm"
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    "l"
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    )) != -1)
14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			list = true;
15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'm':
15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			macro = true;
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
151203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (*wp == NULL)
151303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* list all */
15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = x_bind(NULL, NULL,
15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    false,
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    list);
15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; *wp != NULL; wp++) {
15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((cp = cstrchr(*wp, '=')) == NULL)
15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			up = NULL;
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else {
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(up, *wp, ATEMP);
15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			up[cp++ - *wp] = '\0';
15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (x_bind(up ? up : *wp, cp,
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL
15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    macro,
15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    false))
15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 1;
15335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(up, ATEMP);
15345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
15375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_shift(const char **wp)
15415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
15435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n;
15445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t val;
15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
15465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
15485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
15505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (arg) {
15525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		evaluate(arg, &val, KSH_UNWIND_ERROR, false);
15535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = val;
15545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
15555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = 1;
15565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (n < 0) {
155703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", arg, "bad number");
15585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (l->argc < n) {
15615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("nothing to shift");
15625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argv[n] = l->argv[0];
15655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argv += n;
15665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	l->argc -= n;
15675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
15685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
15715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_umask(const char **wp)
15725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, optc;
15745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *cp;
15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool symbolic = false;
15765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode_t old_umask;
15775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != -1)
15795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'S':
15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			symbolic = true;
15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	cp = wp[builtin_opt.optind];
15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (cp == NULL) {
15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_umask = umask((mode_t)0);
15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(old_umask);
15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (symbolic) {
15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char buf[18], *p;
15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int j;
15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = ~old_umask;
15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p = buf;
15965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (i = 0; i < 3; i++) {
15975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = "ugo"[i];
15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = '=';
15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				for (j = 0; j < 3; j++)
16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (old_umask & (1 << (8 - (3*i + j))))
16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						*p++ = "rwx"[j];
16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*p++ = ',';
16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p[-1] = '\0';
16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%s\n", buf);
16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shprintf("%#3.3o\n", (unsigned int)old_umask);
16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mode_t new_umask;
16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ksh_isdigit(*cp)) {
16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_umask = new_umask * 8 + (*cp - '0');
16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*cp) {
16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("bad number");
16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* symbolic format */
16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			int positions, new_val;
16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char op;
16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = umask((mode_t)0);
162403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* in case of error */
162503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			umask(old_umask);
16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			old_umask = ~old_umask;
16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			new_umask = old_umask;
16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			positions = 0;
16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while (*cp) {
16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*cp && vstrchr("augo", *cp))
16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch (*cp++) {
16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'a':
16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0111;
16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'u':
16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0100;
16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'g':
16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0010;
16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'o':
16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						positions |= 0001;
16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!positions)
164603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* default is a */
164703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					positions = 0111;
16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!vstrchr("=+-", op = *cp))
16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				cp++;
16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_val = 0;
16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while (*cp && vstrchr("rwxugoXs", *cp))
16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					switch (*cp++) {
16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'r': new_val |= 04; break;
16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'w': new_val |= 02; break;
16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'x': new_val |= 01; break;
16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'u':
16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 6;
16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'g':
16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 3;
16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'o':
16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						new_val |= old_umask >> 0;
16655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 'X':
16675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						if (old_umask & 0111)
16685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru							new_val |= 01;
16695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					case 's':
16715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						/* ignored */
16725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						break;
16735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					}
16745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				new_val = (new_val & 07) * positions;
16755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				switch (op) {
16765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '-':
16775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask &= ~new_val;
16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '=':
16805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask = new_val |
16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    (new_umask & ~(positions * 07));
16825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
16835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				case '+':
16845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					new_umask |= new_val;
16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
16865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (*cp == ',') {
16875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					positions = 0;
16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					cp++;
16895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else if (!vstrchr("=+-", *cp))
16905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					break;
16915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*cp) {
16935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("bad mask");
16945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
16955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
16965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			new_umask = ~new_umask;
16975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
16985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(new_umask);
16995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
17015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_dot(const char **wp)
17055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *file, *cp, **argv;
17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, i, errcode;
17085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
17105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((cp = wp[builtin_opt.optind]) == NULL) {
17135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("missing argument");
17145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
171603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((file = search_path(cp, path, R_OK, &errcode)) == NULL) {
171703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", cp, strerror(errcode));
17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Set positional parameters? */
17225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind + 1]) {
17235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argv = wp + builtin_opt.optind;
172403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* preserve $0 */
172503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		argv[0] = e->loc->argv[0];
17265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (argc = 0; argv[argc + 1]; argc++)
17275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
17285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
17295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argc = 0;
17305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		argv = NULL;
17315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((i = include(file, argc, argv, 0)) < 0) {
17335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* should not happen */
17345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s: %s", cp, strerror(errno));
17355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (i);
17385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_wait(const char **wp)
17425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
17435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, sig;
17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
17485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
17495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (waitfor(NULL, &sig) >= 0)
17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
17515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = sig;
17525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
17535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; *wp; wp++)
17545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = waitfor(*wp, &sig);
17555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (rv < 0)
175603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* magic exit code: bad job-id */
175703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = sig ? sig : 127;
17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
17595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
17605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
17615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
17625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
17635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_read(const char **wp)
17645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
176503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define is_ifsws(c) (ctype((c), C_IFS) && ctype((c), C_IFSWS))
17665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static char REPLY[] = "REPLY";
176703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int c, fd = 0, rv = 0, lastparm = 0;
176803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool savehist = false, intoarray = false, aschars = false;
176903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool rawmode = false, expanding = false;
177003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
177103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char delim = '\n';
177203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t bytesleft = 128, bytesread;
177303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct tbl *vp /* FU gcc */ = NULL, *vq;
177403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *cp, *allocd = NULL, *xp;
177503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *ccp;
177603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	XString xs;
177703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ptrdiff_t xsave = 0;
177803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct termios tios;
177903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool restore_tios = false;
178003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
178103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bool hastimeout = false;
178203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct timeval tv, tvlim;
178303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define c_read_opts "Aad:N:n:prst:u,"
178403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
178503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define c_read_opts "Aad:N:n:prsu,"
178603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
17875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
178803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((c = ksh_getopt(wp, &builtin_opt, c_read_opts)) != -1)
178903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (c) {
179003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'a':
179103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		aschars = true;
179203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* FALLTHROUGH */
179303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'A':
179403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		intoarray = true;
179503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
179603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'd':
179703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		delim = builtin_opt.optarg[0];
179803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
179903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'N':
180003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'n':
180103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		readmode = c == 'N' ? BYTES : UPTO;
180203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!bi_getn(builtin_opt.optarg, &c))
180303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
180403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (c == -1) {
180503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			readmode = READALL;
180603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bytesleft = 1024;
180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
180803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bytesleft = (unsigned int)c;
180903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
181003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'p':
181103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((fd = coproc_getfd(R_OK, &ccp)) < 0) {
181203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", "-p", ccp);
181303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
18145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
181503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
181603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'r':
181703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rawmode = true;
181803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
181903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 's':
182003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		savehist = true;
182103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
182203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
182303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 't':
182403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (parse_usec(builtin_opt.optarg, &tv)) {
182503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s '%s'", Tsynerr, strerror(errno),
182603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    builtin_opt.optarg);
182703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
182803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
182903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hastimeout = true;
183003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
183103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
183203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case 'u':
183303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!builtin_opt.optarg[0])
183403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fd = 0;
183503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		else if ((fd = check_fd(builtin_opt.optarg, R_OK, &ccp)) < 0) {
183603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s: %s", "-u", builtin_opt.optarg, ccp);
183703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
183803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
183903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
184003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case '?':
184103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (2);
184203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
18435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
18445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL)
18455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*--wp = REPLY;
18465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
184703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray && wp[1] != NULL) {
184803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("too many arguments");
184903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (2);
185003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
18515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
185203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((ccp = cstrchr(*wp, '?')) != NULL) {
185303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		strdupx(allocd, *wp, ATEMP);
185403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		allocd[ccp - *wp] = '\0';
185503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		*wp = allocd;
18565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (isatty(fd)) {
185703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
185803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * AT&T ksh says it prints prompt on fd if it's open
18595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * for writing and is a tty, but it doesn't do it
18605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * (it also doesn't check the interactive flag,
186103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * as is indicated in the Korn Shell book).
18625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
186303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_puts(ccp + 1, shl_out);
186403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			shf_flush(shl_out);
18655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
18665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
18675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
186803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xinit(xs, xp, bytesleft, ATEMP);
18695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
187003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (readmode == LINES)
187103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bytesleft = 1;
187203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (isatty(fd)) {
187303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		x_mkraw(fd, &tios, true);
187403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		restore_tios = true;
187503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
18765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
187703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
187803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hastimeout) {
187903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		gettimeofday(&tvlim, NULL);
188003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		timeradd(&tvlim, &tv, &tvlim);
188103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
188203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
188303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
188403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_readloop:
188503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
188603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hastimeout) {
188703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		fd_set fdset;
188803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
188903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		FD_ZERO(&fdset);
189003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		FD_SET(fd, &fdset);
189103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		gettimeofday(&tv, NULL);
189203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		timersub(&tvlim, &tv, &tv);
189303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (tv.tv_sec < 0) {
189403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* timeout expired globally */
189503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
189603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
189703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
189803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
189903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (select(fd + 1, &fdset, NULL, NULL, &tv)) {
190003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 1:
190103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
190203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 0:
190303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* timeout expired for this call */
190403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
190503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
190603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
190703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", Tselect, strerror(errno));
190803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
190903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
191003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
191103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
191203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
191303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
191403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bytesread = blocking_read(fd, xp, bytesleft);
191503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (bytesread == (size_t)-1) {
191603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* interrupted */
191703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (errno == EINTR && fatal_trap_check()) {
191803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
191903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * Was the offending signal one that would
192003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * normally kill a process? If so, pretend
192103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * the read was killed.
192203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 */
192303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
192403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
192503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
192603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* just ignore the signal */
192703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_readloop;
192803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
192903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
193003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (readmode) {
193103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case READALL:
193203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
193303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
193403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
193503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
193603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
193703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
193803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		XcheckN(xs, xp, bytesleft);
193903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
194003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
194103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case UPTO:
194203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0)
194303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
194403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
194503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
194603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_readdone;
194703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
194803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case BYTES:
194903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
195003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
195103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
195203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp = Xstring(xs, xp);
195303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
195403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
195503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp += bytesread;
195603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((bytesleft -= bytesread) == 0)
195703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
195803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
195903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case LINES:
196003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (bytesread == 0) {
196103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* end of file reached */
196203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 1;
196303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
196403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
196503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((c = *xp) == '\0' && !aschars && delim != '\0') {
196603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* skip any read NULs unless delimiter */
196703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
196803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
196903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (expanding) {
197003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = false;
197103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (c == delim) {
197203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (Flag(FTALKING_I) && isatty(fd)) {
197303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/*
197403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * set prompt in case this is
197503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 * called from .profile or $ENV
197603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					 */
197703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					set_prompt(PS2, NULL);
197803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					pprompt(prompt, 0);
19795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
198003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* drop the backslash */
198103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				--xp;
198203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* and the delimiter */
19835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
19845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
198503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (c == delim) {
198603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_readdone;
198703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (!rawmode && c == '\\') {
198803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = true;
198903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
199003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
199103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++xp;
199203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
199303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
199403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	goto c_read_readloop;
199503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
199603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_readdone:
199703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bytesread = Xlength(xs, xp);
199803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xput(xs, xp, '\0');
199903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
200003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*-
200103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * state: we finished reading the input and NUL terminated it
200203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * Xstring(xs, xp) -> xp-1 = input string without trailing delim
200303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 * rv = 1 if EOF, 0 otherwise (errors handled already)
200403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	 */
200503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
200603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (rv == 1) {
200703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* clean up coprocess if needed, on EOF */
200803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		coproc_read_close(fd);
200903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (readmode == READALL)
201003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* EOF is no error here */
201103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 0;
201203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
201303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
201403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (savehist)
201503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		histsave(&source->line, Xstring(xs, xp), true, false);
201603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
201703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ccp = cp = Xclose(xs, xp);
201803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	expanding = false;
201903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	XinitN(xs, 128, ATEMP);
202003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray) {
20215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		vp = global(*wp);
20225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (vp->flag & RDONLY) {
202303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitro:
202403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", *wp, "is read only");
202503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_spliterr:
202603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 2;
202703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			afree(cp, ATEMP);
202803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_out;
202903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
203003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* exporting an array is currently pointless */
203103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		unset(vp, 1);
203203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* counter for array index */
203303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		c = 0;
203403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
203503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!aschars) {
203603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip initial IFS whitespace */
203703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesread && is_ifsws(*ccp)) {
203803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++ccp;
203903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
204003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
204103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* trim trailing IFS whitespace */
204203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesread && is_ifsws(ccp[bytesread - 1])) {
204303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
204403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
204503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
204603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitloop:
204703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xp = Xstring(xs, xp);
204803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* generate next word */
204903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!bytesread) {
205003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* no more input */
205103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (intoarray)
205203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitdone;
205303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* zero out next parameters */
205403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_gotword;
205503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
205603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (aschars) {
205703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, '1');
205803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, '#');
205903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bytesleft = utf_ptradj(ccp);
206003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (bytesleft && bytesread) {
206103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			*xp++ = *ccp++;
206203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesleft;
206303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			--bytesread;
206403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
206503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (xp[-1] == '\0') {
206603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp[-1] = '0';
206703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			xp[-3] = '2';
206803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
206903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_gotword;
207003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
207103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
207203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!intoarray && wp[1] == NULL)
207303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		lastparm = 1;
207403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
207503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitlast:
207603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* copy until IFS character */
207703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread) {
207803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char ch;
207903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
208003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ch = *ccp;
208103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (expanding) {
208203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = false;
208303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitcopy;
208403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (ctype(ch, C_IFS)) {
208503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
208603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else if (!rawmode && ch == '\\') {
208703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			expanding = true;
208803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else {
208903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitcopy:
209003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Xcheck(xs, xp);
209103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			Xput(xs, xp, ch);
20925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
209303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
209403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
209503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
209603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	xsave = Xsavepos(xs, xp);
209703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* copy word delimiter: IFSWS+IFS,IFSWS */
209803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread) {
209903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char ch;
210003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
210103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		ch = *ccp;
210203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!ctype(ch, C_IFS))
210303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
210403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
210503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, ch);
210603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
210703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
210803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (!ctype(ch, C_IFSWS))
210903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
211003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
211103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (bytesread && is_ifsws(*ccp)) {
211203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xcheck(xs, xp);
211303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		Xput(xs, xp, *ccp);
211403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++ccp;
211503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		--bytesread;
211603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
211703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* if no more parameters, rinse and repeat */
211803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (lastparm && bytesread) {
211903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++lastparm;
212003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_splitlast;
212103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
212203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get rid of the delimiter unless we pack the rest */
212303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (lastparm < 2)
212403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		xp = Xrestpos(xs, xp, xsave);
212503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_gotword:
212603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xput(xs, xp, '\0');
212703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray) {
212803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq = arraysearch(vp, c++);
212903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else {
213003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq = global(*wp);
213103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* must be checked before exporting */
213203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (vq->flag & RDONLY)
213303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto c_read_splitro;
21345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (Flag(FEXPORT))
21355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			typeset(*wp, EXPORT, 0, 0, 0);
21365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
213703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!setstr(vq, Xstring(xs, xp), KSH_RETURN_ERROR))
213803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_spliterr;
213903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (aschars) {
214003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		setint_v(vq, vq, false);
214103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* protect from UTFMODE changes */
214203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		vq->type = 0;
21435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
214403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (intoarray || *++wp != NULL)
214503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto c_read_splitloop;
214603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
214703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_splitdone:
214803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* free up */
214903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(cp, ATEMP);
21505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
215103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c_read_out:
215203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	afree(allocd, ATEMP);
215303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	Xfree(xs, xp);
215403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (restore_tios)
215503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		tcsetattr(fd, TCSADRAIN, &tios);
215603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
215703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef is_ifsws
21585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
21595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
21615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_eval(const char **wp)
21625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
21635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct source *s, *saves = source;
21645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char savef;
21655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
21665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
21685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
21695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s = pushs(SWORDS, ATEMP);
21705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	s->u.strv = wp + builtin_opt.optind;
21715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
21725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*-
21735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * The following code handles the case where the command is
21745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * empty due to failed command substitution, for example by
21755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	eval "$(false)"
21765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * This has historically returned 1 by AT&T ksh88. In this
21775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * case, shell() will not set or change exstat because the
21785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * compiled tree is empty, so it will use the value we pass
21795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * from subst_exstat, which is cleared in execute(), so it
21805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * should have been 0 if there were no substitutions.
21815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *
21825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * POSIX however says we don't do this, even though it is
21835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * traditionally done. AT&T ksh93 agrees with POSIX, so we
21845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * do. The following is an excerpt from SUSv4 [1003.2-2008]:
21855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *
21865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.9.1: Simple Commands
21875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	... If there is a command name, execution shall
21885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	continue as described in 2.9.1.1 [Command Search
21895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	and Execution]. If there is no command name, but
21905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	the command contained a command substitution, the
21915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	command shall complete with the exit status of the
21925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	last command substitution performed.
21935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.9.1.1: Command Search and Execution
21945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	(1) a. If the command name matches the name of a
21955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	special built-in utility, that special built-in
21965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	utility shall be invoked.
21975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 2.14.5: eval
21985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	If there are no arguments, or only null arguments,
21995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	eval shall return a zero exit status; ...
22005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
22015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* exstat = subst_exstat; */	/* AT&T ksh88 */
22025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	exstat = 0;			/* SUSv4 */
22035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	savef = Flag(FERREXIT);
22055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FERREXIT) = 0;
22065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = shell(s, false);
22075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Flag(FERREXIT) = savef;
22085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = saves;
22095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(s, ATEMP);
22105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
22115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
22125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
22145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_trap(const char **wp)
22155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
22165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
22175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *s;
22185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
22195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
22215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
22225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
22235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp == NULL) {
22255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
22265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (p->trap != NULL) {
22275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_puts("trap -- ", shl_stdout);
22285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				print_value_quoted(p->trap);
22295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shprintf(" %s\n", p->name);
22305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
22315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
22325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
22335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
22355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Use case sensitive lookup for first arg so the
22365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * command 'exit' isn't confused with the pseudo-signal
22375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * 'EXIT'.
22385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
223903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get command */
224003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL;
22415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (s != NULL && s[0] == '-' && s[1] == '\0')
22425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		s = NULL;
22435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set/clear traps */
224503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = 0;
224603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while (*wp != NULL)
224703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((p = gettrap(*wp++, true)) == NULL) {
224803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s '%s'", builtin_argv0,
224903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "bad signal", wp[-1]);
225003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			++i;
225103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
225203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			settrap(p, s);
225303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (i);
22545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
22555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
22575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_exitreturn(const char **wp)
22585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
22595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n, how = LEXIT;
22605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
22615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
22635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
22645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
22655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (arg) {
22675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!getn(arg, &n)) {
22685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = 1;
226903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s", arg, "bad number");
22705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
22715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = n;
227203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} else if (trap_exstat != -1)
227303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		exstat = trap_exstat;
227403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0][0] == 'r') {
227503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* return */
22765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct env *ep;
22775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
227803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
227903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * need to tell if this is exit or return so trap exit will
22805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * work right (POSIX)
22815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
22825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (ep = e; ep; ep = ep->oenv)
22835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (STOP_RETURN(ep->type)) {
22845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				how = LRETURN;
22855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
22865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
22875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
22885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
22895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how == LEXIT && !really_exit && j_stopped_running()) {
22905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		really_exit = 1;
22915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		how = LSHELL;
22925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
22935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
229403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* get rid of any i/o redirections */
229503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	quitenv(NULL);
22965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(how);
22975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* NOTREACHED */
22985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
22995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
23015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_brkcont(const char **wp)
23025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
23035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n, quit;
23045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct env *ep, *last_ep = NULL;
23055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *arg;
23065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_getopt(wp, &builtin_opt, null) == '?')
23085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
23095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	arg = wp[builtin_opt.optind];
23105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!arg)
23125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		n = 1;
23135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (!bi_getn(arg, &n))
23145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
23155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	quit = n;
23165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (quit <= 0) {
23175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* AT&T ksh does this for non-interactive shells only - weird */
231803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", arg, "bad value");
23195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
23205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */
23235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv)
23245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ep->type == E_LOOP) {
23255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (--quit == 0)
23265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
23275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ep->flags |= EF_BRKCONT_PASS;
23285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			last_ep = ep;
23295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
23305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (quit) {
233203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
233303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * AT&T ksh doesn't print a message - just does what it
23345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * can. We print a message 'cause it helps in debugging
23355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * scripts, but don't generate an error (ie, keep going).
23365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
23375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (n == quit) {
233803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			warningf(true, "%s: %s %s", wp[0], "can't", wp[0]);
23395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
23405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
234103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
234203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * POSIX says if n is too big, the last enclosing loop
23435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * shall be used. Doesn't say to print an error but we
23445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * do anyway 'cause the user messed up.
23455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
23465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (last_ep)
23475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			last_ep->flags &= ~EF_BRKCONT_PASS;
23485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		warningf(true, "%s: can only %s %d level(s)",
23495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    wp[0], wp[0], n - quit);
23505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
23535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* NOTREACHED */
23545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
23555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
23575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_set(const char **wp)
23585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
23595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argi;
23605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool setargs;
23615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct block *l = e->loc;
23625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **owp;
23635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[1] == NULL) {
236503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		static const char *args[] = { Tset, "-", NULL };
23665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (c_typeset(args));
23675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	argi = parse_args(wp, OF_SET, &setargs);
23705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argi < 0)
23715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
23725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* set $# and $* */
23735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (setargs) {
23745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp += argi - 1;
23755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		owp = wp;
237603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* save $0 */
237703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		wp[0] = l->argv[0];
23785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (*++wp != NULL)
23795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(*wp, *wp, &l->area);
23805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		l->argc = wp - owp - 1;
238103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		l->argv = alloc2(l->argc + 2, sizeof(char *), &l->area);
23825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (wp = l->argv; (*wp++ = *owp++) != NULL; )
23835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
23845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
23855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*-
23865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * POSIX says set exit status is 0, but old scripts that use
23875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * getopt(1) use the construct
23885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	set -- $(getopt ab:c "$@")
23895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * which assumes the exit value set will be that of the $()
23905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * (subst_exstat is cleared in execute() so that it will be 0
23915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * if there are no command substitutions).
23925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Switched ksh (!posix !sh) to POSIX in mksh R39b.
23935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
23945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (Flag(FSH) ? subst_exstat : 0);
23955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
23965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
23975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
23985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_unset(const char **wp)
23995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *id;
240103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int optc, rv = 0;
24025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool unset_var = true;
24035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != -1)
24055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
24065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'f':
24075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unset_var = false;
24085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
24095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'v':
24105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unset_var = true;
24115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
24125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
241303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*XXX not reached due to GF_ERROR */
241403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (2);
24155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
24165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
24175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; (id = *wp) != NULL; wp++)
241803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (unset_var) {
241903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* unset variable */
24205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			struct tbl *vp;
24215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			char *cp = NULL;
24225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			size_t n;
24235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			n = strlen(id);
24255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (n > 3 && id[n-3] == '[' && id[n-2] == '*' &&
24265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    id[n-1] == ']') {
24275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strndupx(cp, id, n - 3, ATEMP);
24285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				id = cp;
24295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				optc = 3;
24305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
24315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				optc = vstrchr(id, '[') ? 0 : 1;
24325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			vp = global(id);
24345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(cp, ATEMP);
24355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((vp->flag&RDONLY)) {
243703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				warningf(true, "%s: %s", vp->name,
243803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "is read only");
243903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
244003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else
244103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				unset(vp, optc);
244203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
244303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* unset function */
24445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			define(id, NULL);
244503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
24465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
24475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
24495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querup_time(struct shf *shf, bool posix, long tv_sec, int tv_usec, int width,
24505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    const char *prefix, const char *suffix)
24515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tv_usec /= 10000;
24535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (posix)
24545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%s%*ld.%02d%s", prefix, width,
24555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tv_sec, tv_usec, suffix);
24565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
24575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%s%*ldm%d.%02ds%s", prefix, width,
24585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    tv_sec / 60, (int)(tv_sec % 60), tv_usec, suffix);
24595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
24605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
24625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_times(const char **wp MKSH_A_UNUSED)
24635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rusage usage;
24655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_SELF, &usage);
24675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_utime.tv_sec,
24685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_utime.tv_usec, 0, null, " ");
24695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_stime.tv_sec,
24705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_stime.tv_usec, 0, null, "\n");
24715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_CHILDREN, &usage);
24735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_utime.tv_sec,
24745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_utime.tv_usec, 0, null, " ");
24755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p_time(shl_stdout, false, usage.ru_stime.tv_sec,
24765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    usage.ru_stime.tv_usec, 0, null, "\n");
24775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
24795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
24805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
24825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * time pipeline (really a statement, not a built-in command)
24835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
24845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
24855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutimex(struct op *t, int f, volatile int *xerrok)
24865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
24875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_NOARGS	BIT(0)
24885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_NOREAL	BIT(1)		/* don't report real time */
24895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define TF_POSIX	BIT(2)		/* report in POSIX format */
24905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 0, tf = 0;
24915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rusage ru0, ru1, cru0, cru1;
24925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct timeval usrtime, systime, tv0, tv1;
24935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
24945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	gettimeofday(&tv0, NULL);
24955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_SELF, &ru0);
24965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	getrusage(RUSAGE_CHILDREN, &cru0);
24975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (t->left) {
24985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
24995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * Two ways of getting cpu usage of a command: just use t0
25005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * and t1 (which will get cpu usage from other jobs that
25015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * finish while we are executing t->left), or get the
25025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * cpu usage of t->left. AT&T ksh does the former, while
25035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * pdksh tries to do the later (the j_usrtime hack doesn't
25045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * really work as it only counts the last job).
25055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
25065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timerclear(&j_usrtime);
25075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timerclear(&j_systime);
25085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = execute(t->left, f | XTIME, xerrok);
25095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (t->left->type == TCOM)
25105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			tf |= t->left->str[0];
25115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		gettimeofday(&tv1, NULL);
25125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getrusage(RUSAGE_SELF, &ru1);
25135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		getrusage(RUSAGE_CHILDREN, &cru1);
25145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
25155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tf = TF_NOARGS;
25165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
251703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (tf & TF_NOARGS) {
251803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* ksh93 - report shell times (shell+kids) */
25195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		tf |= TF_NOREAL;
25205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&ru0.ru_utime, &cru0.ru_utime, &usrtime);
25215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&ru0.ru_stime, &cru0.ru_stime, &systime);
25225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
25235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&ru1.ru_utime, &ru0.ru_utime, &usrtime);
25245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&usrtime, &j_usrtime, &usrtime);
25255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&ru1.ru_stime, &ru0.ru_stime, &systime);
25265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timeradd(&systime, &j_systime, &systime);
25275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(tf & TF_NOREAL)) {
25305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		timersub(&tv1, &tv0, &tv1);
25315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (tf & TF_POSIX)
25325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p_time(shl_out, true, tv1.tv_sec, tv1.tv_usec,
25335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    5, "real ", "\n");
25345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
25355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p_time(shl_out, false, tv1.tv_sec, tv1.tv_usec,
25365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    5, null, " real ");
25375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tf & TF_POSIX)
25395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, true, usrtime.tv_sec, usrtime.tv_usec,
25405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, "user ", "\n");
25415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
25425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, false, usrtime.tv_sec, usrtime.tv_usec,
25435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, null, " user ");
25445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (tf & TF_POSIX)
25455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, true, systime.tv_sec, systime.tv_usec,
25465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, "sys  ", "\n");
25475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
25485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p_time(shl_out, false, systime.tv_sec, systime.tv_usec,
25495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    5, null, " system\n");
25505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shf_flush(shl_out);
25515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
25535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
25545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
25565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutimex_hook(struct op *t, char **volatile *app)
25575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
25585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **wp = *app;
25595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc, i, j;
25605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Getopt opt;
25615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ksh_getopt_reset(&opt, 0);
256303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* start at the start */
256403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	opt.optind = 0;
25655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt((const char **)wp, &opt, ":p")) != -1)
25665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
25675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'p':
25685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			t->str[0] |= TF_POSIX;
25695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
25705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
257103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorf("time: -%s %s", opt.optarg,
257203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "unknown option");
25735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case ':':
257403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			errorf("time: -%s %s", opt.optarg,
257503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "requires an argument");
25765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
25775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Copy command words down over options. */
25785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (opt.optind != 0) {
25795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0; i < opt.optind; i++)
25805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(wp[i], ATEMP);
25815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0, j = opt.optind; (wp[i] = wp[j]); i++, j++)
25825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
25835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
25845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!wp[0])
25855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		t->str[0] |= TF_NOARGS;
25865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*app = wp;
25875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
25885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* exec with no args - args case is taken care of in comexec() */
25905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
25915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_exec(const char **wp MKSH_A_UNUSED)
25925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
25935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
25945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
25955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* make sure redirects stay in place */
25965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (e->savefd != NULL) {
25975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (i = 0; i < NUFILE; i++) {
25985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (e->savefd[i] > 0)
25995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				close(e->savefd[i]);
26005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/*
26015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * keep all file descriptors > 2 private for ksh,
26025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 * but not for POSIX or legacy/kludge sh
26035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			 */
26045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!Flag(FPOSIX) && !Flag(FSH) && i > 2 &&
26055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    e->savefd[i])
26065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				fcntl(i, F_SETFD, FD_CLOEXEC);
26075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		e->savefd = NULL;
26095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
26115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
26125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_MKNOD
26145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
26155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_mknod(const char **wp)
26165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
26175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, optc, rv = 0;
26185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool ismkfifo = false;
26195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char **argv;
26205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	void *set = NULL;
26215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode_t mode = 0, oldmode = 0;
26225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, "m:")) != -1) {
26245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
26255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'm':
26265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			set = setmode(builtin_opt.optarg);
26275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (set == NULL) {
26285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("invalid file mode");
26295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
26305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
26315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			mode = getmode(set, (mode_t)(DEFFILEMODE));
263203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			free_ossetmode(set);
26335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
26345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
26355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_usage;
26365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	argv = &wp[builtin_opt.optind];
26395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argv[0] == NULL)
26405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto c_mknod_usage;
26415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; argv[argc]; argc++)
26425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
26435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argc == 2 && argv[1][0] == 'p')
26445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ismkfifo = true;
26455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (argc != 4 || (argv[1][0] != 'b' && argv[1][0] != 'c'))
26465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto c_mknod_usage;
26475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (set != NULL)
26495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		oldmode = umask((mode_t)0);
26505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
26515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mode = DEFFILEMODE;
26525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mode |= (argv[1][0] == 'b') ? S_IFBLK :
26545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (argv[1][0] == 'c') ? S_IFCHR : 0;
26555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!ismkfifo) {
26575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unsigned long majnum, minnum;
26585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		dev_t dv;
26595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *c;
26605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		majnum = strtoul(argv[2], &c, 0);
26625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == argv[2]) || (*c != '\0')) {
266303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("non-numeric %s %s '%s'", "device", "major", argv[2]);
26645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
26655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		minnum = strtoul(argv[3], &c, 0);
26675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((c == argv[3]) || (*c != '\0')) {
266803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("non-numeric %s %s '%s'", "device", "minor", argv[3]);
26695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
26705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		dv = makedev(majnum, minnum);
26725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned long)(major(dv)) != majnum) {
267303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s %s too large: %lu", "device", "major", majnum);
26745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
26755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned long)(minor(dv)) != minnum) {
267703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s %s too large: %lu", "device", "minor", minnum);
26785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_err;
26795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
26805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (mknod(argv[0], mode, dv))
26815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto c_mknod_failed;
26825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (mkfifo(argv[0], mode)) {
26835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_failed:
268403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", argv[0], strerror(errno));
26855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_err:
26865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = 1;
26875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
26885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
26895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (set)
26905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		umask(oldmode);
26915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
26925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c_mknod_usage:
269303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bi_errorf("%s: %s", "usage", "mknod [-m mode] name b|c major minor");
269403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	bi_errorf("%s: %s", "usage", "mknod [-m mode] name p");
26955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
26965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
26975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
26985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
269903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*-
270003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra   test(1) accepts the following grammar:
27015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	oexpr	::= aexpr | aexpr "-o" oexpr ;
27025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	aexpr	::= nexpr | nexpr "-a" aexpr ;
27035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	nexpr	::= primary | "!" nexpr ;
27045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	primary	::= unary-operator operand
27055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| operand binary-operator operand
27065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| operand
27075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		| "(" oexpr ")"
27085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
27095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unary-operator ::= "-a"|"-r"|"-w"|"-x"|"-e"|"-f"|"-d"|"-c"|"-b"|"-p"|
27115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			   "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|
27125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			   "-L"|"-h"|"-S"|"-H";
27135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
27155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "-nt"|"-ot"|"-ef"|
27165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    "<"|">"	# rules used for [[ .. ]] expressions
27175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    ;
27185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	operand ::= <any thing>
27195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru*/
27205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
272103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* POSIX says > 1 for errors */
272203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define T_ERR_EXIT	2
27235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
27255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_test(const char **wp)
27265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
27275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int argc, res;
27285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_env te;
27295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.flags = 0;
27315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.isa = ptest_isa;
27325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.getopnd = ptest_getopnd;
27335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.eval = test_eval;
27345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.error = ptest_error;
27355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (argc = 0; wp[argc]; argc++)
27375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
27385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (strcmp(wp[0], "[") == 0) {
27405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (strcmp(wp[--argc], "]") != 0) {
27415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("missing ]");
27425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (T_ERR_EXIT);
27435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
27445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
27455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.pos.wp = wp + 1;
27475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te.wp_end = wp + argc;
27485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
27495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
27505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Handle the special cases from POSIX.2, section 4.62.4.
27515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Implementation of all the rules isn't necessary since
27525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * our parser does the right thing for the omitted steps.
27535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
27545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (argc <= 5) {
275503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		const char **owp = wp, **owpend = te.wp_end;
27565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int invert = 0;
27575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Test_op op;
27585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		const char *opnd1, *opnd2;
27595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
276003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (argc >= 2 && ((*te.isa)(&te, TM_OPAREN))) {
276103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			te.pos.wp = te.wp_end - 1;
276203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if ((*te.isa)(&te, TM_CPAREN)) {
276303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				argc -= 2;
276403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				te.wp_end--;
276503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				te.pos.wp = owp + 2;
276603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else {
276703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				te.pos.wp = owp + 1;
276803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				te.wp_end = owpend;
276903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
277003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
277103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
27725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while (--argc >= 0) {
27735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((*te.isa)(&te, TM_END))
27745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (!0);
27755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (argc == 3) {
27765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				opnd1 = (*te.getopnd)(&te, TO_NONOP, 1);
27775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if ((op = (*te.isa)(&te, TM_BINOP))) {
27785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					opnd2 = (*te.getopnd)(&te, op, 1);
27795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					res = (*te.eval)(&te, op, opnd1,
27805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    opnd2, 1);
27815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (te.flags & TEF_ERROR)
27825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						return (T_ERR_EXIT);
27835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					if (invert & 1)
27845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru						res = !res;
27855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return (!res);
27865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
27875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* back up to opnd1 */
27885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				te.pos.wp--;
27895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
27905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (argc == 1) {
27915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				opnd1 = (*te.getopnd)(&te, TO_NONOP, 1);
27925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				res = (*te.eval)(&te, TO_STNZE, opnd1,
27935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    NULL, 1);
27945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (invert & 1)
27955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					res = !res;
27965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (!res);
27975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
27985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((*te.isa)(&te, TM_NOT)) {
27995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				invert++;
28005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			} else
28015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				break;
28025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
28035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		te.pos.wp = owp + 1;
280403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		te.wp_end = owpend;
28055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
28065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (test_parse(&te));
28085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
28095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
28115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Generic test routines.
28125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
28135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTest_op
28155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_isop(Test_meta meta, const char *s)
28165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
28175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char sc1;
28185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct t_op *tbl;
28195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tbl = meta == TM_UNOP ? u_ops : b_ops;
28215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*s) {
28225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sc1 = s[1];
28235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; tbl->op_text[0]; tbl++)
28245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (sc1 == tbl->op_text[1] && !strcmp(s, tbl->op_text))
28255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (tbl->op_num);
28265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
28275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (TO_NONOP);
28285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
28295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
28315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
28325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    bool do_eval)
28335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
28345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i, s;
28355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	size_t k;
28365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct stat b1, b2;
28375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	mksh_ari_t v1, v2;
28385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
28395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!do_eval)
28405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
28415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
284203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	switch (op) {
284303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
28445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
28455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Unary Operators
28465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
284703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
284803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -n */
284903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STNZE:
28505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (*opnd1 != '\0');
285103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
285203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -z */
285303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STZER:
28545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (*opnd1 == '\0');
285503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
285603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -o */
285703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_OPTION:
28585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((i = *opnd1) == '!' || i == '?')
28595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opnd1++;
28605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((k = option(opnd1)) == (size_t)-1)
28615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
28625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (i == '?' ? 1 : i == '!' ? !Flag(k) : Flag(k));
286303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
286403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -r */
286503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILRD:
286603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* LINTED use of access */
286703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (access(opnd1, R_OK) == 0);
286803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
286903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -w */
287003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILWR:
287103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* LINTED use of access */
287203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (access(opnd1, W_OK) == 0);
287303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
287403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -x */
287503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEX:
287603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (ksh_access(opnd1, X_OK) == 0);
287703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
287803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -a */
287903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILAXST:
288003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -e */
288103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEXST:
28825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0);
288303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
288403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -r */
288503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILREG:
28865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode));
288703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
288803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -d */
288903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILID:
28905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode));
289103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
289203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -c */
289303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILCDEV:
28945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode));
289503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
289603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -b */
289703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILBDEV:
28985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode));
289903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
290003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -p */
290103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILFIFO:
29025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode));
290303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
290403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -h or -L */
290503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSYM:
29065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode));
290703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
290803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -S */
290903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSOCK:
29105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode));
291103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
291203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -H => HP context dependent files (directories) */
291303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILCDF:
291403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef S_ISCDF
291503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	{
291603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		char *nv;
291703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
291803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
291903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * Append a + to filename and check to see if result is
292003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * a setuid directory. CDF stuff in general is hookey,
292103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * since it breaks for, e.g., the following sequence:
292203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * echo hi >foo+; mkdir foo; echo bye >foo/default;
292303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * chmod u+s foo (foo+ refers to the file with hi in it,
292403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * there is no way to get at the file with bye in it;
292503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * please correct me if I'm wrong about this).
292603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 */
292703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
292803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		nv = shf_smprintf("%s+", opnd1);
292903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		i = (stat(nv, &b1) == 0 && S_ISCDF(b1.st_mode));
293003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		afree(nv, ATEMP);
293103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (i);
293203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
293303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else
29345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
293503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
293603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
293703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -u */
293803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSETU:
29395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
29405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISUID) == S_ISUID);
294103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
294203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -g */
294303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSETG:
29445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
29455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISGID) == S_ISGID);
294603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
294703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -k */
294803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILSTCK:
29495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef S_ISVTX
29505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
29515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (b1.st_mode & S_ISVTX) == S_ISVTX);
29525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
29535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
29545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
295503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
295603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -s */
295703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILGZ:
29585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && b1.st_size > 0L);
295903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
296003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -t */
296103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILTT:
29625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (opnd1 && !bi_getn(opnd1, &i)) {
29635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			te->flags |= TEF_ERROR;
29645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			i = 0;
29655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
29665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			i = isatty(opnd1 ? i : 0);
29675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (i);
296803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
296903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -O */
297003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILUID:
29715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid);
297203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
297303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -G */
297403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILGID:
29755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 && b1.st_gid == getegid());
297603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
29775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
29785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Binary Operators
29795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
298003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
298103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* = */
298203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STEQL:
29835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_DBRACKET)
29845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (gmatchx(opnd1, opnd2, false));
29855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) == 0);
298603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
298703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* != */
298803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STNEQ:
29895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_DBRACKET)
29905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (!gmatchx(opnd1, opnd2, false));
29915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) != 0);
299203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
299303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* < */
299403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STLT:
29955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) < 0);
299603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
299703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* > */
299803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_STGT:
29995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (strcmp(opnd1, opnd2) > 0);
300003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
300103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -eq */
300203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTEQ:
300303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ne */
300403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTNE:
300503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ge */
300603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTGE:
300703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -gt */
300803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTGT:
300903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -le */
301003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTLE:
301103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -lt */
301203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_INTLT:
30135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) ||
30145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) {
30155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* error already printed.. */
30165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			te->flags |= TEF_ERROR;
30175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
30185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
301903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (op) {
30205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTEQ:
30215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 == v2);
30225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTNE:
30235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 != v2);
30245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTGE:
30255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 >= v2);
30265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTGT:
30275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 > v2);
30285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTLE:
30295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 <= v2);
30305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case TO_INTLT:
30315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (v1 < v2);
303203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
303303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* NOTREACHED */
303403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
30355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
303603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* NOTREACHED */
303703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
303803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -nt */
303903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILNT:
304003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
304103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * ksh88/ksh93 succeed if file2 can't be stated
30425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (subtly different from 'does not exist').
30435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
30445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd1, &b1) == 0 &&
30455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((s = stat(opnd2, &b2)) == 0 &&
30465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_mtime > b2.st_mtime) || s < 0));
304703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
304803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ot */
304903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILOT:
305003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
305103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * ksh88/ksh93 succeed if file1 can't be stated
30525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (subtly different from 'does not exist').
30535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
30545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat(opnd2, &b2) == 0 &&
30555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (((s = stat(opnd1, &b1)) == 0 &&
30565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_mtime < b2.st_mtime) || s < 0));
305703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
305803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* -ef */
305903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_FILEQ:
30605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 &&
30615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino);
306203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
306303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* all other cases */
306403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_NONOP:
306503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case TO_NONNULL:
306603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* throw the error */
306703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		break;
30685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
30695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(*te->error)(te, 0, "internal error: unknown op");
30705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
30715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
30725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
30745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_parse(Test_env *te)
30755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
30765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
30775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rv = test_oexpr(te, 1);
30795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && !(*te->isa)(te, TM_END))
30815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(*te->error)(te, 0, "unexpected operator/operand");
30825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((te->flags & TEF_ERROR) ? T_ERR_EXIT : !rv);
30845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
30855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
30875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_oexpr(Test_env *te, bool do_eval)
30885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
30895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
30905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((rv = test_aexpr(te, do_eval)))
30925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		do_eval = false;
30935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_OR))
30945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (test_oexpr(te, do_eval) || rv);
30955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
30965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
30975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
30985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
30995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_aexpr(Test_env *te, bool do_eval)
31005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
31025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(rv = test_nexpr(te, do_eval)))
31045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		do_eval = false;
31055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_AND))
31065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (test_aexpr(te, do_eval) && rv);
31075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
31085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
31095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
31115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_nexpr(Test_env *te, bool do_eval)
31125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_NOT))
31145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (!test_nexpr(te, do_eval));
31155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (test_primary(te, do_eval));
31165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
31175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
31195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutest_primary(Test_env *te, bool do_eval)
31205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *opnd1, *opnd2;
31225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv;
31235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op op;
31245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->flags & TEF_ERROR)
31265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
31275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((*te->isa)(te, TM_OPAREN)) {
31285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = test_oexpr(te, do_eval);
31295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (te->flags & TEF_ERROR)
31305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
31315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(*te->isa)(te, TM_CPAREN)) {
313203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			(*te->error)(te, 0, "missing )");
31335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
31345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
31355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (rv);
31365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
31375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
31385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Binary should have precedence over unary in this case
31395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * so that something like test \( -f = -f \) is accepted
31405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
31415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((te->flags & TEF_DBRACKET) || (&te->pos.wp[1] < te->wp_end &&
31425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    !test_isop(TM_BINOP, te->pos.wp[1]))) {
31435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((op = (*te->isa)(te, TM_UNOP))) {
31445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* unary expression */
31455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			opnd1 = (*te->getopnd)(te, op, do_eval);
31465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!opnd1) {
31475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				(*te->error)(te, -1, "missing argument");
31485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (0);
31495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
31505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return ((*te->eval)(te, op, opnd1, NULL, do_eval));
31525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
31535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
31545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	opnd1 = (*te->getopnd)(te, TO_NONOP, do_eval);
31555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!opnd1) {
31565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(*te->error)(te, 0, "expression expected");
31575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
31585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
31595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((op = (*te->isa)(te, TM_BINOP))) {
31605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* binary expression */
31615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		opnd2 = (*te->getopnd)(te, op, do_eval);
31625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!opnd2) {
31635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			(*te->error)(te, -1, "missing second argument");
31645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (0);
31655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
31665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return ((*te->eval)(te, op, opnd1, opnd2, do_eval));
31685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
31695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return ((*te->eval)(te, TO_STNZE, opnd1, NULL, do_eval));
31705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
31715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
31735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Plain test (test and [ .. ]) specific routines.
31745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
31755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
31775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Test if the current token is a whatever. Accepts the current token if
31785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it is. Returns 0 if it is not, non-zero if it is (in the case of
31795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * TM_UNOP and TM_BINOP, the returned value is a Test_op).
31805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
31815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Test_op
31825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_isa(Test_env *te, Test_meta meta)
31835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
31845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Order important - indexed by Test_meta values */
31855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static const char *const tokens[] = {
31865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		"-o", "-a", "!", "(", ")"
31875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	};
31885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Test_op rv;
31895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->pos.wp >= te->wp_end)
31915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (meta == TM_END ? TO_NONNULL : TO_NONOP);
31925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
31935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (meta == TM_UNOP || meta == TM_BINOP)
31945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = test_isop(meta, *te->pos.wp);
31955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (meta == TM_END)
31965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = TO_NONOP;
31975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
31985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = !strcmp(*te->pos.wp, tokens[(int)meta]) ?
31995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    TO_NONNULL : TO_NONOP;
32005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Accept the token? */
32025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rv != TO_NONOP)
32035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		te->pos.wp++;
32045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
32065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const char *
32095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_getopnd(Test_env *te, Test_op op, bool do_eval MKSH_A_UNUSED)
32105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (te->pos.wp >= te->wp_end)
32125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (op == TO_FILTT ? "1" : NULL);
32135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (*te->pos.wp++);
32145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
32175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruptest_error(Test_env *te, int ofs, const char *msg)
32185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *op;
32205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	te->flags |= TEF_ERROR;
32225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((op = te->pos.wp + ofs >= te->wp_end ? NULL : te->pos.wp[ofs]))
32235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s: %s", op, msg);
32245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
32255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s", msg);
32265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
32275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_NO_LIMITS
32295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SOFT	0x1
32305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define HARD	0x2
32315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct limits {
32335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *name;
32345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int resource;		/* resource to get/set */
32355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int factor;		/* multiply by to get rlim_{cur,max} values */
32365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char option;
32375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
32385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void print_ulimit(const struct limits *, int);
32405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int set_ulimit(const struct limits *, const char *, int);
32415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Magic to divine the 'm' and 'v' limits */
32435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AS
32455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
32465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    !defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
32475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_AS
32485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(RLIMIT_VMEM)
32495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
32505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_AS
32515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
32525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_VMEM
32535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_RSS
32585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef ULIMIT_V_IS_VMEM
32595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_RSS
32605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
32615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_VMEM
32625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
32635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_RSS
32645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)
32665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#undef ULIMIT_M_IS_RSS
32675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
32715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_V_IS_VMEM
32725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
32755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    (!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
32765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define ULIMIT_M_IS_VMEM
32775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
32805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru    (RLIMIT_VMEM == RLIMIT_AS)
32815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#undef ULIMIT_M_IS_VMEM
32825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
32855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
32865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_ulimit(const char **wp)
32875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
32885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static const struct limits limits[] = {
32895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* do not use options -H, -S or -a or change the order */
32905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_CPU
32915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "time(cpu-seconds)", RLIMIT_CPU, 1, 't' },
32925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_FSIZE
32945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
32955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_CORE
32975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
32985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
32995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_DATA
33005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "data(KiB)", RLIMIT_DATA, 1024, 'd' },
33015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_STACK
33035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "stack(KiB)", RLIMIT_STACK, 1024, 's' },
33045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_MEMLOCK
33065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l' },
33075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NOFILE
33095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
33105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NPROC
33125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "processes", RLIMIT_NPROC, 1, 'p' },
33135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SWAP
33155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "swap(KiB)", RLIMIT_SWAP, 1024, 'w' },
33165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_LOCKS
33185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "flocks", RLIMIT_LOCKS, -1, 'L' },
33195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_TIME
33215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "humantime(seconds)", RLIMIT_TIME, 1, 'T' },
33225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NOVMON
33245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "vnodemonitors", RLIMIT_NOVMON, 1, 'V' },
33255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SIGPENDING
33275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "sigpending", RLIMIT_SIGPENDING, 1, 'i' },
33285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_MSGQUEUE
33305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q' },
33315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AIO_MEM
33335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M' },
33345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_AIO_OPS
33365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "AIOoperations", RLIMIT_AIO_OPS, 1, 'O' },
33375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_TCACHE
33395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "cachedthreads", RLIMIT_TCACHE, 1, 'C' },
33405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_SBSIZE
33425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B' },
33435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_PTHREAD
33455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "threadsperprocess", RLIMIT_PTHREAD, 1, 'P' },
33465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_NICE
33485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "maxnice", RLIMIT_NICE, 1, 'e' },
33495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef RLIMIT_RTPRIO
33515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "maxrtprio", RLIMIT_RTPRIO, 1, 'r' },
33525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_M_IS_RSS)
33545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "resident-set(KiB)", RLIMIT_RSS, 1024, 'm' },
33555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(ULIMIT_M_IS_VMEM)
33565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "memory(KiB)", RLIMIT_VMEM, 1024, 'm' },
33575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if defined(ULIMIT_V_IS_VMEM)
33595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v' },
33605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif defined(ULIMIT_V_IS_AS)
33615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ "address-space(KiB)", RLIMIT_AS, 1024, 'v' },
33625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
33635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		{ NULL, 0, 0, 0 }
33645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	};
33655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static char opts[3 + NELEM(limits)];
33665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int how = SOFT | HARD, optc, what = 'f';
33675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool all = false;
33685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const struct limits *l;
33695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!opts[0]) {
33715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* build options string on first call - yuck */
33725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *p = opts;
33735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*p++ = 'H'; *p++ = 'S'; *p++ = 'a';
33755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (l = limits; l->name; l++)
33765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*p++ = l->option;
33775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*p = '\0';
33785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
33795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
33815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
33825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'H':
33835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			how = HARD;
33845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
33855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'S':
33865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			how = SOFT;
33875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
33885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'a':
33895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			all = true;
33905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
33915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
339203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", "usage",
339303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "ulimit [-acdfHLlmnpSsTtvw] [value]");
33945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
33955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		default:
33965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			what = optc;
33975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
33985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (l = limits; l->name && l->option != what; l++)
34005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		;
34015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!l->name) {
34025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		internal_warningf("ulimit: %c", what);
34035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
34045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (wp[builtin_opt.optind]) {
34075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (all || wp[builtin_opt.optind + 1]) {
34085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("too many arguments");
34095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
34105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
34115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (set_ulimit(l, wp[builtin_opt.optind], how));
34125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!all)
34145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		print_ulimit(l, how);
34155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else for (l = limits; l->name; l++) {
34165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shprintf("%-20s ", l->name);
34175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		print_ulimit(l, how);
34185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
34205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
34215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
34235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruset_ulimit(const struct limits *l, const char *v, int how)
34245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
34255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rlim_t val = (rlim_t)0;
34265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rlimit limit;
34275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (strcmp(v, "unlimited") == 0)
34295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = (rlim_t)RLIM_INFINITY;
34305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
34315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		mksh_ari_t rval;
34325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!evaluate(v, &rval, KSH_RETURN_ERROR, false))
34345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
34355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
34365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * Avoid problems caused by typos that evaluate misses due
34375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * to evaluating unset parameters to 0...
34385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * If this causes problems, will have to add parameter to
34395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * evaluate() to control if unset params are 0 or an error.
34405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
34415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!rval && !ksh_isdigit(v[0])) {
34425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("invalid %s limit: %s", l->name, v);
34435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
34445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
34455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = (rlim_t)((rlim_t)rval * l->factor);
34465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (getrlimit(l->resource, &limit) < 0) {
344903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* some can't be read, e.g. Linux RLIMIT_LOCKS */
34505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_cur = RLIM_INFINITY;
34515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_max = RLIM_INFINITY;
34525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & SOFT)
34545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_cur = val;
34555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & HARD)
34565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		limit.rlim_max = val;
34575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!setrlimit(l->resource, &limit))
34585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
34595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (errno == EPERM)
34605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("%s exceeds allowable %s limit", v, l->name);
34615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
34625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("bad %s limit: %s", l->name, strerror(errno));
34635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
34645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
34655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
34675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprint_ulimit(const struct limits *l, int how)
34685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
34695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	rlim_t val = (rlim_t)0;
34705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct rlimit limit;
34715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (getrlimit(l->resource, &limit)) {
34735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("unknown\n", shl_stdout);
34745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
34755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
34765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (how & SOFT)
34775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = limit.rlim_cur;
34785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (how & HARD)
34795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		val = limit.rlim_max;
34805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (val == (rlim_t)RLIM_INFINITY)
34815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_puts("unlimited\n", shl_stdout);
34825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else
34835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shprintf("%ld\n", (long)(val / l->factor));
34845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
34855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
34865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
34885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_rename(const char **wp)
34895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
34905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
34915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
349203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
349303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
349403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
349503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
349603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
349703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
349803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* check for exactly two arguments */
349903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] == NULL	/* first argument */ ||
350003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    wp[1] == NULL	/* second argument */ ||
350103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	    wp[2] != NULL	/* no further args please */)
350203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
350303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if ((rv = rename(wp[0], wp[1])) != 0) {
35045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = errno;
350503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", "failed", strerror(rv));
35065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
35075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
35095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
35105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
35125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_realpath(const char **wp)
35135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
35145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int rv = 1;
35155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *buf;
35165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
351703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
351803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
351903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
352003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
352103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
35225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
352303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* check for exactly one argument */
352403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] == NULL || wp[1] != NULL)
352503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
352603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if ((buf = do_realpath(wp[0])) == NULL) {
35275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = errno;
352803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s", wp[0], strerror(rv));
35295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((unsigned int)rv > 255)
35305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rv = 255;
35315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
35325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shprintf("%s\n", buf);
35335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(buf, ATEMP);
353403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rv = 0;
35355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
35365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
35375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
35385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
353903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
354003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint
354103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_cat(const char **wp)
354203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
354303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int fd = STDIN_FILENO, rv;
354403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t n, w;
354503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *fn = "<stdin>";
354603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *buf, *cp;
354703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define MKSH_CAT_BUFSIZ 4096
354803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
354903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((buf = malloc_osfunc(MKSH_CAT_BUFSIZ)) == NULL) {
355003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Toomem, (unsigned long)MKSH_CAT_BUFSIZ);
355103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		return (1);
355203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
355303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
355403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* parse options: POSIX demands we support "-u" as no-op */
355503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	while ((rv = ksh_getopt(wp, &builtin_opt, "u")) != -1) {
355603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		switch (rv) {
355703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 'u':
355803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* we already operate unbuffered */
355903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			break;
356003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		default:
356103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf(Tsynerr);
356203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			return (1);
356303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
356403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
356503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	wp += builtin_opt.optind;
356603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	rv = 0;
356703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
356803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	do {
356903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (*wp) {
357003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			fn = *wp++;
357103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (fn[0] == '-' && fn[1] == '\0')
357203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				fd = STDIN_FILENO;
357303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			else if ((fd = open(fn, O_RDONLY)) < 0) {
357403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = errno;
357503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", fn, strerror(rv));
357603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
357703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				continue;
357803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
357903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
358003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		while (/* CONSTCOND */ 1) {
358103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			n = blocking_read(fd, (cp = buf), MKSH_CAT_BUFSIZ);
358203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (n == -1) {
358303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (errno == EINTR) {
358403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* give the user a chance to ^C out */
358503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					intrcheck();
358603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* interrupted, try again */
358703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					continue;
358803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
358903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* an error occured during reading */
359003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = errno;
359103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", fn, strerror(rv));
359203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				rv = 1;
359303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
359403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			} else if (n == 0)
359503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* end of file reached */
359603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				break;
359703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			while (n) {
359803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				w = write(STDOUT_FILENO, cp, n);
359903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				if (w == -1) {
360003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (errno == EINTR)
360103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						/* interrupted, try again */
360203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						continue;
360303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					/* an error occured during writing */
360403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					rv = errno;
360503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("%s: %s", "<stdout>",
360603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    strerror(rv));
360703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					rv = 1;
360803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					if (fd != STDIN_FILENO)
360903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra						close(fd);
361003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					goto out;
361103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				}
361203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				n -= w;
361303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				cp += w;
361403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			}
361503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		}
361603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (fd != STDIN_FILENO)
361703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			close(fd);
361803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	} while (*wp);
361903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
362003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra out:
362103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	free_osfunc(buf);
362203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
362303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
362403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
362503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SELECT
362603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint
362703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_sleep(const char **wp)
362803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
362903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	struct timeval tv;
363003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int rv = 1;
363103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
363203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* skip argv[0] */
363303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++wp;
363403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (wp[0] && !strcmp(wp[0], "--"))
363503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* skip "--" (options separator) */
363603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		++wp;
363703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
363803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!wp[0] || wp[1])
363903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf(Tsynerr);
364003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else if (parse_usec(wp[0], &tv))
364103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("%s: %s '%s'", Tsynerr, strerror(errno), wp[0]);
364203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	else {
364303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK
364403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigset_t omask;
364503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
364603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* block SIGCHLD from interrupting us, though */
364703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
364803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
364903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (select(0, NULL, NULL, NULL, &tv) == 0 || errno == EINTR)
365003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*
365103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * strictly speaking only for SIGALRM, but the
365203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 * execution may be interrupted by other signals
365303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			 */
365403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			rv = 0;
365503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		else
365603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", Tselect, strerror(errno));
365703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_NOPROSPECTOFWORK
365803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigprocmask(SIG_SETMASK, &omask, NULL);
365903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
366003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
366103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (rv);
366203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
366303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
366403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
366503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if defined(ANDROID)
366603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int
366703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_android_lsmod(const char **wp MKSH_A_UNUSED)
366803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{
366903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	const char *cwp[3] = { "cat", "/proc/modules", NULL };
367003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
367103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	builtin_argv0 = cwp[0];
367203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	return (c_cat(cwp));
367303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra}
367403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif
3675