blob: 5b363784c60e3b72c20269a8a957facd9a0e7f07 [file] [log] [blame]
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001/* $OpenBSD: sh.h,v 1.35 2015/09/10 22:48:58 nicm Exp $ */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002/* $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00003/* $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $ */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07004/* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08005/* $OpenBSD: expand.h,v 1.7 2015/09/01 13:12:31 tedu Exp $ */
Thorsten Glaser811a5752013-07-25 14:24:45 +00006/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */
Elliott Hughes737fdce2014-08-07 12:59:26 -07007/* $OpenBSD: proto.h,v 1.35 2013/09/04 15:49:19 millert Exp $ */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07008/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
9/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
10
11/*-
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000012 * Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
Elliott Hughesa3c3f962017-04-12 16:52:30 -070013 * 2011, 2012, 2013, 2014, 2015, 2016, 2017
Elliott Hughesfc0307d2016-02-02 15:26:47 -080014 * mirabilos <m@mirbsd.org>
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070015 *
16 * Provided that these terms and disclaimer and all copyright notices
17 * are retained or reproduced in an accompanying document, permission
Geremy Condra03ebf062011-10-12 18:17:24 -070018 * is granted to deal in this work without restriction, including un‐
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070019 * limited rights to use, publicly perform, distribute, sell, modify,
20 * merge, give away, or sublicence.
21 *
Geremy Condra03ebf062011-10-12 18:17:24 -070022 * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070023 * the utmost extent permitted by applicable law, neither express nor
24 * implied; without malicious intent or gross negligence. In no event
25 * may a licensor, author or contributor be held liable for indirect,
26 * direct, other damage, loss, or other issues arising in any way out
27 * of dealing in the work, even if advised of the possibility of such
28 * damage or existence of a defect, except proven that it results out
Geremy Condra03ebf062011-10-12 18:17:24 -070029 * of said person’s immediate fault when using the work as intended.
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070030 */
31
32#ifdef __dietlibc__
33/* XXX imake style */
Geremy Condra03ebf062011-10-12 18:17:24 -070034#define _BSD_SOURCE /* live, BSD, live❣ */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070035#endif
36
37#if HAVE_SYS_PARAM_H
38#include <sys/param.h>
39#endif
40#include <sys/types.h>
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000041#if HAVE_BOTH_TIME_H
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070042#include <sys/time.h>
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000043#include <time.h>
44#elif HAVE_SYS_TIME_H
45#include <sys/time.h>
46#elif HAVE_TIME_H
47#include <time.h>
48#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070049#include <sys/ioctl.h>
50#if HAVE_SYS_SYSMACROS_H
51#include <sys/sysmacros.h>
52#endif
53#if HAVE_SYS_MKDEV_H
54#include <sys/mkdev.h>
55#endif
56#if HAVE_SYS_MMAN_H
57#include <sys/mman.h>
58#endif
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000059#if HAVE_SYS_RESOURCE_H
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070060#include <sys/resource.h>
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000061#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070062#include <sys/stat.h>
63#include <sys/wait.h>
64#include <dirent.h>
65#include <errno.h>
66#include <fcntl.h>
Elliott Hughes96b43632015-07-17 11:39:41 -070067#if HAVE_IO_H
68#include <io.h>
69#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070070#if HAVE_LIBGEN_H
71#include <libgen.h>
72#endif
73#if HAVE_LIBUTIL_H
74#include <libutil.h>
75#endif
76#include <limits.h>
77#if HAVE_PATHS_H
78#include <paths.h>
79#endif
80#include <pwd.h>
81#include <setjmp.h>
82#include <signal.h>
83#include <stdarg.h>
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070084#include <stddef.h>
85#if HAVE_STDINT_H
86#include <stdint.h>
87#endif
88#include <stdio.h>
89#include <stdlib.h>
90#include <string.h>
91#if HAVE_STRINGS_H
92#include <strings.h>
93#endif
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000094#if HAVE_TERMIOS_H
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -070095#include <termios.h>
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +000096#else
97/* shudder… */
98#include <termio.h>
99#endif
100#ifdef _ISC_UNIX
101/* XXX imake style */
102#include <sys/sioctl.h>
103#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700104#if HAVE_ULIMIT_H
105#include <ulimit.h>
106#endif
107#include <unistd.h>
108#if HAVE_VALUES_H
109#include <values.h>
110#endif
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800111#ifdef MIRBSD_BOOTFLOPPY
112#include <wchar.h>
113#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700114
115#undef __attribute__
116#if HAVE_ATTRIBUTE_BOUNDED
Elliott Hughes737fdce2014-08-07 12:59:26 -0700117#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__(x, y, z)))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700118#else
119#define MKSH_A_BOUNDED(x,y,z) /* nothing */
120#endif
121#if HAVE_ATTRIBUTE_FORMAT
Elliott Hughes737fdce2014-08-07 12:59:26 -0700122#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__(x, y, z)))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700123#else
124#define MKSH_A_FORMAT(x,y,z) /* nothing */
125#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700126#if HAVE_ATTRIBUTE_NORETURN
Geremy Condra03ebf062011-10-12 18:17:24 -0700127#define MKSH_A_NORETURN __attribute__((__noreturn__))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700128#else
129#define MKSH_A_NORETURN /* nothing */
130#endif
Elliott Hughes737fdce2014-08-07 12:59:26 -0700131#if HAVE_ATTRIBUTE_PURE
132#define MKSH_A_PURE __attribute__((__pure__))
133#else
134#define MKSH_A_PURE /* nothing */
135#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700136#if HAVE_ATTRIBUTE_UNUSED
Geremy Condra03ebf062011-10-12 18:17:24 -0700137#define MKSH_A_UNUSED __attribute__((__unused__))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700138#else
139#define MKSH_A_UNUSED /* nothing */
140#endif
141#if HAVE_ATTRIBUTE_USED
Geremy Condra03ebf062011-10-12 18:17:24 -0700142#define MKSH_A_USED __attribute__((__used__))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700143#else
144#define MKSH_A_USED /* nothing */
145#endif
146
147#if defined(MirBSD) && (MirBSD >= 0x09A1) && \
148 defined(__ELF__) && defined(__GNUC__) && \
149 !defined(__llvm__) && !defined(__NWCC__)
150/*
151 * We got usable __IDSTRING __COPYRIGHT __RCSID __SCCSID macros
152 * which work for all cases; no need to redefine them using the
153 * "portable" macros from below when we might have the "better"
154 * gcc+ELF specific macros or other system dependent ones.
155 */
156#else
157#undef __IDSTRING
158#undef __IDSTRING_CONCAT
159#undef __IDSTRING_EXPAND
160#undef __COPYRIGHT
161#undef __RCSID
162#undef __SCCSID
163#define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p
164#define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p)
Geremy Condra03ebf062011-10-12 18:17:24 -0700165#ifdef MKSH_DONT_EMIT_IDSTRING
166#define __IDSTRING(prefix, string) /* nothing */
167#else
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700168#define __IDSTRING(prefix, string) \
169 static const char __IDSTRING_EXPAND(__LINE__,prefix) [] \
170 MKSH_A_USED = "@(""#)" #prefix ": " string
Geremy Condra03ebf062011-10-12 18:17:24 -0700171#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700172#define __COPYRIGHT(x) __IDSTRING(copyright,x)
173#define __RCSID(x) __IDSTRING(rcsid,x)
174#define __SCCSID(x) __IDSTRING(sccsid,x)
175#endif
176
177#ifdef EXTERN
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700178__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.808 2017/04/12 17:38:46 tg Exp $");
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700179#endif
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700180#define MKSH_VERSION "R55 2017/04/12"
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000181
182/* arithmetic types: C implementation */
183#if !HAVE_CAN_INTTYPES
184#if !HAVE_CAN_UCBINTS
185typedef signed int int32_t;
186typedef unsigned int uint32_t;
187#else
188typedef u_int32_t uint32_t;
189#endif
190#endif
191
192/* arithmetic types: shell arithmetics */
193#ifdef MKSH_LEGACY_MODE
194/*
195 * POSIX demands these to be the C environment's long type
196 */
197typedef long mksh_ari_t;
198typedef unsigned long mksh_uari_t;
199#else
200/*
201 * These types are exactly 32 bit wide; signed and unsigned
202 * integer wraparound, even across division and modulo, for
203 * any shell code using them, is guaranteed.
204 */
205typedef int32_t mksh_ari_t;
206typedef uint32_t mksh_uari_t;
207#endif
208
209/* boolean type (no <stdbool.h> deliberately) */
210typedef unsigned char mksh_bool;
211#undef bool
212/* false MUST equal the same 0 as written by static storage initialisation */
213#undef false
214#undef true
215/* access macros for boolean type */
216#define bool mksh_bool
217/* values must have identity mapping between mksh_bool and short */
218#define false 0
219#define true 1
220/* make any-type into bool or short */
221#define tobool(cond) ((cond) ? true : false)
222
223/* char (octet) type: C implementation */
224#if !HAVE_CAN_INT8TYPE
225#if !HAVE_CAN_UCBINT8
226typedef unsigned char uint8_t;
227#else
228typedef u_int8_t uint8_t;
229#endif
230#endif
231
232/* other standard types */
233
234#if !HAVE_RLIM_T
235typedef unsigned long rlim_t;
236#endif
237
238#if !HAVE_SIG_T
239#undef sig_t
240typedef void (*sig_t)(int);
241#endif
242
243#ifdef MKSH_TYPEDEF_SIG_ATOMIC_T
244typedef MKSH_TYPEDEF_SIG_ATOMIC_T sig_atomic_t;
245#endif
246
247#ifdef MKSH_TYPEDEF_SSIZE_T
248typedef MKSH_TYPEDEF_SSIZE_T ssize_t;
249#endif
250
251/* un-do vendor damage */
252
253#undef BAD /* AIX defines that somewhere */
254#undef PRINT /* LynxOS defines that somewhere */
255#undef flock /* SCO UnixWare defines that to flock64 but ENOENT */
256
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700257
258#ifndef MKSH_INCLUDES_ONLY
259
260/* extra types */
261
Elliott Hughes96b43632015-07-17 11:39:41 -0700262/* getrusage does not exist on OS/2 kLIBC */
263#if !HAVE_GETRUSAGE && !defined(__OS2__)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700264#undef rusage
265#undef RUSAGE_SELF
266#undef RUSAGE_CHILDREN
267#define rusage mksh_rusage
Geremy Condra03ebf062011-10-12 18:17:24 -0700268#define RUSAGE_SELF 0
269#define RUSAGE_CHILDREN -1
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700270
271struct rusage {
272 struct timeval ru_utime;
273 struct timeval ru_stime;
274};
275#endif
276
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700277/* extra macros */
278
279#ifndef timerclear
280#define timerclear(tvp) \
281 do { \
282 (tvp)->tv_sec = (tvp)->tv_usec = 0; \
283 } while (/* CONSTCOND */ 0)
284#endif
285#ifndef timeradd
286#define timeradd(tvp, uvp, vvp) \
287 do { \
288 (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
289 (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
290 if ((vvp)->tv_usec >= 1000000) { \
291 (vvp)->tv_sec++; \
292 (vvp)->tv_usec -= 1000000; \
293 } \
294 } while (/* CONSTCOND */ 0)
295#endif
296#ifndef timersub
297#define timersub(tvp, uvp, vvp) \
298 do { \
299 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
300 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
301 if ((vvp)->tv_usec < 0) { \
302 (vvp)->tv_sec--; \
303 (vvp)->tv_usec += 1000000; \
304 } \
305 } while (/* CONSTCOND */ 0)
306#endif
307
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000308#ifdef MKSH__NO_PATH_MAX
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700309#undef PATH_MAX
310#else
311#ifndef PATH_MAX
Elliott Hughes50012062015-03-10 22:22:24 -0700312#ifdef MAXPATHLEN
313#define PATH_MAX MAXPATHLEN
314#else
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700315#define PATH_MAX 1024
316#endif
317#endif
Elliott Hughes50012062015-03-10 22:22:24 -0700318#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700319#ifndef SIZE_MAX
320#ifdef SIZE_T_MAX
321#define SIZE_MAX SIZE_T_MAX
322#else
323#define SIZE_MAX ((size_t)-1)
324#endif
325#endif
326#ifndef S_ISLNK
327#define S_ISLNK(m) ((m & 0170000) == 0120000)
328#endif
329#ifndef S_ISSOCK
330#define S_ISSOCK(m) ((m & 0170000) == 0140000)
331#endif
Geremy Condra03ebf062011-10-12 18:17:24 -0700332#if !defined(S_ISCDF) && defined(S_CDF)
333#define S_ISCDF(m) (S_ISDIR(m) && ((m) & S_CDF))
334#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700335#ifndef DEFFILEMODE
336#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
337#endif
338
Elliott Hughes96b43632015-07-17 11:39:41 -0700339
340/* determine ksh_NSIG: first, use the traditional definitions */
341#undef ksh_NSIG
342#if defined(NSIG)
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800343#define ksh_NSIG (NSIG)
Elliott Hughes96b43632015-07-17 11:39:41 -0700344#elif defined(_NSIG)
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800345#define ksh_NSIG (_NSIG)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700346#elif defined(SIGMAX)
Elliott Hughes96b43632015-07-17 11:39:41 -0700347#define ksh_NSIG (SIGMAX + 1)
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000348#elif defined(_SIGMAX)
Elliott Hughes96b43632015-07-17 11:39:41 -0700349#define ksh_NSIG (_SIGMAX + 1)
350#elif defined(NSIG_MAX)
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800351#define ksh_NSIG (NSIG_MAX)
Elliott Hughes737fdce2014-08-07 12:59:26 -0700352#else
353# error Please have your platform define NSIG.
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700354#endif
Elliott Hughes96b43632015-07-17 11:39:41 -0700355/* range-check them */
356#if (ksh_NSIG < 1)
Elliott Hughes737fdce2014-08-07 12:59:26 -0700357# error Your NSIG value is not positive.
Elliott Hughes96b43632015-07-17 11:39:41 -0700358#undef ksh_NSIG
359#endif
360/* second, see if the new POSIX definition is available */
361#ifdef NSIG_MAX
362#if (NSIG_MAX < 2)
363/* and usable */
364# error Your NSIG_MAX value is too small.
365#undef NSIG_MAX
366#elif (ksh_NSIG > NSIG_MAX)
367/* and realistic */
368# error Your NSIG value is larger than your NSIG_MAX value.
369#undef NSIG_MAX
370#else
371/* since it’s usable, prefer it */
372#undef ksh_NSIG
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800373#define ksh_NSIG (NSIG_MAX)
Elliott Hughes96b43632015-07-17 11:39:41 -0700374#endif
375/* if NSIG_MAX is now still defined, use sysconf(_SC_NSIG) at runtime */
376#endif
377/* third, for cpp without the error directive, default */
378#ifndef ksh_NSIG
379#define ksh_NSIG 64
Elliott Hughes737fdce2014-08-07 12:59:26 -0700380#endif
381
Elliott Hughesfc0307d2016-02-02 15:26:47 -0800382#define ksh_sigmask(sig) (((sig) < 1 || (sig) > 127) ? 255 : 128 + (sig))
383
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700384
385/* OS-dependent additions (functions, variables, by OS) */
386
Elliott Hughes96b43632015-07-17 11:39:41 -0700387#ifdef MKSH_EXE_EXT
388#undef MKSH_EXE_EXT
389#define MKSH_EXE_EXT ".exe"
390#else
391#define MKSH_EXE_EXT ""
392#endif
393
394#ifdef __OS2__
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700395#define MKSH_UNIXROOT "/@unixroot"
396#else
397#define MKSH_UNIXROOT ""
398#endif
399
400#ifdef MKSH_DOSPATH
401#ifndef __GNUC__
402# error GCC extensions needed later on
403#endif
Elliott Hughes96b43632015-07-17 11:39:41 -0700404#define MKSH_PATHSEPS ";"
405#define MKSH_PATHSEPC ';'
Elliott Hughes96b43632015-07-17 11:39:41 -0700406#else
407#define MKSH_PATHSEPS ":"
408#define MKSH_PATHSEPC ':'
Elliott Hughes96b43632015-07-17 11:39:41 -0700409#endif
410
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700411#if !HAVE_FLOCK_DECL
412extern int flock(int, int);
413#endif
414
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000415#if !HAVE_GETTIMEOFDAY
416#define mksh_TIME(tv) do { \
417 (tv).tv_usec = 0; \
418 (tv).tv_sec = time(NULL); \
419} while (/* CONSTCOND */ 0)
420#else
421#define mksh_TIME(tv) gettimeofday(&(tv), NULL)
422#endif
423
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700424#if !HAVE_GETRUSAGE
425extern int getrusage(int, struct rusage *);
426#endif
427
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000428#if !HAVE_MEMMOVE
429/* we assume either memmove or bcopy exist, at the moment */
430#define memmove(dst, src, len) bcopy((src), (dst), (len))
431#endif
432
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700433#if !HAVE_REVOKE_DECL
434extern int revoke(const char *);
435#endif
436
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000437#if defined(DEBUG) || !HAVE_STRERROR
Thorsten Glaser811a5752013-07-25 14:24:45 +0000438#undef strerror
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000439#define strerror /* poisoned */ dontuse_strerror
440#define cstrerror /* replaced */ cstrerror
441extern const char *cstrerror(int);
442#else
443#define cstrerror(errnum) ((const char *)strerror(errnum))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700444#endif
445
446#if !HAVE_STRLCPY
447size_t strlcpy(char *, const char *, size_t);
448#endif
449
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700450#ifdef __INTERIX
451/* XXX imake style */
452#define makedev mkdev
453extern int __cdecl seteuid(uid_t);
454extern int __cdecl setegid(gid_t);
455#endif
456
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000457#if defined(__COHERENT__)
458#ifndef O_ACCMODE
459/* this need not work everywhere, take care */
460#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
461#endif
462#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700463
Elliott Hughes737fdce2014-08-07 12:59:26 -0700464#ifndef O_BINARY
465#define O_BINARY 0
466#endif
467
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000468#ifdef MKSH__NO_SYMLINK
469#undef S_ISLNK
470#define S_ISLNK(m) (/* CONSTCOND */ 0)
471#define mksh_lstat stat
472#else
473#define mksh_lstat lstat
474#endif
475
476#if HAVE_TERMIOS_H
477#define mksh_ttyst struct termios
478#define mksh_tcget(fd,st) tcgetattr((fd), (st))
479#define mksh_tcset(fd,st) tcsetattr((fd), TCSADRAIN, (st))
480#else
481#define mksh_ttyst struct termio
482#define mksh_tcget(fd,st) ioctl((fd), TCGETA, (st))
483#define mksh_tcset(fd,st) ioctl((fd), TCSETAW, (st))
484#endif
485
Elliott Hughes737fdce2014-08-07 12:59:26 -0700486#ifndef ISTRIP
487#define ISTRIP 0
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700488#endif
489
490
491/* some useful #defines */
492#ifdef EXTERN
Geremy Condra03ebf062011-10-12 18:17:24 -0700493# define E_INIT(i) = i
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700494#else
Geremy Condra03ebf062011-10-12 18:17:24 -0700495# define E_INIT(i)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700496# define EXTERN extern
497# define EXTERN_DEFINED
498#endif
499
Geremy Condra03ebf062011-10-12 18:17:24 -0700500/* define bit in flag */
501#define BIT(i) (1 << (i))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700502#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700503
Geremy Condra03ebf062011-10-12 18:17:24 -0700504/*
505 * Make MAGIC a char that might be printed to make bugs more obvious, but
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700506 * not a char that is used often. Also, can't use the high bit as it causes
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000507 * portability problems (calling strchr(x, 0x80 | 'x') is error prone).
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700508 */
509#define MAGIC (7) /* prefix for *?[!{,} during expand */
510#define ISMAGIC(c) ((unsigned char)(c) == MAGIC)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700511
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700512EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000513
514#ifdef MKSH_LEGACY_MODE
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700515#define KSH_VERSIONNAME_ISLEGACY "LEGACY"
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000516#else
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700517#define KSH_VERSIONNAME_ISLEGACY "MIRBSD"
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000518#endif
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700519#ifdef MKSH_WITH_TEXTMODE
520#define KSH_VERSIONNAME_TEXTMODE " +TEXTMODE"
521#else
522#define KSH_VERSIONNAME_TEXTMODE ""
523#endif
524#ifndef KSH_VERSIONNAME_VENDOR_EXT
525#define KSH_VERSIONNAME_VENDOR_EXT ""
526#endif
527EXTERN const char initvsn[] E_INIT("KSH_VERSION=@(#)" KSH_VERSIONNAME_ISLEGACY \
528 " KSH " MKSH_VERSION KSH_VERSIONNAME_TEXTMODE KSH_VERSIONNAME_VENDOR_EXT);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700529#define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16)
530
Geremy Condra03ebf062011-10-12 18:17:24 -0700531EXTERN const char digits_uc[] E_INIT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
532EXTERN const char digits_lc[] E_INIT("0123456789abcdefghijklmnopqrstuvwxyz");
Elliott Hughes96b43632015-07-17 11:39:41 -0700533#define letters_uc (digits_uc + 10)
534#define letters_lc (digits_lc + 10)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700535
536/*
537 * Evil hack for const correctness due to API brokenness
538 */
539union mksh_cchack {
540 char *rw;
541 const char *ro;
542};
543union mksh_ccphack {
544 char **rw;
545 const char **ro;
546};
547
Thorsten Glaser811a5752013-07-25 14:24:45 +0000548/*
549 * Evil hack since casting uint to sint is implementation-defined
550 */
551typedef union {
552 mksh_ari_t i;
553 mksh_uari_t u;
554} mksh_ari_u;
555
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700556/* for const debugging */
557#if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \
558 !defined(__INTEL_COMPILER) && !defined(__SUNPRO_C)
559char *ucstrchr(char *, int);
560char *ucstrstr(char *, const char *);
561#undef strchr
562#define strchr ucstrchr
563#define strstr ucstrstr
564#define cstrchr(s,c) ({ \
565 union mksh_cchack in, out; \
566 \
567 in.ro = (s); \
568 out.rw = ucstrchr(in.rw, (c)); \
569 (out.ro); \
570})
571#define cstrstr(b,l) ({ \
572 union mksh_cchack in, out; \
573 \
574 in.ro = (b); \
575 out.rw = ucstrstr(in.rw, (l)); \
576 (out.ro); \
577})
578#define vstrchr(s,c) (cstrchr((s), (c)) != NULL)
579#define vstrstr(b,l) (cstrstr((b), (l)) != NULL)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700580#else /* !DEBUG, !gcc */
581#define cstrchr(s,c) ((const char *)strchr((s), (c)))
582#define cstrstr(s,c) ((const char *)strstr((s), (c)))
583#define vstrchr(s,c) (strchr((s), (c)) != NULL)
584#define vstrstr(b,l) (strstr((b), (l)) != NULL)
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000585#endif
586
587#if defined(DEBUG) || defined(__COVERITY__)
588#define mkssert(e) do { if (!(e)) exit(255); } while (/* CONSTCOND */ 0)
589#ifndef DEBUG_LEAKS
590#define DEBUG_LEAKS
591#endif
592#else
593#define mkssert(e) do { } while (/* CONSTCOND */ 0)
594#endif
595
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700596#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 551)
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000597#error Must run Build.sh to compile this.
Thorsten Glaser811a5752013-07-25 14:24:45 +0000598extern void thiswillneverbedefinedIhope(void);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000599int
600im_sorry_dave(void)
601{
602 /* I’m sorry, Dave. I’m afraid I can’t do that. */
603 return (thiswillneverbedefinedIhope());
604}
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700605#endif
606
607/* use this ipv strchr(s, 0) but no side effects in s! */
608#define strnul(s) ((s) + strlen(s))
609
610#define utf_ptradjx(src, dst) do { \
611 (dst) = (src) + utf_ptradj(src); \
612} while (/* CONSTCOND */ 0)
613
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000614#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
615#define strdupx(d, s, ap) do { \
616 (d) = strdup_i((s), (ap)); \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700617} while (/* CONSTCOND */ 0)
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000618#define strndupx(d, s, n, ap) do { \
619 (d) = strndup_i((s), (n), (ap)); \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700620} while (/* CONSTCOND */ 0)
621#else
622/* be careful to evaluate arguments only once! */
623#define strdupx(d, s, ap) do { \
624 const char *strdup_src = (s); \
625 char *strdup_dst = NULL; \
626 \
627 if (strdup_src != NULL) { \
628 size_t strdup_len = strlen(strdup_src) + 1; \
629 strdup_dst = alloc(strdup_len, (ap)); \
630 memcpy(strdup_dst, strdup_src, strdup_len); \
631 } \
632 (d) = strdup_dst; \
633} while (/* CONSTCOND */ 0)
634#define strndupx(d, s, n, ap) do { \
635 const char *strdup_src = (s); \
636 char *strdup_dst = NULL; \
637 \
638 if (strdup_src != NULL) { \
639 size_t strndup_len = (n); \
640 strdup_dst = alloc(strndup_len + 1, (ap)); \
641 memcpy(strdup_dst, strdup_src, strndup_len); \
642 strdup_dst[strndup_len] = '\0'; \
643 } \
644 (d) = strdup_dst; \
645} while (/* CONSTCOND */ 0)
646#endif
647
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700648#ifdef MKSH_SMALL
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700649#ifndef MKSH_NOPWNAM
650#define MKSH_NOPWNAM /* defined */
651#endif
652#ifndef MKSH_S_NOVI
653#define MKSH_S_NOVI 1
654#endif
655#endif
656
657#ifndef MKSH_S_NOVI
658#define MKSH_S_NOVI 0
659#endif
660
Geremy Condra03ebf062011-10-12 18:17:24 -0700661#if defined(MKSH_NOPROSPECTOFWORK) && !defined(MKSH_UNEMPLOYED)
662#define MKSH_UNEMPLOYED 1
663#endif
664
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000665#define NUFILE 32 /* Number of user-accessible files */
666#define FDBASE 10 /* First file usable by Shell */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000667
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700668/*
669 * simple grouping allocator
670 */
671
Geremy Condra03ebf062011-10-12 18:17:24 -0700672
673/* 0. OS API: where to get memory from and how to free it (grouped) */
674
675/* malloc(3)/realloc(3) -> free(3) for use by the memory allocator */
676#define malloc_osi(sz) malloc(sz)
677#define realloc_osi(p,sz) realloc((p), (sz))
678#define free_osimalloc(p) free(p)
679
680/* malloc(3)/realloc(3) -> free(3) for use by mksh code */
681#define malloc_osfunc(sz) malloc(sz)
682#define realloc_osfunc(p,sz) realloc((p), (sz))
683#define free_osfunc(p) free(p)
684
685#if HAVE_MKNOD
686/* setmode(3) -> free(3) */
687#define free_ossetmode(p) free(p)
688#endif
689
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000690#ifdef MKSH__NO_PATH_MAX
Geremy Condra03ebf062011-10-12 18:17:24 -0700691/* GNU libc: get_current_dir_name(3) -> free(3) */
692#define free_gnu_gcdn(p) free(p)
693#endif
694
695
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700696/* 1. internal structure */
Elliott Hughes77740fc2016-08-12 15:06:53 -0700697struct lalloc_common {
698 struct lalloc_common *next;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700699};
700
Elliott Hughes77740fc2016-08-12 15:06:53 -0700701#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
702struct lalloc_item {
703 struct lalloc_common *next;
704 size_t len;
705 char dummy[8192 - sizeof(struct lalloc_common *) - sizeof(size_t)];
706};
707#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700708
Elliott Hughes77740fc2016-08-12 15:06:53 -0700709/* 2. sizes */
710#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
711#define ALLOC_ITEM struct lalloc_item
712#define ALLOC_OVERHEAD 0
713#else
714#define ALLOC_ITEM struct lalloc_common
715#define ALLOC_OVERHEAD (sizeof(ALLOC_ITEM))
716#endif
717
718/* 3. group structure */
719typedef struct lalloc_common Area;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700720
721
722EXTERN Area aperm; /* permanent object space */
723#define APERM &aperm
724#define ATEMP &e->area
725
726/*
727 * flags (the order of these enums MUST match the order in misc.c(options[]))
728 */
729enum sh_flag {
730#define SHFLAGS_ENUMS
Elliott Hughes737fdce2014-08-07 12:59:26 -0700731#include "sh_flags.gen"
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700732 FNFLAGS /* (place holder: how many flags are there) */
733};
734
Geremy Condra03ebf062011-10-12 18:17:24 -0700735#define Flag(f) (shell_flags[(int)(f)])
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700736#define UTFMODE Flag(FUNICODE)
737
738/*
739 * parsing & execution environment
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000740 *
741 * note that kshlongjmp MUST NOT be passed 0 as second argument!
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700742 */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000743#ifdef MKSH_NO_SIGSETJMP
744#define kshjmp_buf jmp_buf
745#define kshsetjmp(jbuf) _setjmp(jbuf)
746#define kshlongjmp _longjmp
747#else
748#define kshjmp_buf sigjmp_buf
749#define kshsetjmp(jbuf) sigsetjmp((jbuf), 0)
750#define kshlongjmp siglongjmp
751#endif
752
753struct sretrace_info;
754struct yyrecursive_state;
755
756EXTERN struct sretrace_info *retrace_info E_INIT(NULL);
757EXTERN int subshell_nesting_type E_INIT(0);
758
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700759extern struct env {
Geremy Condra03ebf062011-10-12 18:17:24 -0700760 ALLOC_ITEM alloc_INT; /* internal, do not touch */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700761 Area area; /* temporary allocation area */
762 struct env *oenv; /* link to previous environment */
763 struct block *loc; /* local variables and functions */
764 short *savefd; /* original redirected fds */
765 struct temp *temps; /* temp files */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000766 /* saved parser recursion state */
767 struct yyrecursive_state *yyrecursive_statep;
768 kshjmp_buf jbuf; /* long jump back to env creator */
769 uint8_t type; /* environment type - see below */
770 uint8_t flags; /* EF_* */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700771} *e;
772
773/* struct env.type values */
774#define E_NONE 0 /* dummy environment */
775#define E_PARSE 1 /* parsing command # */
776#define E_FUNC 2 /* executing function # */
777#define E_INCL 3 /* including a file via . # */
778#define E_EXEC 4 /* executing command tree */
779#define E_LOOP 5 /* executing for/while # */
780#define E_ERRH 6 /* general error handler # */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000781#define E_GONE 7 /* hidden in child */
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700782#define E_EVAL 8 /* running eval # */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700783/* # indicates env has valid jbuf (see unwind()) */
784
785/* struct env.flag values */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700786#define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */
787#define EF_FAKE_SIGDIE BIT(2) /* hack to get info from unwind to quitenv */
788
789/* Do breaks/continues stop at env type e? */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000790#define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE || \
791 (t) == E_FUNC || (t) == E_INCL)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700792/* Do returns stop at env type e? */
793#define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL)
794
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +0000795/* values for kshlongjmp(e->jbuf, i) */
796/* note that i MUST NOT be zero */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700797#define LRETURN 1 /* return statement */
798#define LEXIT 2 /* exit statement */
799#define LERROR 3 /* errorf() called */
800#define LLEAVE 4 /* untrappable exit/error */
801#define LINTR 5 /* ^C noticed */
802#define LBREAK 6 /* break statement */
803#define LCONTIN 7 /* continue statement */
804#define LSHELL 8 /* return to interactive shell() */
805#define LAEXPR 9 /* error in arithmetic expression */
806
Geremy Condra03ebf062011-10-12 18:17:24 -0700807/* sort of shell global state */
808EXTERN pid_t procpid; /* PID of executing process */
809EXTERN int exstat; /* exit status */
810EXTERN int subst_exstat; /* exit status of last $(..)/`..` */
811EXTERN struct tbl *vp_pipest; /* global PIPESTATUS array */
812EXTERN short trap_exstat; /* exit status before running a trap */
813EXTERN uint8_t trap_nested; /* running nested traps */
814EXTERN uint8_t shell_flags[FNFLAGS];
815EXTERN const char *kshname; /* $0 */
816EXTERN struct {
817 uid_t kshuid_v; /* real UID of shell */
818 uid_t ksheuid_v; /* effective UID of shell */
819 gid_t kshgid_v; /* real GID of shell */
820 gid_t kshegid_v; /* effective GID of shell */
821 pid_t kshpgrp_v; /* process group of shell */
822 pid_t kshppid_v; /* PID of parent of shell */
823 pid_t kshpid_v; /* $$, shell PID */
824} rndsetupstate;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700825
Geremy Condra03ebf062011-10-12 18:17:24 -0700826#define kshpid rndsetupstate.kshpid_v
827#define kshpgrp rndsetupstate.kshpgrp_v
828#define kshuid rndsetupstate.kshuid_v
829#define ksheuid rndsetupstate.ksheuid_v
830#define kshgid rndsetupstate.kshgid_v
831#define kshegid rndsetupstate.kshegid_v
832#define kshppid rndsetupstate.kshppid_v
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -0700833
834
835/* option processing */
836#define OF_CMDLINE 0x01 /* command line */
837#define OF_SET 0x02 /* set builtin */
838#define OF_SPECIAL 0x04 /* a special variable changing */
839#define OF_INTERNAL 0x08 /* set internally by shell */
840#define OF_FIRSTTIME 0x10 /* as early as possible, once */
841#define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL)
842
Geremy Condra03ebf062011-10-12 18:17:24 -0700843/* null value for variable; comparison pointer for unset */
844EXTERN char null[] E_INIT("");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700845
846/* string pooling: do we rely on the compiler? */
847#ifndef HAVE_STRING_POOLING
848/* no, we use our own, saves quite some space */
849#elif HAVE_STRING_POOLING == 2
850/* “on demand” */
851#ifdef __GNUC__
852/* only for GCC 4 or later, older ones can get by without */
853#if __GNUC__ < 4
854#undef HAVE_STRING_POOLING
Geremy Condra03ebf062011-10-12 18:17:24 -0700855#endif
Elliott Hughes77740fc2016-08-12 15:06:53 -0700856#else
857/* not GCC, default to on */
858#endif
859#elif HAVE_STRING_POOLING == 0
860/* default to on, unless explicitly set to 0 */
861#undef HAVE_STRING_POOLING
862#endif
863
864#ifndef HAVE_STRING_POOLING /* helpers for pooled strings */
865EXTERN const char T4spaces[] E_INIT(" ");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700866#define T1space (Treal_sp2 + 5)
867#define Tcolsp (Tf_sD_ + 2)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700868EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
869#define TC_IFSWS (TC_LEX1 + 7)
870EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_");
871#define Tspdollaru (TFCEDIT_dollaru + 18)
872EXTERN const char Tsgdot[] E_INIT("*=.");
873EXTERN const char Taugo[] E_INIT("augo");
874EXTERN const char Tbracket[] E_INIT("[");
875#define Tdot (Tsgdot + 2)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700876#define Talias (Tunalias + 2)
877EXTERN const char Tbadnum[] E_INIT("bad number");
878#define Tbadsubst (Tfg_badsubst + 10)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700879EXTERN const char Tbg[] E_INIT("bg");
880EXTERN const char Tbad_bsize[] E_INIT("bad shf/buf/bsize");
881#define Tbsize (Tbad_bsize + 12)
882EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'");
883#define Tbad_sig_s (Tbad_sig_ss + 4)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700884EXTERN const char Tsgbreak[] E_INIT("*=break");
885#define Tbreak (Tsgbreak + 2)
886EXTERN const char T__builtin[] E_INIT("-\\builtin");
887#define T_builtin (T__builtin + 1)
888#define Tbuiltin (T__builtin + 2)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700889EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
890EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd");
891EXTERN const char Tcant_find[] E_INIT("can't find");
892EXTERN const char Tcant_open[] E_INIT("can't open");
893#define Tbytes (Toomem + 24)
894EXTERN const char Tbcat[] E_INIT("!cat");
895#define Tcat (Tbcat + 1)
896#define Tcd (Tcant_cd + 25)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700897#define T_command (T_funny_command + 9)
898#define Tcommand (T_funny_command + 10)
899EXTERN const char Tsgcontinue[] E_INIT("*=continue");
900#define Tcontinue (Tsgcontinue + 2)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700901EXTERN const char Tcreate[] E_INIT("create");
902EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected");
903EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700904EXTERN const char Tdsgexport[] E_INIT("^*=export");
905#define Texport (Tdsgexport + 3)
Elliott Hughes96b43632015-07-17 11:39:41 -0700906#ifdef __OS2__
907EXTERN const char Textproc[] E_INIT("extproc");
908#endif
Elliott Hughes77740fc2016-08-12 15:06:53 -0700909EXTERN const char Tfalse[] E_INIT("false");
910EXTERN const char Tfg[] E_INIT("fg");
911EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700912#define Tfile (Tfile_fd + 20)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700913EXTERN const char Tfile_fd[] E_INIT("function definition file");
914EXTERN const char TFPATH[] E_INIT("FPATH");
Geremy Condra03ebf062011-10-12 18:17:24 -0700915EXTERN const char T_function[] E_INIT(" function");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700916#define Tfunction (T_function + 1)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700917EXTERN const char T_funny_command[] E_INIT("funny $()-command");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700918EXTERN const char Tgetopts[] E_INIT("getopts");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700919#define Thistory (Tnot_in_history + 7)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700920EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700921EXTERN const char Tinvname[] E_INIT("%s: invalid %s name");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700922EXTERN const char Tjobs[] E_INIT("jobs");
923EXTERN const char Tjob_not_started[] E_INIT("job not started");
924EXTERN const char Tmksh[] E_INIT("mksh");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700925#define Tname (Tinvname + 15)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700926EXTERN const char Tno_args[] E_INIT("missing argument");
927EXTERN const char Tno_OLDPWD[] E_INIT("no OLDPWD");
928EXTERN const char Tnot_ident[] E_INIT("is not an identifier");
929EXTERN const char Tnot_in_history[] E_INIT("not in history");
930EXTERN const char Tnot_found_s[] E_INIT("%s not found");
931#define Tnot_found (Tnot_found_s + 3)
932#define Tnot_started (Tjob_not_started + 4)
933#define TOLDPWD (Tno_OLDPWD + 3)
934#define Topen (Tcant_open + 6)
935#define TPATH (TFPATH + 1)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700936#define Tpv (TpVv + 1)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700937EXTERN const char TpVv[] E_INIT("Vpv");
938#define TPWD (Tno_OLDPWD + 6)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700939#define Tread (Tshf_read + 4)
940EXTERN const char Tdsgreadonly[] E_INIT("^*=readonly");
941#define Treadonly (Tdsgreadonly + 3)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700942EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection");
943#define Tredirection (Tredirection_dup + 19)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700944#define Treal_sp1 (Treal_sp2 + 1)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700945EXTERN const char Treal_sp2[] E_INIT(" real ");
946EXTERN const char Treq_arg[] E_INIT("requires an argument");
947EXTERN const char Tselect[] E_INIT("select");
948EXTERN const char Tsgset[] E_INIT("*=set");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700949#define Tset (Tf_parm + 18)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700950#define Tsh (Tmksh + 2)
951#define TSHELL (TEXECSHELL + 4)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700952#define Tshell (Ttoo_many_files + 23)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700953EXTERN const char Tshf_read[] E_INIT("shf_read");
954EXTERN const char Tshf_write[] E_INIT("shf_write");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700955EXTERN const char Tgsource[] E_INIT("=source");
956#define Tsource (Tgsource + 1)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700957EXTERN const char Tj_suspend[] E_INIT("j_suspend");
958#define Tsuspend (Tj_suspend + 2)
959EXTERN const char Tsynerr[] E_INIT("syntax error");
960EXTERN const char Ttime[] E_INIT("time");
961EXTERN const char Ttoo_many_args[] E_INIT("too many arguments");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700962EXTERN const char Ttoo_many_files[] E_INIT("too many open files in shell");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700963EXTERN const char Ttrue[] E_INIT("true");
964EXTERN const char Ttty_fd_dupof[] E_INIT("dup of tty fd");
965#define Ttty_fd (Ttty_fd_dupof + 7)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700966EXTERN const char Tdgtypeset[] E_INIT("^=typeset");
967#define Ttypeset (Tdgtypeset + 2)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700968#define Tugo (Taugo + 1)
969EXTERN const char Tunalias[] E_INIT("unalias");
970#define Tunexpected (TELIF_unexpected + 6)
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700971EXTERN const char Tunexpected_type[] E_INIT("%s: unexpected %s type %d");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700972EXTERN const char Tunknown_option[] E_INIT("unknown option");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700973EXTERN const char Tunwind[] E_INIT("unwind");
974#define Tuser_sp1 (Tuser_sp2 + 1)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700975EXTERN const char Tuser_sp2[] E_INIT(" user ");
976#define Twrite (Tshf_write + 4)
977EXTERN const char Tf__S[] E_INIT(" %S");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700978#define Tf__d (Tunexpected_type + 22)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700979EXTERN const char Tf__ss[] E_INIT(" %s%s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700980#define Tf__sN (Tf_s_s_sN + 5)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700981EXTERN const char Tf_sSs[] E_INIT("%s/%s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700982#define Tf_T (Tf_s_T + 3)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700983EXTERN const char Tf_dN[] E_INIT("%d\n");
984EXTERN const char Tf_s_[] E_INIT("%s ");
985EXTERN const char Tf_s_T[] E_INIT("%s %T");
986EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700987#define Tf_s_s (Tf_sD_s_s + 4)
988#define Tf_s_sD_s (Tf_cant_ss_s + 6)
Elliott Hughes77740fc2016-08-12 15:06:53 -0700989EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s");
990EXTERN const char Tf_sD_[] E_INIT("%s: ");
991EXTERN const char Tf_szs[] E_INIT("%s: %zd %s");
992EXTERN const char Tf_parm[] E_INIT("%s: parameter not set");
993EXTERN const char Tf_coproc[] E_INIT("-p: %s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -0700994EXTERN const char Tf_cant_s[] E_INIT("%s: can't %s");
995EXTERN const char Tf_cant_ss_s[] E_INIT("can't %s %s: %s");
996EXTERN const char Tf_heredoc[] E_INIT("here document '%s' unclosed");
Elliott Hughes77740fc2016-08-12 15:06:53 -0700997#if HAVE_MKNOD
998EXTERN const char Tf_nonnum[] E_INIT("non-numeric %s %s '%s'");
999#endif
1000EXTERN const char Tf_S_[] E_INIT("%S ");
1001#define Tf_S (Tf__S + 1)
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001002#define Tf_lu (Tf_toolarge + 17)
Elliott Hughes77740fc2016-08-12 15:06:53 -07001003EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu");
1004EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001005#define Tf_ss (Tf_sss + 2)
Elliott Hughes77740fc2016-08-12 15:06:53 -07001006EXTERN const char Tf_sss[] E_INIT("%s%s%s");
1007EXTERN const char Tf_sD_s_sD_s[] E_INIT("%s: %s %s: %s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001008EXTERN const char Tf_toomany[] E_INIT("too many %ss");
Elliott Hughes77740fc2016-08-12 15:06:53 -07001009EXTERN const char Tf_sd[] E_INIT("%s %d");
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001010#define Tf_s (Tf_temp + 28)
Elliott Hughes77740fc2016-08-12 15:06:53 -07001011EXTERN const char Tft_end[] E_INIT("%;");
1012EXTERN const char Tft_R[] E_INIT("%R");
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001013#define Tf_d (Tunexpected_type + 23)
Elliott Hughes77740fc2016-08-12 15:06:53 -07001014EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'");
1015EXTERN const char Tf_ro[] E_INIT("read-only: %s");
1016EXTERN const char Tf_flags[] E_INIT("%s: flags 0x%X");
1017EXTERN const char Tf_temp[] E_INIT("can't %s temporary file %s: %s");
1018EXTERN const char Tf_ssfaileds[] E_INIT("%s: %s failed: %s");
1019EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s");
1020EXTERN const char Tf__c_[] E_INIT("-%c ");
1021EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s");
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001022#define Tf_sN (Tf_s_s_sN + 6)
1023#define Tf_sD_s (Tf_temp + 24)
Elliott Hughes77740fc2016-08-12 15:06:53 -07001024EXTERN const char T_devtty[] E_INIT("/dev/tty");
1025#else /* helpers for string pooling */
1026#define T4spaces " "
1027#define T1space " "
1028#define Tcolsp ": "
1029#define TC_LEX1 "|&;<>() \t\n"
1030#define TC_IFSWS " \t\n"
1031#define TFCEDIT_dollaru "${FCEDIT:-/bin/ed} $_"
1032#define Tspdollaru " $_"
1033#define Tsgdot "*=."
1034#define Taugo "augo"
1035#define Tbracket "["
1036#define Tdot "."
1037#define Talias "alias"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001038#define Tbadnum "bad number"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001039#define Tbadsubst "bad substitution"
1040#define Tbg "bg"
1041#define Tbad_bsize "bad shf/buf/bsize"
1042#define Tbsize "bsize"
1043#define Tbad_sig_ss "%s: bad signal '%s'"
1044#define Tbad_sig_s "bad signal '%s'"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001045#define Tsgbreak "*=break"
1046#define Tbreak "break"
1047#define T__builtin "-\\builtin"
1048#define T_builtin "\\builtin"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001049#define Tbuiltin "builtin"
1050#define Toomem "can't allocate %zu data bytes"
1051#define Tcant_cd "restricted shell - can't cd"
1052#define Tcant_find "can't find"
1053#define Tcant_open "can't open"
1054#define Tbytes "bytes"
1055#define Tbcat "!cat"
1056#define Tcat "cat"
1057#define Tcd "cd"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001058#define T_command "-command"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001059#define Tcommand "command"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001060#define Tsgcontinue "*=continue"
1061#define Tcontinue "continue"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001062#define Tcreate "create"
1063#define TELIF_unexpected "TELIF unexpected"
1064#define TEXECSHELL "EXECSHELL"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001065#define Tdsgexport "^*=export"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001066#define Texport "export"
1067#ifdef __OS2__
1068#define Textproc "extproc"
1069#endif
1070#define Tfalse "false"
1071#define Tfg "fg"
1072#define Tfg_badsubst "fileglob: bad substitution"
1073#define Tfile "file"
1074#define Tfile_fd "function definition file"
1075#define TFPATH "FPATH"
1076#define T_function " function"
1077#define Tfunction "function"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001078#define T_funny_command "funny $()-command"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001079#define Tgetopts "getopts"
1080#define Thistory "history"
1081#define Tintovfl "integer overflow %zu %c %zu prevented"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001082#define Tinvname "%s: invalid %s name"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001083#define Tjobs "jobs"
1084#define Tjob_not_started "job not started"
1085#define Tmksh "mksh"
1086#define Tname "name"
1087#define Tno_args "missing argument"
1088#define Tno_OLDPWD "no OLDPWD"
1089#define Tnot_ident "is not an identifier"
1090#define Tnot_in_history "not in history"
1091#define Tnot_found_s "%s not found"
1092#define Tnot_found "not found"
1093#define Tnot_started "not started"
1094#define TOLDPWD "OLDPWD"
1095#define Topen "open"
1096#define TPATH "PATH"
1097#define Tpv "pv"
1098#define TpVv "Vpv"
1099#define TPWD "PWD"
1100#define Tread "read"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001101#define Tdsgreadonly "^*=readonly"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001102#define Treadonly "readonly"
1103#define Tredirection_dup "can't finish (dup) redirection"
1104#define Tredirection "redirection"
1105#define Treal_sp1 "real "
1106#define Treal_sp2 " real "
1107#define Treq_arg "requires an argument"
1108#define Tselect "select"
1109#define Tsgset "*=set"
1110#define Tset "set"
1111#define Tsh "sh"
1112#define TSHELL "SHELL"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001113#define Tshell "shell"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001114#define Tshf_read "shf_read"
1115#define Tshf_write "shf_write"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001116#define Tgsource "=source"
1117#define Tsource "source"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001118#define Tj_suspend "j_suspend"
1119#define Tsuspend "suspend"
1120#define Tsynerr "syntax error"
1121#define Ttime "time"
1122#define Ttoo_many_args "too many arguments"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001123#define Ttoo_many_files "too many open files in shell"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001124#define Ttrue "true"
1125#define Ttty_fd_dupof "dup of tty fd"
1126#define Ttty_fd "tty fd"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001127#define Tdgtypeset "^=typeset"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001128#define Ttypeset "typeset"
1129#define Tugo "ugo"
1130#define Tunalias "unalias"
1131#define Tunexpected "unexpected"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001132#define Tunexpected_type "%s: unexpected %s type %d"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001133#define Tunknown_option "unknown option"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001134#define Tunwind "unwind"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001135#define Tuser_sp1 "user "
1136#define Tuser_sp2 " user "
1137#define Twrite "write"
1138#define Tf__S " %S"
1139#define Tf__d " %d"
1140#define Tf__ss " %s%s"
1141#define Tf__sN " %s\n"
1142#define Tf_sSs "%s/%s"
1143#define Tf_T "%T"
1144#define Tf_dN "%d\n"
1145#define Tf_s_ "%s "
1146#define Tf_s_T "%s %T"
1147#define Tf_s_s_sN "%s %s %s\n"
1148#define Tf_s_s "%s %s"
1149#define Tf_s_sD_s "%s %s: %s"
1150#define Tf_optfoo "%s%s-%c: %s"
1151#define Tf_sD_ "%s: "
1152#define Tf_szs "%s: %zd %s"
1153#define Tf_parm "%s: parameter not set"
1154#define Tf_coproc "-p: %s"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001155#define Tf_cant_s "%s: can't %s"
1156#define Tf_cant_ss_s "can't %s %s: %s"
1157#define Tf_heredoc "here document '%s' unclosed"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001158#if HAVE_MKNOD
1159#define Tf_nonnum "non-numeric %s %s '%s'"
1160#endif
1161#define Tf_S_ "%S "
1162#define Tf_S "%S"
1163#define Tf_lu "%lu"
1164#define Tf_toolarge "%s %s too large: %lu"
1165#define Tf_ldfailed "%s %s(%d, %ld) failed: %s"
1166#define Tf_ss "%s%s"
1167#define Tf_sss "%s%s%s"
1168#define Tf_sD_s_sD_s "%s: %s %s: %s"
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001169#define Tf_toomany "too many %ss"
Elliott Hughes77740fc2016-08-12 15:06:53 -07001170#define Tf_sd "%s %d"
1171#define Tf_s "%s"
1172#define Tft_end "%;"
1173#define Tft_R "%R"
1174#define Tf_d "%d"
1175#define Tf_sD_s_qs "%s: %s '%s'"
1176#define Tf_ro "read-only: %s"
1177#define Tf_flags "%s: flags 0x%X"
1178#define Tf_temp "can't %s temporary file %s: %s"
1179#define Tf_ssfaileds "%s: %s failed: %s"
1180#define Tf_sD_sD_s "%s: %s: %s"
1181#define Tf__c_ "-%c "
1182#define Tf_sD_s_s "%s: %s %s"
1183#define Tf_sN "%s\n"
1184#define Tf_sD_s "%s: %s"
1185#define T_devtty "/dev/tty"
1186#endif /* end of string pooling */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001187
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001188typedef uint8_t Temp_type;
1189/* expanded heredoc */
1190#define TT_HEREDOC_EXP 0
1191/* temporary file used for history editing (fc -e) */
1192#define TT_HIST_EDIT 1
1193/* temporary file used during in-situ command substitution */
1194#define TT_FUNSUB 2
1195
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001196/* temp/heredoc files. The file is removed when the struct is freed. */
1197struct temp {
1198 struct temp *next;
1199 struct shf *shf;
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001200 /* pid of process parsed here-doc */
1201 pid_t pid;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001202 Temp_type type;
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001203 /* actually longer: name (variable length) */
1204 char tffn[3];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001205};
1206
1207/*
1208 * stdio and our IO routines
1209 */
1210
Thorsten Glaser811a5752013-07-25 14:24:45 +00001211#define shl_xtrace (&shf_iob[0]) /* for set -x */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001212#define shl_stdout (&shf_iob[1])
1213#define shl_out (&shf_iob[2])
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001214#ifdef DF
1215#define shl_dbg (&shf_iob[3]) /* for DF() */
1216#endif
Geremy Condra03ebf062011-10-12 18:17:24 -07001217EXTERN bool shl_stdout_ok;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001218
1219/*
1220 * trap handlers
1221 */
1222typedef struct trap {
1223 const char *name; /* short name */
1224 const char *mess; /* descriptive name */
1225 char *trap; /* trap command */
1226 sig_t cursig; /* current handler (valid if TF_ORIG_* set) */
1227 sig_t shtrap; /* shell signal handler */
1228 int signal; /* signal number */
1229 int flags; /* TF_* */
1230 volatile sig_atomic_t set; /* trap pending */
1231} Trap;
1232
1233/* values for Trap.flags */
1234#define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */
1235#define TF_USER_SET BIT(1) /* user has (tried to) set trap */
1236#define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */
1237#define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */
1238#define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */
1239#define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */
1240#define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */
1241#define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */
1242#define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */
1243#define TF_FATAL BIT(9) /* causes termination if not trapped */
1244
1245/* values for setsig()/setexecsig() flags argument */
1246#define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */
1247#define SS_RESTORE_CURR 0 /* leave current handler in place */
1248#define SS_RESTORE_ORIG 1 /* restore original handler */
1249#define SS_RESTORE_DFL 2 /* restore to SIG_DFL */
1250#define SS_RESTORE_IGN 3 /* restore to SIG_IGN */
1251#define SS_FORCE BIT(3) /* set signal even if original signal ignored */
1252#define SS_USER BIT(4) /* user is doing the set (ie, trap command) */
1253#define SS_SHTRAP BIT(5) /* trap for internal use (ALRM, CHLD, WINCH) */
1254
Elliott Hughes96b43632015-07-17 11:39:41 -07001255#define ksh_SIGEXIT 0 /* for trap EXIT */
1256#define ksh_SIGERR ksh_NSIG /* for trap ERR */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001257
1258EXTERN volatile sig_atomic_t trap; /* traps pending? */
1259EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */
Geremy Condra03ebf062011-10-12 18:17:24 -07001260EXTERN volatile sig_atomic_t fatal_trap; /* received a fatal signal */
Elliott Hughes96b43632015-07-17 11:39:41 -07001261extern Trap sigtraps[ksh_NSIG + 1];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001262
1263/* got_winch = 1 when we need to re-adjust the window size */
1264#ifdef SIGWINCH
Geremy Condra03ebf062011-10-12 18:17:24 -07001265EXTERN volatile sig_atomic_t got_winch E_INIT(1);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001266#else
1267#define got_winch true
1268#endif
1269
1270/*
1271 * TMOUT support
1272 */
1273/* values for ksh_tmout_state */
1274enum tmout_enum {
1275 TMOUT_EXECUTING = 0, /* executing commands */
1276 TMOUT_READING, /* waiting for input */
1277 TMOUT_LEAVING /* have timed out */
1278};
1279EXTERN unsigned int ksh_tmout;
Geremy Condra03ebf062011-10-12 18:17:24 -07001280EXTERN enum tmout_enum ksh_tmout_state E_INIT(TMOUT_EXECUTING);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001281
1282/* For "You have stopped jobs" message */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001283EXTERN bool really_exit;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001284
1285/*
1286 * fast character classes
1287 */
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001288#define C_ALPHX BIT(0) /* A-Za-z_ */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001289#define C_DIGIT BIT(1) /* 0-9 */
1290#define C_LEX1 BIT(2) /* \t \n\0|&;<>() */
1291#define C_VAR1 BIT(3) /* *@#!$-? */
1292#define C_IFSWS BIT(4) /* \t \n (IFS white space) */
1293#define C_SUBOP1 BIT(5) /* "=-+?" */
1294#define C_QUOTE BIT(6) /* \t\n "#$&'()*;<=>?[\]`| (needing quoting) */
1295#define C_IFS BIT(7) /* $IFS */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001296
1297extern unsigned char chtypes[];
1298
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001299#define ctype(c, t) tobool(chtypes[(unsigned char)(c)] & (t))
Elliott Hughes96b43632015-07-17 11:39:41 -07001300#define ord(c) ((int)(unsigned char)(c))
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001301#define ksh_issubop2(c) tobool((c) == ord('#') || (c) == ord('%'))
1302#define ksh_isalias(c) (ctype((c), C_ALPHX | C_DIGIT) || (c) == ord('!') || \
1303 (c) == ord('%') || (c) == ord(',') || \
1304 (c) == ord('@') || (c) == ord('-'))
1305#define ksh_isalpha(c) (ctype((c), C_ALPHX) && (c) != ord('_'))
1306#define ksh_isalphx(c) ctype((c), C_ALPHX)
1307#define ksh_isalnux(c) ctype((c), C_ALPHX | C_DIGIT)
1308#define ksh_isdigit(c) ctype((c), C_DIGIT)
Elliott Hughes96b43632015-07-17 11:39:41 -07001309#define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z'))
1310#define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
1311#define ksh_tolower(c) (ksh_isupper(c) ? (c) - 'A' + 'a' : (c))
1312#define ksh_toupper(c) (ksh_islower(c) ? (c) - 'a' + 'A' : (c))
1313#define ksh_isdash(s) (((s)[0] == '-') && ((s)[1] == '\0'))
1314#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
1315#define ksh_eq(c,u,l) (((c) | 0x20) == (l))
1316#define ksh_numdig(c) ((c) - ord('0'))
1317#define ksh_numuc(c) ((c) - ord('A'))
1318#define ksh_numlc(c) ((c) - ord('a'))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001319
Geremy Condra03ebf062011-10-12 18:17:24 -07001320EXTERN int ifs0 E_INIT(' '); /* for "$*" */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001321
1322/* Argument parsing for built-in commands and getopts command */
1323
1324/* Values for Getopt.flags */
1325#define GF_ERROR BIT(0) /* call errorf() if there is an error */
1326#define GF_PLUSOPT BIT(1) /* allow +c as an option */
1327#define GF_NONAME BIT(2) /* don't print argv[0] in errors */
1328
1329/* Values for Getopt.info */
1330#define GI_MINUS BIT(0) /* an option started with -... */
1331#define GI_PLUS BIT(1) /* an option started with +... */
1332#define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */
1333
Geremy Condra03ebf062011-10-12 18:17:24 -07001334/* in case some OS defines these */
1335#undef optarg
1336#undef optind
1337
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001338typedef struct {
Geremy Condra03ebf062011-10-12 18:17:24 -07001339 const char *optarg;
1340 int optind;
1341 int uoptind; /* what user sees in $OPTIND */
1342 int flags; /* see GF_* */
1343 int info; /* see GI_* */
1344 unsigned int p; /* 0 or index into argv[optind - 1] */
1345 char buf[2]; /* for bad option OPTARG value */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001346} Getopt;
1347
1348EXTERN Getopt builtin_opt; /* for shell builtin commands */
1349EXTERN Getopt user_opt; /* parsing state for getopts builtin command */
1350
1351/* This for co-processes */
1352
Geremy Condra03ebf062011-10-12 18:17:24 -07001353/* something that won't (realisticly) wrap */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001354typedef int Coproc_id;
Geremy Condra03ebf062011-10-12 18:17:24 -07001355
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001356struct coproc {
1357 void *job; /* 0 or job of co-process using input pipe */
1358 int read; /* pipe from co-process's stdout */
1359 int readw; /* other side of read (saved temporarily) */
1360 int write; /* pipe to co-process's stdin */
1361 int njobs; /* number of live jobs using output pipe */
1362 Coproc_id id; /* id of current output pipe */
1363};
1364EXTERN struct coproc coproc;
1365
Geremy Condra03ebf062011-10-12 18:17:24 -07001366#ifndef MKSH_NOPROSPECTOFWORK
1367/* used in jobs.c and by coprocess stuff in exec.c and select() calls */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001368EXTERN sigset_t sm_default, sm_sigchld;
Geremy Condra03ebf062011-10-12 18:17:24 -07001369#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001370
1371/* name of called builtin function (used by error functions) */
1372EXTERN const char *builtin_argv0;
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001373/* is called builtin a POSIX special builtin? (error functions only) */
Elliott Hughes50012062015-03-10 22:22:24 -07001374EXTERN bool builtin_spec;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001375
Geremy Condra03ebf062011-10-12 18:17:24 -07001376/* current working directory */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001377EXTERN char *current_wd;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001378
Thorsten Glaser811a5752013-07-25 14:24:45 +00001379/* input line size */
Elliott Hughes77740fc2016-08-12 15:06:53 -07001380#ifdef MKSH_SMALL
1381#define LINE (4096 - ALLOC_OVERHEAD)
1382#else
1383#define LINE (16384 - ALLOC_OVERHEAD)
1384#endif
1385/* columns and lines of the tty */
1386EXTERN mksh_ari_t x_cols E_INIT(80);
1387EXTERN mksh_ari_t x_lins E_INIT(24);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001388
Geremy Condra03ebf062011-10-12 18:17:24 -07001389
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001390/* Determine the location of the system (common) profile */
Geremy Condra03ebf062011-10-12 18:17:24 -07001391
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001392#ifndef MKSH_DEFAULT_PROFILEDIR
Elliott Hughes966dd552016-12-08 15:56:04 -08001393#define MKSH_DEFAULT_PROFILEDIR MKSH_UNIXROOT "/etc"
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001394#endif
Geremy Condra03ebf062011-10-12 18:17:24 -07001395
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001396#define MKSH_SYSTEM_PROFILE MKSH_DEFAULT_PROFILEDIR "/profile"
1397#define MKSH_SUID_PROFILE MKSH_DEFAULT_PROFILEDIR "/suid_profile"
Geremy Condra03ebf062011-10-12 18:17:24 -07001398
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001399
1400/* Used by v_evaluate() and setstr() to control action when error occurs */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001401#define KSH_UNWIND_ERROR 0 /* unwind the stack (kshlongjmp) */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001402#define KSH_RETURN_ERROR 1 /* return 1/0 for success/failure */
1403
1404/*
1405 * Shell file I/O routines
1406 */
1407
Geremy Condra03ebf062011-10-12 18:17:24 -07001408#define SHF_BSIZE 512
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001409
Geremy Condra03ebf062011-10-12 18:17:24 -07001410#define shf_fileno(shf) ((shf)->fd)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001411#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd))
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001412#define shf_getc_i(shf) ((shf)->rnleft > 0 ? \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001413 (shf)->rnleft--, *(shf)->rp++ : \
1414 shf_getchar(shf))
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001415#define shf_putc_i(c, shf) ((shf)->wnleft == 0 ? \
Elliott Hughes77740fc2016-08-12 15:06:53 -07001416 shf_putchar((uint8_t)(c), (shf)) : \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001417 ((shf)->wnleft--, *(shf)->wp++ = (c)))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001418#define shf_eof(shf) ((shf)->flags & SHF_EOF)
1419#define shf_error(shf) ((shf)->flags & SHF_ERROR)
Geremy Condra03ebf062011-10-12 18:17:24 -07001420#define shf_errno(shf) ((shf)->errnosv)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001421#define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR))
1422
1423/* Flags passed to shf_*open() */
1424#define SHF_RD 0x0001
1425#define SHF_WR 0x0002
1426#define SHF_RDWR (SHF_RD|SHF_WR)
1427#define SHF_ACCMODE 0x0003 /* mask */
1428#define SHF_GETFL 0x0004 /* use fcntl() to figure RD/WR flags */
1429#define SHF_UNBUF 0x0008 /* unbuffered I/O */
1430#define SHF_CLEXEC 0x0010 /* set close on exec flag */
1431#define SHF_MAPHI 0x0020 /* make fd > FDBASE (and close orig)
1432 * (shf_open() only) */
1433#define SHF_DYNAMIC 0x0040 /* string: increase buffer as needed */
1434#define SHF_INTERRUPT 0x0080 /* EINTR in read/write causes error */
1435/* Flags used internally */
1436#define SHF_STRING 0x0100 /* a string, not a file */
1437#define SHF_ALLOCS 0x0200 /* shf and shf->buf were alloc()ed */
1438#define SHF_ALLOCB 0x0400 /* shf->buf was alloc()ed */
1439#define SHF_ERROR 0x0800 /* read()/write() error */
1440#define SHF_EOF 0x1000 /* read eof (sticky) */
1441#define SHF_READING 0x2000 /* currently reading: rnleft,rp valid */
1442#define SHF_WRITING 0x4000 /* currently writing: wnleft,wp valid */
1443
1444
1445struct shf {
1446 Area *areap; /* area shf/buf were allocated in */
1447 unsigned char *rp; /* read: current position in buffer */
1448 unsigned char *wp; /* write: current position in buffer */
1449 unsigned char *buf; /* buffer */
Geremy Condra03ebf062011-10-12 18:17:24 -07001450 ssize_t bsize; /* actual size of buf */
1451 ssize_t rbsize; /* size of buffer (1 if SHF_UNBUF) */
1452 ssize_t rnleft; /* read: how much data left in buffer */
1453 ssize_t wbsize; /* size of buffer (0 if SHF_UNBUF) */
1454 ssize_t wnleft; /* write: how much space left in buffer */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001455 int flags; /* see SHF_* */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001456 int fd; /* file descriptor */
Geremy Condra03ebf062011-10-12 18:17:24 -07001457 int errnosv; /* saved value of errno after error */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001458};
1459
1460extern struct shf shf_iob[];
1461
1462struct table {
1463 Area *areap; /* area to allocate entries */
1464 struct tbl **tbls; /* hashed table items */
Geremy Condra03ebf062011-10-12 18:17:24 -07001465 size_t nfree; /* free table entries */
1466 uint8_t tshift; /* table size (2^tshift) */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001467};
1468
Geremy Condra03ebf062011-10-12 18:17:24 -07001469/* table item */
1470struct tbl {
1471 /* Area to allocate from */
1472 Area *areap;
1473 /* value */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001474 union {
Geremy Condra03ebf062011-10-12 18:17:24 -07001475 char *s; /* string */
1476 mksh_ari_t i; /* integer */
1477 mksh_uari_t u; /* unsigned integer */
1478 int (*f)(const char **); /* built-in command */
1479 struct op *t; /* "function" tree */
1480 } val;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001481 union {
1482 struct tbl *array; /* array values */
1483 const char *fpath; /* temporary path to undef function */
1484 } u;
1485 union {
Geremy Condra03ebf062011-10-12 18:17:24 -07001486 int field; /* field with for -L/-R/-Z */
1487 int errnov; /* CEXEC/CTALIAS */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001488 } u2;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001489 union {
1490 uint32_t hval; /* hash(name) */
1491 uint32_t index; /* index for an array */
1492 } ua;
Geremy Condra03ebf062011-10-12 18:17:24 -07001493 /*
1494 * command type (see below), base (if INTEGER),
1495 * offset from val.s of value (if EXPORT)
1496 */
1497 int type;
1498 /* flags (see below) */
1499 uint32_t flag;
1500
1501 /* actually longer: name (variable length) */
1502 char name[4];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001503};
1504
Elliott Hughes77740fc2016-08-12 15:06:53 -07001505EXTERN struct tbl *vtemp;
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001506/* set by isglobal(), global() and local() */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001507EXTERN bool last_lookup_was_array;
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001508
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001509/* common flag bits */
1510#define ALLOC BIT(0) /* val.s has been allocated */
1511#define DEFINED BIT(1) /* is defined in block */
1512#define ISSET BIT(2) /* has value, vp->val.[si] */
1513#define EXPORT BIT(3) /* exported variable/function */
1514#define TRACE BIT(4) /* var: user flagged, func: execution tracing */
1515/* (start non-common flags at 8) */
1516/* flag bits used for variables */
1517#define SPECIAL BIT(8) /* PATH, IFS, SECONDS, etc */
1518#define INTEGER BIT(9) /* val.i contains integer value */
1519#define RDONLY BIT(10) /* read-only variable */
1520#define LOCAL BIT(11) /* for local typeset() */
1521#define ARRAY BIT(13) /* array */
1522#define LJUST BIT(14) /* left justify */
1523#define RJUST BIT(15) /* right justify */
1524#define ZEROFIL BIT(16) /* 0 filled if RJUSTIFY, strip 0s if LJUSTIFY */
1525#define LCASEV BIT(17) /* convert to lower case */
1526#define UCASEV_AL BIT(18) /* convert to upper case / autoload function */
1527#define INT_U BIT(19) /* unsigned integer */
Geremy Condra03ebf062011-10-12 18:17:24 -07001528#define INT_L BIT(20) /* long integer (no-op but used as magic) */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001529#define IMPORT BIT(21) /* flag to typeset(): no arrays, must have = */
1530#define LOCAL_COPY BIT(22) /* with LOCAL - copy attrs from existing var */
1531#define EXPRINEVAL BIT(23) /* contents currently being evaluated */
1532#define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */
1533#define AINDEX BIT(25) /* array index >0 = ua.index filled in */
1534#define ASSOC BIT(26) /* ARRAY ? associative : reference */
1535/* flag bits used for taliases/builtins/aliases/keywords/functions */
1536#define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */
1537#define FINUSE BIT(9) /* function being executed */
1538#define FDELETE BIT(10) /* function deleted while it was executing */
1539#define FKSH BIT(11) /* function defined with function x (vs x()) */
1540#define SPEC_BI BIT(12) /* a POSIX special builtin */
Elliott Hughes77740fc2016-08-12 15:06:53 -07001541#define LOWER_BI BIT(13) /* (with LOW_BI) override even w/o flags */
1542#define LOW_BI BIT(14) /* external utility overrides built-in one */
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001543#define DECL_UTIL BIT(15) /* is declaration utility */
1544#define DECL_FWDR BIT(16) /* is declaration utility forwarder */
Elliott Hughes77740fc2016-08-12 15:06:53 -07001545
Geremy Condra03ebf062011-10-12 18:17:24 -07001546/*
1547 * Attributes that can be set by the user (used to decide if an unset
1548 * param should be repoted by set/typeset). Does not include ARRAY or
1549 * LOCAL.
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001550 */
1551#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL|\
1552 LCASEV|UCASEV_AL|INT_U|INT_L)
1553
1554#define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
1555 (vp)->ua.index : 0))
1556
Elliott Hughes737fdce2014-08-07 12:59:26 -07001557enum namerefflag {
Geremy Condra03ebf062011-10-12 18:17:24 -07001558 SRF_NOP,
1559 SRF_ENABLE,
1560 SRF_DISABLE
Elliott Hughes737fdce2014-08-07 12:59:26 -07001561};
Geremy Condra03ebf062011-10-12 18:17:24 -07001562
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001563/* command types */
1564#define CNONE 0 /* undefined */
1565#define CSHELL 1 /* built-in */
1566#define CFUNC 2 /* function */
1567#define CEXEC 4 /* executable command */
1568#define CALIAS 5 /* alias */
1569#define CKEYWD 6 /* keyword */
1570#define CTALIAS 7 /* tracked alias */
1571
1572/* Flags for findcom()/comexec() */
1573#define FC_SPECBI BIT(0) /* special builtin */
Thorsten Glaser811a5752013-07-25 14:24:45 +00001574#define FC_FUNC BIT(1) /* function */
1575#define FC_NORMBI BIT(2) /* not special builtin */
1576#define FC_BI (FC_SPECBI | FC_NORMBI)
1577#define FC_PATH BIT(3) /* do path search */
1578#define FC_DEFPATH BIT(4) /* use default path in path search */
Elliott Hughes77740fc2016-08-12 15:06:53 -07001579#define FC_WHENCE BIT(5) /* for use by command and whence */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001580
1581#define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */
1582#define AF_ARGS_ALLOCED 0x2 /* argument strings allocated */
1583#define AI_ARGV(a, i) ((i) == 0 ? (a).argv[0] : (a).argv[(i) - (a).skip])
Geremy Condra03ebf062011-10-12 18:17:24 -07001584#define AI_ARGC(a) ((a).ai_argc - (a).skip)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001585
1586/* Argument info. Used for $#, $* for shell, functions, includes, etc. */
1587struct arg_info {
1588 const char **argv;
1589 int flags; /* AF_* */
Geremy Condra03ebf062011-10-12 18:17:24 -07001590 int ai_argc;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001591 int skip; /* first arg is argv[0], second is argv[1 + skip] */
1592};
1593
1594/*
1595 * activation record for function blocks
1596 */
1597struct block {
1598 Area area; /* area to allocate things */
1599 const char **argv;
1600 char *error; /* error handler */
1601 char *exit; /* exit handler */
1602 struct block *next; /* enclosing block */
1603 struct table vars; /* local variables */
1604 struct table funs; /* local functions */
1605 Getopt getopts_state;
1606 int argc;
1607 int flags; /* see BF_* */
1608};
1609
1610/* Values for struct block.flags */
1611#define BF_DOGETOPTS BIT(0) /* save/restore getopts state */
Elliott Hughes50012062015-03-10 22:22:24 -07001612#define BF_STOPENV BIT(1) /* do not export further */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001613
1614/*
1615 * Used by ktwalk() and ktnext() routines.
1616 */
1617struct tstate {
1618 struct tbl **next;
1619 ssize_t left;
1620};
1621
1622EXTERN struct table taliases; /* tracked aliases */
1623EXTERN struct table builtins; /* built-in commands */
1624EXTERN struct table aliases; /* aliases */
1625EXTERN struct table keywords; /* keywords */
1626#ifndef MKSH_NOPWNAM
1627EXTERN struct table homedirs; /* homedir() cache */
1628#endif
1629
1630struct builtin {
1631 const char *name;
1632 int (*func)(const char **);
1633};
1634
1635extern const struct builtin mkshbuiltins[];
1636
1637/* values for set_prompt() */
1638#define PS1 0 /* command */
1639#define PS2 1 /* command continuation */
1640
1641EXTERN char *path; /* copy of either PATH or def_path */
1642EXTERN const char *def_path; /* path to use if PATH not set */
1643EXTERN char *tmpdir; /* TMPDIR value */
1644EXTERN const char *prompt;
Elliott Hughesb27ce952015-04-21 13:39:18 -07001645EXTERN uint8_t cur_prompt; /* PS1 or PS2 */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001646EXTERN int current_lineno; /* LINENO value */
1647
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001648/*
1649 * Description of a command or an operation on commands.
1650 */
1651struct op {
1652 const char **args; /* arguments to a command */
1653 char **vars; /* variable assignments */
1654 struct ioword **ioact; /* IO actions (eg, < > >>) */
1655 struct op *left, *right; /* descendents */
1656 char *str; /* word for case; identifier for for,
1657 * select, and functions;
1658 * path to execute for TEXEC;
1659 * time hook for TCOM.
1660 */
1661 int lineno; /* TCOM/TFUNC: LINENO for this */
1662 short type; /* operation type, see below */
Geremy Condra03ebf062011-10-12 18:17:24 -07001663 /* WARNING: newtp(), tcopy() use evalflags = 0 to clear union */
1664 union {
1665 /* TCOM: arg expansion eval() flags */
1666 short evalflags;
1667 /* TFUNC: function x (vs x()) */
1668 short ksh_func;
1669 /* TPAT: termination character */
1670 char charflag;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001671 } u;
1672};
1673
1674/* Tree.type values */
1675#define TEOF 0
1676#define TCOM 1 /* command */
1677#define TPAREN 2 /* (c-list) */
1678#define TPIPE 3 /* a | b */
1679#define TLIST 4 /* a ; b */
1680#define TOR 5 /* || */
1681#define TAND 6 /* && */
1682#define TBANG 7 /* ! */
1683#define TDBRACKET 8 /* [[ .. ]] */
1684#define TFOR 9
1685#define TSELECT 10
1686#define TCASE 11
1687#define TIF 12
1688#define TWHILE 13
1689#define TUNTIL 14
1690#define TELIF 15
1691#define TPAT 16 /* pattern in case */
1692#define TBRACE 17 /* {c-list} */
1693#define TASYNC 18 /* c & */
1694#define TFUNCT 19 /* function name { command; } */
1695#define TTIME 20 /* time pipeline */
1696#define TEXEC 21 /* fork/exec eval'd TCOM */
1697#define TCOPROC 22 /* coprocess |& */
1698
1699/*
1700 * prefix codes for words in command tree
1701 */
1702#define EOS 0 /* end of string */
1703#define CHAR 1 /* unquoted character */
1704#define QCHAR 2 /* quoted character */
1705#define COMSUB 3 /* $() substitution (0 terminated) */
1706#define EXPRSUB 4 /* $(()) substitution (0 terminated) */
1707#define OQUOTE 5 /* opening " or ' */
1708#define CQUOTE 6 /* closing " or ' */
1709#define OSUBST 7 /* opening ${ subst (followed by { or X) */
1710#define CSUBST 8 /* closing } of above (followed by } or X) */
1711#define OPAT 9 /* open pattern: *(, @(, etc. */
1712#define SPAT 10 /* separate pattern: | */
1713#define CPAT 11 /* close pattern: ) */
1714#define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001715#define FUNSUB 14 /* ${ foo;} substitution (NUL terminated) */
Thorsten Glaser811a5752013-07-25 14:24:45 +00001716#define VALSUB 15 /* ${|foo;} substitution (NUL terminated) */
Elliott Hughesa3c3f962017-04-12 16:52:30 -07001717#define COMASUB 16 /* `…` substitution (COMSUB but expand aliases) */
1718#define FUNASUB 17 /* function substitution but expand aliases */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001719
1720/*
1721 * IO redirection
1722 */
1723struct ioword {
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001724 char *ioname; /* filename (unused if heredoc) */
Elliott Hughesb27ce952015-04-21 13:39:18 -07001725 char *delim; /* delimiter for <<, <<- */
1726 char *heredoc; /* content of heredoc */
1727 unsigned short ioflag; /* action (below) */
1728 short unit; /* unit (fd) affected */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001729};
1730
1731/* ioword.flag - type of redirection */
Geremy Condra03ebf062011-10-12 18:17:24 -07001732#define IOTYPE 0xF /* type: bits 0:3 */
1733#define IOREAD 0x1 /* < */
1734#define IOWRITE 0x2 /* > */
1735#define IORDWR 0x3 /* <>: todo */
1736#define IOHERE 0x4 /* << (here file) */
1737#define IOCAT 0x5 /* >> */
1738#define IODUP 0x6 /* <&/>& */
1739#define IOEVAL BIT(4) /* expand in << */
1740#define IOSKIP BIT(5) /* <<-, skip ^\t* */
1741#define IOCLOB BIT(6) /* >|, override -o noclobber */
1742#define IORDUP BIT(7) /* x<&y (as opposed to x>&y) */
1743#define IONAMEXP BIT(8) /* name has been expanded */
1744#define IOBASH BIT(9) /* &> etc. */
1745#define IOHERESTR BIT(10) /* <<< (here string) */
1746#define IONDELIM BIT(11) /* null delimiter (<<) */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001747
1748/* execute/exchild flags */
1749#define XEXEC BIT(0) /* execute without forking */
1750#define XFORK BIT(1) /* fork before executing */
1751#define XBGND BIT(2) /* command & */
1752#define XPIPEI BIT(3) /* input is pipe */
1753#define XPIPEO BIT(4) /* output is pipe */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001754#define XXCOM BIT(5) /* `...` command */
1755#define XPCLOSE BIT(6) /* exchild: close close_fd in parent */
1756#define XCCLOSE BIT(7) /* exchild: close close_fd in child */
1757#define XERROK BIT(8) /* non-zero exit ok (for set -e) */
1758#define XCOPROC BIT(9) /* starting a co-process */
1759#define XTIME BIT(10) /* timing TCOM command */
Geremy Condra03ebf062011-10-12 18:17:24 -07001760#define XPIPEST BIT(11) /* want PIPESTATUS */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001761
1762/*
1763 * flags to control expansion of words (assumed by t->evalflags to fit
1764 * in a short)
1765 */
1766#define DOBLANK BIT(0) /* perform blank interpretation */
1767#define DOGLOB BIT(1) /* expand [?* */
1768#define DOPAT BIT(2) /* quote *?[ */
1769#define DOTILDE BIT(3) /* normal ~ expansion (first char) */
1770#define DONTRUNCOMMAND BIT(4) /* do not run $(command) things */
1771#define DOASNTILDE BIT(5) /* assignment ~ expansion (after =, :) */
Geremy Condra03ebf062011-10-12 18:17:24 -07001772#define DOBRACE BIT(6) /* used by expand(): do brace expansion */
1773#define DOMAGIC BIT(7) /* used by expand(): string contains MAGIC */
1774#define DOTEMP BIT(8) /* dito: in word part of ${..[%#=?]..} */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001775#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
1776#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001777#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
Elliott Hughes50012062015-03-10 22:22:24 -07001778#define DOSCALAR BIT(12) /* change field handling to non-list context */
1779#define DOHEREDOC BIT(13) /* change scalar handling to heredoc body */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001780#define DOHERESTR BIT(14) /* append a newline char */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001781
Geremy Condra03ebf062011-10-12 18:17:24 -07001782#define X_EXTRA 20 /* this many extra bytes in X string */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001783
1784typedef struct XString {
Elliott Hughes966dd552016-12-08 15:56:04 -08001785 /* beginning of string */
Elliott Hughes77740fc2016-08-12 15:06:53 -07001786 char *beg;
1787 /* length of allocated area, minus safety margin */
1788 size_t len;
1789 /* end of string */
1790 char *end;
1791 /* memory area used */
1792 Area *areap;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001793} XString;
1794
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001795/* initialise expandable string */
1796#define XinitN(xs, length, area) do { \
1797 (xs).len = (length); \
1798 (xs).areap = (area); \
1799 (xs).beg = alloc((xs).len + X_EXTRA, (xs).areap); \
1800 (xs).end = (xs).beg + (xs).len; \
1801} while (/* CONSTCOND */ 0)
1802#define Xinit(xs, xp, length, area) do { \
1803 XinitN((xs), (length), (area)); \
1804 (xp) = (xs).beg; \
1805} while (/* CONSTCOND */ 0)
1806
1807/* stuff char into string */
1808#define Xput(xs, xp, c) (*xp++ = (c))
1809
1810/* check if there are at least n bytes left */
1811#define XcheckN(xs, xp, n) do { \
Geremy Condra03ebf062011-10-12 18:17:24 -07001812 ssize_t more = ((xp) + (n)) - (xs).end; \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001813 if (more > 0) \
Elliott Hughes737fdce2014-08-07 12:59:26 -07001814 (xp) = Xcheck_grow(&(xs), (xp), (size_t)more); \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001815} while (/* CONSTCOND */ 0)
1816
1817/* check for overflow, expand string */
1818#define Xcheck(xs, xp) XcheckN((xs), (xp), 1)
1819
1820/* free string */
1821#define Xfree(xs, xp) afree((xs).beg, (xs).areap)
1822
1823/* close, return string */
1824#define Xclose(xs, xp) aresize((xs).beg, (xp) - (xs).beg, (xs).areap)
1825
Elliott Hughes966dd552016-12-08 15:56:04 -08001826/* beginning of string */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001827#define Xstring(xs, xp) ((xs).beg)
1828
1829#define Xnleft(xs, xp) ((xs).end - (xp)) /* may be less than 0 */
1830#define Xlength(xs, xp) ((xp) - (xs).beg)
1831#define Xsize(xs, xp) ((xs).end - (xs).beg)
1832#define Xsavepos(xs, xp) ((xp) - (xs).beg)
1833#define Xrestpos(xs, xp, n) ((xs).beg + (n))
1834
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001835char *Xcheck_grow(XString *, const char *, size_t);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001836
1837/*
1838 * expandable vector of generic pointers
1839 */
1840
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001841typedef struct {
Elliott Hughes966dd552016-12-08 15:56:04 -08001842 /* beginning of allocated area */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001843 void **beg;
1844 /* currently used number of entries */
1845 size_t len;
1846 /* allocated number of entries */
1847 size_t siz;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001848} XPtrV;
1849
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001850#define XPinit(x, n) do { \
1851 (x).siz = (n); \
1852 (x).len = 0; \
1853 (x).beg = alloc2((x).siz, sizeof(void *), ATEMP); \
1854} while (/* CONSTCOND */ 0) \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001855
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001856#define XPput(x, p) do { \
1857 if ((x).len == (x).siz) { \
1858 (x).beg = aresize2((x).beg, (x).siz, \
1859 2 * sizeof(void *), ATEMP); \
1860 (x).siz <<= 1; \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001861 } \
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001862 (x).beg[(x).len++] = (p); \
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001863} while (/* CONSTCOND */ 0)
1864
1865#define XPptrv(x) ((x).beg)
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001866#define XPsize(x) ((x).len)
Geremy Condra03ebf062011-10-12 18:17:24 -07001867#define XPclose(x) aresize2((x).beg, XPsize(x), sizeof(void *), ATEMP)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001868#define XPfree(x) afree((x).beg, ATEMP)
1869
Elliott Hughes966dd552016-12-08 15:56:04 -08001870/* for print_columns */
1871
1872struct columnise_opts {
1873 struct shf *shf;
1874 char linesep;
1875 bool do_last;
1876 bool prefcol;
1877};
1878
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001879/*
1880 * Lexer internals
1881 */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001882
1883typedef struct source Source;
1884struct source {
Elliott Hughes77740fc2016-08-12 15:06:53 -07001885 /* input buffer */
1886 XString xs;
1887 /* memory area, also checked in reclaim() */
1888 Area *areap;
1889 /* stacked source */
1890 Source *next;
1891 /* input pointer */
1892 const char *str;
1893 /* start of current buffer */
1894 const char *start;
1895 /* input file name */
1896 const char *file;
1897 /* extra data */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001898 union {
Elliott Hughes77740fc2016-08-12 15:06:53 -07001899 /* string[] */
1900 const char **strv;
1901 /* shell file */
1902 struct shf *shf;
1903 /* alias (SF_HASALIAS) */
1904 struct tbl *tblp;
1905 /* (also for SREREAD) */
1906 char *freeme;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001907 } u;
Elliott Hughes77740fc2016-08-12 15:06:53 -07001908 /* flags */
1909 int flags;
1910 /* input type */
1911 int type;
1912 /* line number */
1913 int line;
1914 /* line the error occurred on (0 if not set) */
1915 int errline;
1916 /* buffer for ungetsc() (SREREAD) and alias (SALIAS) */
1917 char ugbuf[2];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001918};
1919
1920/* Source.type values */
1921#define SEOF 0 /* input EOF */
1922#define SFILE 1 /* file input */
1923#define SSTDIN 2 /* read stdin */
1924#define SSTRING 3 /* string */
1925#define SWSTR 4 /* string without \n */
1926#define SWORDS 5 /* string[] */
1927#define SWORDSEP 6 /* string[] separator */
1928#define SALIAS 7 /* alias expansion */
1929#define SREREAD 8 /* read ahead to be re-scanned */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001930#define SSTRINGCMDLINE 9 /* string from "mksh -c ..." */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001931
1932/* Source.flags values */
1933#define SF_ECHO BIT(0) /* echo input to shlout */
1934#define SF_ALIAS BIT(1) /* faking space at end of alias */
1935#define SF_ALIASEND BIT(2) /* faking space at end of alias */
1936#define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */
Geremy Condra03ebf062011-10-12 18:17:24 -07001937#define SF_HASALIAS BIT(4) /* u.tblp valid (SALIAS, SEOF) */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001938#define SF_MAYEXEC BIT(5) /* special sh -c optimisation hack */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001939
1940typedef union {
1941 int i;
1942 char *cp;
1943 char **wp;
1944 struct op *o;
1945 struct ioword *iop;
1946} YYSTYPE;
1947
1948/* If something is added here, add it to tokentab[] in syn.c as well */
1949#define LWORD 256
1950#define LOGAND 257 /* && */
1951#define LOGOR 258 /* || */
1952#define BREAK 259 /* ;; */
1953#define IF 260
1954#define THEN 261
1955#define ELSE 262
1956#define ELIF 263
1957#define FI 264
1958#define CASE 265
1959#define ESAC 266
1960#define FOR 267
1961#define SELECT 268
1962#define WHILE 269
1963#define UNTIL 270
1964#define DO 271
1965#define DONE 272
1966#define IN 273
1967#define FUNCTION 274
1968#define TIME 275
1969#define REDIR 276
1970#define MDPAREN 277 /* (( )) */
1971#define BANG 278 /* ! */
1972#define DBRACKET 279 /* [[ .. ]] */
1973#define COPROC 280 /* |& */
Geremy Condra03ebf062011-10-12 18:17:24 -07001974#define BRKEV 281 /* ;| */
1975#define BRKFT 282 /* ;& */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001976#define YYERRCODE 300
1977
1978/* flags to yylex */
1979#define CONTIN BIT(0) /* skip new lines to complete command */
1980#define ONEWORD BIT(1) /* single word for substitute() */
1981#define ALIAS BIT(2) /* recognise alias */
1982#define KEYWORD BIT(3) /* recognise keywords */
1983#define LETEXPR BIT(4) /* get expression inside (( )) */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001984#define CMDASN BIT(5) /* parse x[1 & 2] as one word, for typeset */
1985#define HEREDOC BIT(6) /* parsing a here document body */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001986#define ESACONLY BIT(7) /* only accept esac keyword */
Elliott Hughesfc0307d2016-02-02 15:26:47 -08001987#define CMDWORD BIT(8) /* parsing simple command (alias related) */
1988#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
1989#define LQCHAR BIT(10) /* source string contains QCHAR */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001990
Geremy Condra03ebf062011-10-12 18:17:24 -07001991#define HERES 10 /* max number of << in line */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001992
1993#undef CTRL
1994#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
1995#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
Elliott Hughes737fdce2014-08-07 12:59:26 -07001996#define ISCTRL(x) (((signed char)((uint8_t)(x) + 1)) < 33)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07001997
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00001998#define IDENT 64
1999
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002000EXTERN Source *source; /* yyparse/yylex source */
Geremy Condra03ebf062011-10-12 18:17:24 -07002001EXTERN YYSTYPE yylval; /* result from yylex */
2002EXTERN struct ioword *heres[HERES], **herep;
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002003EXTERN char ident[IDENT + 1];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002004
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002005EXTERN char **history; /* saved commands */
2006EXTERN char **histptr; /* last history item */
2007EXTERN mksh_ari_t histsize; /* history size */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002008
Elliott Hughes96b43632015-07-17 11:39:41 -07002009/* flags to histsave */
2010#define HIST_FLUSH 0
2011#define HIST_QUEUE 1
2012#define HIST_APPEND 2
2013#define HIST_STORE 3
2014#define HIST_NOTE 4
2015
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002016/* user and system time of last j_waitjed job */
2017EXTERN struct timeval j_usrtime, j_systime;
2018
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002019#define notok2mul(max, val, c) (((val) != 0) && ((c) != 0) && \
2020 (((max) / (c)) < (val)))
2021#define notok2add(max, val, c) ((val) > ((max) - (c)))
2022#define notoktomul(val, cnst) notok2mul(SIZE_MAX, (val), (cnst))
2023#define notoktoadd(val, cnst) notok2add(SIZE_MAX, (val), (cnst))
Geremy Condra03ebf062011-10-12 18:17:24 -07002024#define checkoktoadd(val, cnst) do { \
2025 if (notoktoadd((val), (cnst))) \
2026 internal_errorf(Tintovfl, (size_t)(val), \
2027 '+', (size_t)(cnst)); \
2028} while (/* CONSTCOND */ 0)
2029
2030
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002031/* lalloc.c */
2032void ainit(Area *);
2033void afreeall(Area *);
2034/* these cannot fail and can take NULL (not for ap) */
Geremy Condra03ebf062011-10-12 18:17:24 -07002035#define alloc(n, ap) aresize(NULL, (n), (ap))
2036#define alloc2(m, n, ap) aresize2(NULL, (m), (n), (ap))
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002037void *aresize(void *, size_t, Area *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002038void *aresize2(void *, size_t, size_t, Area *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002039void afree(void *, Area *); /* can take NULL */
2040/* edit.c */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002041#ifndef MKSH_NO_CMDLINE_EDITING
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002042#ifndef MKSH_SMALL
2043int x_bind(const char *, const char *, bool, bool);
2044#else
2045int x_bind(const char *, const char *, bool);
2046#endif
2047void x_init(void);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002048#ifdef DEBUG_LEAKS
2049void x_done(void);
2050#endif
Thorsten Glaser811a5752013-07-25 14:24:45 +00002051int x_read(char *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002052#endif
2053void x_mkraw(int, mksh_ttyst *, bool);
Elliott Hughes77740fc2016-08-12 15:06:53 -07002054void x_initterm(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002055/* eval.c */
2056char *substitute(const char *, int);
2057char **eval(const char **, int);
2058char *evalstr(const char *cp, int);
2059char *evalonestr(const char *cp, int);
2060char *debunk(char *, const char *, size_t);
2061void expand(const char *, XPtrV *, int);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002062int glob_str(char *, XPtrV *, bool);
Elliott Hughes50012062015-03-10 22:22:24 -07002063char *do_tilde(char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002064/* exec.c */
2065int execute(struct op * volatile, volatile int, volatile int * volatile);
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002066int c_builtin(const char **);
2067struct tbl *get_builtin(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002068struct tbl *findfunc(const char *, uint32_t, bool);
2069int define(const char *, struct op *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002070const char *builtin(const char *, int (*)(const char **));
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002071struct tbl *findcom(const char *, int);
Geremy Condra03ebf062011-10-12 18:17:24 -07002072void flushcom(bool);
Elliott Hughesfc0307d2016-02-02 15:26:47 -08002073int search_access(const char *, int);
Geremy Condra03ebf062011-10-12 18:17:24 -07002074const char *search_path(const char *, const char *, int, int *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002075void pr_menu(const char * const *);
Elliott Hughes966dd552016-12-08 15:56:04 -08002076void pr_list(struct columnise_opts *, char * const *);
Elliott Hughes77740fc2016-08-12 15:06:53 -07002077int herein(struct ioword *, char **);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002078/* expr.c */
2079int evaluate(const char *, mksh_ari_t *, int, bool);
2080int v_evaluate(struct tbl *, const char *, volatile int, bool);
2081/* UTF-8 stuff */
2082size_t utf_mbtowc(unsigned int *, const char *);
2083size_t utf_wctomb(char *, unsigned int);
2084int utf_widthadj(const char *, const char **);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002085size_t utf_mbswidth(const char *) MKSH_A_PURE;
Elliott Hughes77740fc2016-08-12 15:06:53 -07002086const char *utf_skipcols(const char *, int, int *);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002087size_t utf_ptradj(const char *) MKSH_A_PURE;
Elliott Hughesfc0307d2016-02-02 15:26:47 -08002088#ifdef MIRBSD_BOOTFLOPPY
2089#define utf_wcwidth(i) wcwidth((wchar_t)(i))
2090#else
Elliott Hughes737fdce2014-08-07 12:59:26 -07002091int utf_wcwidth(unsigned int) MKSH_A_PURE;
Elliott Hughesfc0307d2016-02-02 15:26:47 -08002092#endif
Geremy Condra03ebf062011-10-12 18:17:24 -07002093int ksh_access(const char *, int);
Elliott Hughes77740fc2016-08-12 15:06:53 -07002094struct tbl *tempvar(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002095/* funcs.c */
2096int c_hash(const char **);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002097int c_pwd(const char **);
2098int c_print(const char **);
2099#ifdef MKSH_PRINTF_BUILTIN
2100int c_printf(const char **);
2101#endif
2102int c_whence(const char **);
2103int c_command(const char **);
2104int c_typeset(const char **);
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002105bool valid_alias_name(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002106int c_alias(const char **);
2107int c_unalias(const char **);
2108int c_let(const char **);
2109int c_jobs(const char **);
2110#ifndef MKSH_UNEMPLOYED
2111int c_fgbg(const char **);
2112#endif
2113int c_kill(const char **);
2114void getopts_reset(int);
2115int c_getopts(const char **);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002116#ifndef MKSH_NO_CMDLINE_EDITING
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002117int c_bind(const char **);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002118#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002119int c_shift(const char **);
2120int c_umask(const char **);
2121int c_dot(const char **);
2122int c_wait(const char **);
2123int c_read(const char **);
2124int c_eval(const char **);
2125int c_trap(const char **);
2126int c_brkcont(const char **);
2127int c_exitreturn(const char **);
2128int c_set(const char **);
2129int c_unset(const char **);
2130int c_ulimit(const char **);
2131int c_times(const char **);
2132int timex(struct op *, int, volatile int *);
2133void timex_hook(struct op *, char ** volatile *);
2134int c_exec(const char **);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002135int c_test(const char **);
2136#if HAVE_MKNOD
2137int c_mknod(const char **);
2138#endif
2139int c_realpath(const char **);
2140int c_rename(const char **);
Geremy Condra03ebf062011-10-12 18:17:24 -07002141int c_cat(const char **);
2142int c_sleep(const char **);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002143/* histrap.c */
2144void init_histvec(void);
2145void hist_init(Source *);
2146#if HAVE_PERSISTENT_HISTORY
2147void hist_finish(void);
2148#endif
Elliott Hughes96b43632015-07-17 11:39:41 -07002149void histsave(int *, const char *, int, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002150#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
2151bool histsync(void);
2152#endif
2153int c_fc(const char **);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002154void sethistsize(mksh_ari_t);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002155#if HAVE_PERSISTENT_HISTORY
2156void sethistfile(const char *);
2157#endif
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002158#if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI
Elliott Hughes737fdce2014-08-07 12:59:26 -07002159char **histpos(void) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002160int histnum(int);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002161#endif
Elliott Hughes737fdce2014-08-07 12:59:26 -07002162int findhist(int, int, const char *, bool) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002163char **hist_get_newest(bool);
2164void inittraps(void);
2165void alarm_init(void);
Elliott Hughes96b43632015-07-17 11:39:41 -07002166Trap *gettrap(const char *, bool, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002167void trapsig(int);
2168void intrcheck(void);
2169int fatal_trap_check(void);
2170int trap_pending(void);
2171void runtraps(int intr);
Geremy Condra03ebf062011-10-12 18:17:24 -07002172void runtrap(Trap *, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002173void cleartraps(void);
2174void restoresigs(void);
2175void settrap(Trap *, const char *);
Elliott Hughes966dd552016-12-08 15:56:04 -08002176bool block_pipe(void);
2177void restore_pipe(void);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002178int setsig(Trap *, sig_t, int);
2179void setexecsig(Trap *, int);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002180#if HAVE_FLOCK || HAVE_LOCK_FCNTL
2181void mksh_lockfd(int);
2182void mksh_unlkfd(int);
2183#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002184/* jobs.c */
2185void j_init(void);
2186void j_exit(void);
2187#ifndef MKSH_UNEMPLOYED
2188void j_change(void);
2189#endif
2190int exchild(struct op *, int, volatile int *, int);
2191void startlast(void);
2192int waitlast(void);
2193int waitfor(const char *, int *);
2194int j_kill(const char *, int);
2195#ifndef MKSH_UNEMPLOYED
2196int j_resume(const char *, int);
2197#endif
Elliott Hughes737fdce2014-08-07 12:59:26 -07002198#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
2199void j_suspend(void);
2200#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002201int j_jobs(const char *, int, int);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002202void j_notify(void);
2203pid_t j_async(void);
2204int j_stopped_running(void);
2205/* lex.c */
2206int yylex(int);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002207void yyskiputf8bom(void);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002208void yyerror(const char *, ...)
2209 MKSH_A_NORETURN
Geremy Condra03ebf062011-10-12 18:17:24 -07002210 MKSH_A_FORMAT(__printf__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002211Source *pushs(int, Area *);
2212void set_prompt(int, Source *);
Thorsten Glaser811a5752013-07-25 14:24:45 +00002213int pprompt(const char *, int);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002214/* main.c */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002215int include(const char *, int, const char **, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002216int command(const char *, int);
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002217int shell(Source * volatile, volatile int);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002218/* argument MUST NOT be 0 */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002219void unwind(int) MKSH_A_NORETURN;
2220void newenv(int);
2221void quitenv(struct shf *);
2222void cleanup_parents_env(void);
2223void cleanup_proc_env(void);
2224void errorf(const char *, ...)
2225 MKSH_A_NORETURN
Geremy Condra03ebf062011-10-12 18:17:24 -07002226 MKSH_A_FORMAT(__printf__, 1, 2);
2227void errorfx(int, const char *, ...)
2228 MKSH_A_NORETURN
2229 MKSH_A_FORMAT(__printf__, 2, 3);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002230void warningf(bool, const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002231 MKSH_A_FORMAT(__printf__, 2, 3);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002232void bi_errorf(const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002233 MKSH_A_FORMAT(__printf__, 1, 2);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002234#define errorfz() errorf(NULL)
2235#define errorfxz(rc) errorfx((rc), NULL)
2236#define bi_errorfz() bi_errorf(NULL)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002237void internal_errorf(const char *, ...)
2238 MKSH_A_NORETURN
Geremy Condra03ebf062011-10-12 18:17:24 -07002239 MKSH_A_FORMAT(__printf__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002240void internal_warningf(const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002241 MKSH_A_FORMAT(__printf__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002242void error_prefix(bool);
2243void shellf(const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002244 MKSH_A_FORMAT(__printf__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002245void shprintf(const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002246 MKSH_A_FORMAT(__printf__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002247int can_seek(int);
2248void initio(void);
2249int ksh_dup2(int, int, bool);
2250short savefd(int);
2251void restfd(int, int);
2252void openpipe(int *);
2253void closepipe(int *);
2254int check_fd(const char *, int, const char **);
2255void coproc_init(void);
2256void coproc_read_close(int);
2257void coproc_readw_close(int);
2258void coproc_write_close(int);
2259int coproc_getfd(int, const char **);
2260void coproc_cleanup(int);
2261struct temp *maketemp(Area *, Temp_type, struct temp **);
Geremy Condra03ebf062011-10-12 18:17:24 -07002262void ktinit(Area *, struct table *, uint8_t);
2263struct tbl *ktscan(struct table *, const char *, uint32_t, struct tbl ***);
2264/* table, name (key) to search for, hash(n) */
2265#define ktsearch(tp, s, h) ktscan((tp), (s), (h), NULL)
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002266struct tbl *ktenter(struct table *, const char *, uint32_t);
2267#define ktdelete(p) do { p->flag = 0; } while (/* CONSTCOND */ 0)
2268void ktwalk(struct tstate *, struct table *);
2269struct tbl *ktnext(struct tstate *);
2270struct tbl **ktsort(struct table *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002271#ifdef DF
2272void DF(const char *, ...)
2273 MKSH_A_FORMAT(__printf__, 1, 2);
2274#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002275/* misc.c */
2276void setctypes(const char *, int);
2277void initctypes(void);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002278size_t option(const char *) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002279char *getoptions(void);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002280void change_flag(enum sh_flag, int, bool);
Thorsten Glaser811a5752013-07-25 14:24:45 +00002281void change_xtrace(unsigned char, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002282int parse_args(const char **, int, bool *);
2283int getn(const char *, int *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002284int gmatchx(const char *, const char *, bool);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002285int has_globbing(const char *, const char *) MKSH_A_PURE;
2286int xstrcmp(const void *, const void *) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002287void ksh_getopt_reset(Getopt *, int);
2288int ksh_getopt(const char **, Getopt *, const char *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002289void print_value_quoted(struct shf *, const char *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002290char *quote_value(const char *);
Elliott Hughes966dd552016-12-08 15:56:04 -08002291void print_columns(struct columnise_opts *, unsigned int,
Elliott Hughes96b43632015-07-17 11:39:41 -07002292 void (*)(char *, size_t, unsigned int, const void *),
Elliott Hughes966dd552016-12-08 15:56:04 -08002293 const void *, size_t, size_t);
Elliott Hughesb27ce952015-04-21 13:39:18 -07002294void strip_nuls(char *, size_t)
2295 MKSH_A_BOUNDED(__string__, 1, 2);
Geremy Condra03ebf062011-10-12 18:17:24 -07002296ssize_t blocking_read(int, char *, size_t)
2297 MKSH_A_BOUNDED(__buffer__, 2, 3);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002298int reset_nonblock(int);
Geremy Condra03ebf062011-10-12 18:17:24 -07002299char *ksh_get_wd(void);
2300char *do_realpath(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002301void simplify_path(char *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002302void set_current_wd(const char *);
2303int c_cd(const char **);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002304#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
2305char *strdup_i(const char *, Area *);
2306char *strndup_i(const char *, size_t, Area *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002307#endif
2308int unbksl(bool, int (*)(void), void (*)(int));
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002309#ifdef __OS2__
2310/* os2.c */
2311void os2_init(int *, const char ***);
2312void setextlibpath(const char *, const char *);
2313int access_ex(int (*)(const char *, int), const char *, int);
2314int stat_ex(const char *, struct stat *);
2315const char *real_exec_name(const char *);
2316#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002317/* shf.c */
2318struct shf *shf_open(const char *, int, int, int);
2319struct shf *shf_fdopen(int, int, struct shf *);
2320struct shf *shf_reopen(int, int, struct shf *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002321struct shf *shf_sopen(char *, ssize_t, int, struct shf *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002322int shf_close(struct shf *);
2323int shf_fdclose(struct shf *);
2324char *shf_sclose(struct shf *);
2325int shf_flush(struct shf *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002326ssize_t shf_read(char *, ssize_t, struct shf *);
2327char *shf_getse(char *, ssize_t, struct shf *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002328int shf_getchar(struct shf *s);
2329int shf_ungetc(int, struct shf *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002330#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
Geremy Condra03ebf062011-10-12 18:17:24 -07002331int shf_getc(struct shf *);
2332int shf_putc(int, struct shf *);
2333#else
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002334#define shf_getc shf_getc_i
2335#define shf_putc shf_putc_i
Geremy Condra03ebf062011-10-12 18:17:24 -07002336#endif
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002337int shf_putchar(int, struct shf *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002338ssize_t shf_puts(const char *, struct shf *);
2339ssize_t shf_write(const char *, ssize_t, struct shf *);
2340ssize_t shf_fprintf(struct shf *, const char *, ...)
2341 MKSH_A_FORMAT(__printf__, 2, 3);
2342ssize_t shf_snprintf(char *, ssize_t, const char *, ...)
2343 MKSH_A_FORMAT(__printf__, 3, 4)
2344 MKSH_A_BOUNDED(__string__, 1, 2);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002345char *shf_smprintf(const char *, ...)
Geremy Condra03ebf062011-10-12 18:17:24 -07002346 MKSH_A_FORMAT(__printf__, 1, 2);
2347ssize_t shf_vfprintf(struct shf *, const char *, va_list)
2348 MKSH_A_FORMAT(__printf__, 2, 0);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002349/* syn.c */
2350void initkeywords(void);
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002351struct op *compile(Source *, bool, bool);
Geremy Condra03ebf062011-10-12 18:17:24 -07002352bool parse_usec(const char *, struct timeval *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002353char *yyrecursive(int);
2354void yyrecursive_pop(bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002355/* tree.c */
Geremy Condra03ebf062011-10-12 18:17:24 -07002356void fptreef(struct shf *, int, const char *, ...);
2357char *snptreef(char *, ssize_t, const char *, ...);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002358struct op *tcopy(struct op *, Area *);
2359char *wdcopy(const char *, Area *);
2360const char *wdscan(const char *, int);
Geremy Condra03ebf062011-10-12 18:17:24 -07002361#define WDS_TPUTS BIT(0) /* tputS (dumpwdvar) mode */
Geremy Condra03ebf062011-10-12 18:17:24 -07002362char *wdstrip(const char *, int);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002363void tfree(struct op *, Area *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002364void dumpchar(struct shf *, int);
2365void dumptree(struct shf *, struct op *);
2366void dumpwdvar(struct shf *, const char *);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002367void dumpioact(struct shf *shf, struct op *t);
Geremy Condra03ebf062011-10-12 18:17:24 -07002368void vistree(char *, size_t, struct op *)
2369 MKSH_A_BOUNDED(__string__, 1, 2);
2370void fpFUNCTf(struct shf *, int, bool, const char *, struct op *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002371/* var.c */
2372void newblock(void);
2373void popblock(void);
2374void initvar(void);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002375struct block *varsearch(struct block *, struct tbl **, const char *, uint32_t);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002376struct tbl *global(const char *);
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002377struct tbl *isglobal(const char *, bool);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002378struct tbl *local(const char *, bool);
2379char *str_val(struct tbl *);
2380int setstr(struct tbl *, const char *, int);
2381struct tbl *setint_v(struct tbl *, struct tbl *, bool);
2382void setint(struct tbl *, mksh_ari_t);
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002383void setint_n(struct tbl *, mksh_ari_t, int);
2384struct tbl *typeset(const char *, uint32_t, uint32_t, int, int);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002385void unset(struct tbl *, int);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002386const char *skip_varname(const char *, bool) MKSH_A_PURE;
2387const char *skip_wdvarname(const char *, bool) MKSH_A_PURE;
2388int is_wdvarname(const char *, bool) MKSH_A_PURE;
2389int is_wdvarassign(const char *) MKSH_A_PURE;
Geremy Condra03ebf062011-10-12 18:17:24 -07002390struct tbl *arraysearch(struct tbl *, uint32_t);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002391char **makenv(void);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002392void change_winsz(void);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002393size_t array_ref_len(const char *) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002394char *arrayname(const char *);
2395mksh_uari_t set_array(const char *, bool, const char **);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002396uint32_t hash(const void *) MKSH_A_PURE;
2397uint32_t chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002398mksh_ari_t rndget(void);
Thorsten Glaser811a5752013-07-25 14:24:45 +00002399void rndset(unsigned long);
Elliott Hughes737fdce2014-08-07 12:59:26 -07002400void rndpush(const void *);
Elliott Hughes77740fc2016-08-12 15:06:53 -07002401void record_match(const char *);
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002402
2403enum Test_op {
Geremy Condra03ebf062011-10-12 18:17:24 -07002404 /* non-operator */
2405 TO_NONOP = 0,
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002406 /* unary operators */
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002407 TO_STNZE, TO_STZER, TO_ISSET, TO_OPTION,
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002408 TO_FILAXST,
2409 TO_FILEXST,
2410 TO_FILREG, TO_FILBDEV, TO_FILCDEV, TO_FILSYM, TO_FILFIFO, TO_FILSOCK,
2411 TO_FILCDF, TO_FILID, TO_FILGID, TO_FILSETG, TO_FILSTCK, TO_FILUID,
2412 TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX,
2413 /* binary operators */
2414 TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT,
2415 TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT,
2416 /* not an operator */
2417 TO_NONNULL /* !TO_NONOP */
2418};
2419typedef enum Test_op Test_op;
2420
2421/* Used by Test_env.isa() (order important - used to index *_tokens[] arrays) */
2422enum Test_meta {
2423 TM_OR, /* -o or || */
2424 TM_AND, /* -a or && */
2425 TM_NOT, /* ! */
2426 TM_OPAREN, /* ( */
2427 TM_CPAREN, /* ) */
2428 TM_UNOP, /* unary operator */
2429 TM_BINOP, /* binary operator */
2430 TM_END /* end of input */
2431};
2432typedef enum Test_meta Test_meta;
2433
2434#define TEF_ERROR BIT(0) /* set if we've hit an error */
2435#define TEF_DBRACKET BIT(1) /* set if [[ .. ]] test */
2436
2437typedef struct test_env {
2438 union {
Geremy Condra03ebf062011-10-12 18:17:24 -07002439 const char **wp; /* used by ptest_* */
2440 XPtrV *av; /* used by dbtestp_* */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002441 } pos;
Geremy Condra03ebf062011-10-12 18:17:24 -07002442 const char **wp_end; /* used by ptest_* */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002443 Test_op (*isa)(struct test_env *, Test_meta);
2444 const char *(*getopnd) (struct test_env *, Test_op, bool);
2445 int (*eval)(struct test_env *, Test_op, const char *, const char *, bool);
2446 void (*error)(struct test_env *, int, const char *);
Geremy Condra03ebf062011-10-12 18:17:24 -07002447 int flags; /* TEF_* */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002448} Test_env;
2449
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002450extern const char * const dbtest_tokens[];
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002451
Elliott Hughes737fdce2014-08-07 12:59:26 -07002452Test_op test_isop(Test_meta, const char *) MKSH_A_PURE;
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002453int test_eval(Test_env *, Test_op, const char *, const char *, bool);
2454int test_parse(Test_env *);
2455
Elliott Hughes737fdce2014-08-07 12:59:26 -07002456/* tty_fd is not opened O_BINARY, it's thus never read/written */
Geremy Condra03ebf062011-10-12 18:17:24 -07002457EXTERN int tty_fd E_INIT(-1); /* dup'd tty file descriptor */
2458EXTERN bool tty_devtty; /* true if tty_fd is from /dev/tty */
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002459EXTERN mksh_ttyst tty_state; /* saved tty state */
2460EXTERN bool tty_hasstate; /* true if tty_state is valid */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002461
Thorsten Glaserc2dc5de2013-02-18 23:02:51 +00002462extern int tty_init_fd(void); /* initialise tty_fd, tty_devtty */
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002463
Elliott Hughes96b43632015-07-17 11:39:41 -07002464#ifdef __OS2__
Elliott Hughes96b43632015-07-17 11:39:41 -07002465#define binopen2(path,flags) __extension__({ \
2466 int binopen2_fd = open((path), (flags) | O_BINARY); \
2467 if (binopen2_fd >= 0) \
2468 setmode(binopen2_fd, O_BINARY); \
2469 (binopen2_fd); \
2470})
2471#define binopen3(path,flags,mode) __extension__({ \
2472 int binopen3_fd = open((path), (flags) | O_BINARY, (mode)); \
2473 if (binopen3_fd >= 0) \
2474 setmode(binopen3_fd, O_BINARY); \
2475 (binopen3_fd); \
2476})
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002477#else
2478#define binopen2(path,flags) open((path), (flags) | O_BINARY)
2479#define binopen3(path,flags,mode) open((path), (flags) | O_BINARY, (mode))
2480#endif
2481
2482#ifdef MKSH_DOSPATH
Elliott Hughes96b43632015-07-17 11:39:41 -07002483#define mksh_abspath(s) __extension__({ \
2484 const char *mksh_abspath_s = (s); \
Elliott Hughes966dd552016-12-08 15:56:04 -08002485 (mksh_cdirsep(mksh_abspath_s[0]) || \
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002486 (ksh_isalpha(mksh_abspath_s[0]) && \
Elliott Hughes96b43632015-07-17 11:39:41 -07002487 mksh_abspath_s[1] == ':')); \
2488})
Elliott Hughes966dd552016-12-08 15:56:04 -08002489#define mksh_cdirsep(c) __extension__({ \
2490 char mksh_cdirsep_c = (c); \
2491 (mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\'); \
2492})
Elliott Hughesa3c3f962017-04-12 16:52:30 -07002493#define mksh_sdirsep(s) __extension__({ \
2494 const char *mksh_sdirsep_s = (s); \
2495 ((char *)((ksh_isalphx(mksh_sdirsep_s[0]) && \
2496 mksh_sdirsep_s[1] == ':' && \
2497 !mksh_cdirsep(mksh_sdirsep_s[2])) ? \
2498 (mksh_sdirsep_s + 1) : strpbrk(mksh_sdirsep_s, "/\\"))); \
2499})
2500#define mksh_vdirsep(s) (mksh_sdirsep((s)) != NULL)
Elliott Hughes96b43632015-07-17 11:39:41 -07002501#else
Elliott Hughes96b43632015-07-17 11:39:41 -07002502#define mksh_abspath(s) ((s)[0] == '/')
Elliott Hughes966dd552016-12-08 15:56:04 -08002503#define mksh_cdirsep(c) ((c) == '/')
2504#define mksh_sdirsep(s) strchr((s), '/')
2505#define mksh_vdirsep(s) vstrchr((s), '/')
Elliott Hughes96b43632015-07-17 11:39:41 -07002506#endif
2507
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002508/* be sure not to interfere with anyone else's idea about EXTERN */
2509#ifdef EXTERN_DEFINED
2510# undef EXTERN_DEFINED
2511# undef EXTERN
2512#endif
Geremy Condra03ebf062011-10-12 18:17:24 -07002513#undef E_INIT
Jean-Baptiste Queru5155f1c2011-06-16 10:05:28 -07002514
2515#endif /* !MKSH_INCLUDES_ONLY */