* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2019, 2020
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
* is granted to deal in this work without restriction, including un‐
* limited rights to use, publicly perform, distribute, sell, modify,
* merge, give away, or sublicence.
*
* This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
* the utmost extent permitted by applicable law, neither express nor
* implied; without malicious intent or gross negligence. In no event
* may a licensor, author or contributor be held liable for indirect,
* direct, other damage, loss, or other issues arising in any way out
* of dealing in the work, even if advised of the possibility of such
* damage or existence of a defect, except proven that it results out
* of said person’s immediate fault when using the work as intended.
*/
#ifdef __dietlibc__
#define _BSD_SOURCE
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/types.h>
#if HAVE_BOTH_TIME_H
#include <sys/time.h>
#include <time.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#elif HAVE_TIME_H
#include <time.h>
#endif
#include <sys/ioctl.h>
#if HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
#if HAVE_SYS_MKDEV_H
#include <sys/mkdev.h>
#endif
#if HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#if HAVE_IO_H
#include <io.h>
#endif
#if HAVE_LIBGEN_H
#include <libgen.h>
#endif
#if HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#include <limits.h>
#if HAVE_PATHS_H
#include <paths.h>
#endif
#ifndef MKSH_NOPWNAM
#include <pwd.h>
#endif
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_STRINGS_H
#include <strings.h>
#endif
#if HAVE_TERMIOS_H
#include <termios.h>
#else
#include <termio.h>
#endif
#ifdef _ISC_UNIX
#include <sys/sioctl.h>
#endif
#if HAVE_ULIMIT_H
#include <ulimit.h>
#endif
#include <unistd.h>
#if HAVE_VALUES_H
#include <values.h>
#endif
#ifdef MIRBSD_BOOTFLOPPY
#include <wchar.h>
#endif
#if (defined(__KLIBC__) || defined(__dietlibc__)) && \
((defined(__GNUC__) && (__GNUC__ > 3)) || defined(__NWCC__))
#undef offsetof
#define offsetof(s,e) __builtin_offsetof(s, e)
#endif
#undef __attribute__
#if HAVE_ATTRIBUTE_BOUNDED
#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__(x, y, z)))
#else
#define MKSH_A_BOUNDED(x,y,z)
#endif
#if HAVE_ATTRIBUTE_FORMAT
#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__(x, y, z)))
#else
#define MKSH_A_FORMAT(x,y,z)
#endif
#if HAVE_ATTRIBUTE_NORETURN
#define MKSH_A_NORETURN __attribute__((__noreturn__))
#else
#define MKSH_A_NORETURN
#endif
#if HAVE_ATTRIBUTE_PURE
#define MKSH_A_PURE __attribute__((__pure__))
#else
#define MKSH_A_PURE
#endif
#if HAVE_ATTRIBUTE_UNUSED
#define MKSH_A_UNUSED __attribute__((__unused__))
#else
#define MKSH_A_UNUSED
#endif
#if HAVE_ATTRIBUTE_USED
#define MKSH_A_USED __attribute__((__used__))
#else
#define MKSH_A_USED
#endif
#if defined(MirBSD) && (MirBSD >= 0x09A1) && \
defined(__ELF__) && defined(__GNUC__) && \
!defined(__llvm__) && !defined(__NWCC__)
* We got usable __IDSTRING __COPYRIGHT __RCSID __SCCSID macros
* which work for all cases; no need to redefine them using the
* "portable" macros from below when we might have the "better"
* gcc+ELF specific macros or other system dependent ones.
*/
#else
#undef __IDSTRING
#undef __IDSTRING_CONCAT
#undef __IDSTRING_EXPAND
#undef __COPYRIGHT
#undef __RCSID
#undef __SCCSID
#define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p
#define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p)
#ifdef MKSH_DONT_EMIT_IDSTRING
#define __IDSTRING(prefix,string)
#elif defined(__ELF__) && defined(__GNUC__) && \
!(defined(__GNUC__) && defined(__mips16) && (__GNUC__ >= 8)) && \
!defined(__llvm__) && !defined(__NWCC__) && !defined(NO_ASM)
#define __IDSTRING(prefix,string) \
__asm__(".section .comment" \
"\n .ascii \"@(\"\"#)" #prefix ": \"" \
"\n .asciz \"" string "\"" \
"\n .previous")
#else
#define __IDSTRING(prefix,string) \
static const char __IDSTRING_EXPAND(__LINE__,prefix) [] \
MKSH_A_USED = "@(""#)" #prefix ": " string
#endif
#define __COPYRIGHT(x) __IDSTRING(copyright,x)
#define __RCSID(x) __IDSTRING(rcsid,x)
#define __SCCSID(x) __IDSTRING(sccsid,x)
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.904 2020/10/31 03:53:06 tg Exp $");
#endif
#define MKSH_VERSION "R59 2020/10/31"
#if !HAVE_CAN_INTTYPES
#if !HAVE_CAN_UCBINTS
typedef signed int int32_t;
typedef unsigned int uint32_t;
#else
typedef u_int32_t uint32_t;
#endif
#endif
#ifdef MKSH_LEGACY_MODE
* POSIX demands these to be the C environment's long type
*/
typedef long mksh_ari_t;
typedef unsigned long mksh_uari_t;
#else
* These types are exactly 32 bit wide; signed and unsigned
* integer wraparound, even across division and modulo, for
* any shell code using them, is guaranteed.
*/
typedef int32_t mksh_ari_t;
typedef uint32_t mksh_uari_t;
#endif
typedef unsigned char mksh_bool;
#undef bool
#undef false
#undef true
#define bool mksh_bool
#define false 0
#define true 1
#define tobool(cond) ((cond) ? true : false)
#if !HAVE_CAN_INT8TYPE
#if !HAVE_CAN_UCBINT8
typedef unsigned char uint8_t;
#else
typedef u_int8_t uint8_t;
#endif
#endif
#if !HAVE_SIG_T
#undef sig_t
typedef void (*sig_t)(int);
#endif
#ifdef MKSH_TYPEDEF_SIG_ATOMIC_T
typedef MKSH_TYPEDEF_SIG_ATOMIC_T sig_atomic_t;
#endif
#ifdef MKSH_OH_ADAPT
#define MAX_WRITE_RETRY_TIME 10
#endif
#ifdef MKSH_TYPEDEF_SSIZE_T
typedef MKSH_TYPEDEF_SSIZE_T ssize_t;
#endif
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
#define MKSH_SHF_NO_INLINE
#endif
#ifdef __neatcc__
#define MKSH_SHF_NO_INLINE
#endif
#undef BAD
#undef PRINT
#undef flock
#ifndef MKSH_INCLUDES_ONLY
#define cta(name,expr) struct cta_ ## name { char t[(expr) ? 1 : -1]; }
#if defined(MKSH_FOR_Z_OS) && defined(__MVS__) && defined(__IBMC__) && defined(__CHARSET_LIB)
# if !__CHARSET_LIB && !defined(MKSH_EBCDIC)
# error "Please compile with Build.sh -E for EBCDIC!"
# endif
# if __CHARSET_LIB && defined(MKSH_EBCDIC)
# error "Please compile without -E argument to Build.sh for ASCII!"
# endif
# if __CHARSET_LIB && !defined(_ENHANCED_ASCII_EXT)
# define _ENHANCED_ASCII_EXT 0xFFFFFFFF
# endif
#endif
#if !HAVE_GETRUSAGE && !defined(__OS2__)
#undef rusage
#undef RUSAGE_SELF
#undef RUSAGE_CHILDREN
#define rusage mksh_rusage
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN -1
struct rusage {
struct timeval ru_utime;
struct timeval ru_stime;
};
#endif
#ifndef timerclear
#define timerclear(tvp) \
do { \
(tvp)->tv_sec = (tvp)->tv_usec = 0; \
} while ( 0)
#endif
#ifndef timeradd
#define timeradd(tvp,uvp,vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while ( 0)
#endif
#ifndef timersub
#define timersub(tvp,uvp,vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while ( 0)
#endif
#ifdef MKSH__NO_PATH_MAX
#undef PATH_MAX
#else
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#ifndef SIZE_MAX
#ifdef SIZE_T_MAX
#define SIZE_MAX SIZE_T_MAX
#else
#define SIZE_MAX ((size_t)-1)
#endif
#endif
#ifndef S_ISLNK
#define S_ISLNK(m) ((m & 0170000) == 0120000)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(m) ((m & 0170000) == 0140000)
#endif
#if !defined(S_ISCDF) && defined(S_CDF)
#define S_ISCDF(m) (S_ISDIR(m) && ((m) & S_CDF))
#endif
#ifndef DEFFILEMODE
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
#endif
#undef ksh_NSIG
#if defined(NSIG)
#define ksh_NSIG (NSIG)
#elif defined(_NSIG)
#define ksh_NSIG (_NSIG)
#elif defined(SIGMAX)
#define ksh_NSIG (SIGMAX + 1)
#elif defined(_SIGMAX)
#define ksh_NSIG (_SIGMAX + 1)
#elif defined(NSIG_MAX)
#define ksh_NSIG (NSIG_MAX)
#elif defined(MKSH_FOR_Z_OS)
#define ksh_NSIG 40
#else
# error Please have your platform define NSIG.
#endif
#if (ksh_NSIG < 1)
# error Your NSIG value is not positive.
#undef ksh_NSIG
#endif
#ifdef NSIG_MAX
#if (NSIG_MAX < 2)
# error Your NSIG_MAX value is too small.
#undef NSIG_MAX
#elif (ksh_NSIG > NSIG_MAX)
# error Your NSIG value is larger than your NSIG_MAX value.
#undef NSIG_MAX
#else
#undef ksh_NSIG
#define ksh_NSIG (NSIG_MAX)
#endif
#endif
#ifndef ksh_NSIG
#define ksh_NSIG 64
#endif
#define ksh_sigmask(sig) (((sig) < 1 || (sig) > 127) ? 255 : 128 + (sig))
#ifdef MKSH_EXE_EXT
#undef MKSH_EXE_EXT
#define MKSH_EXE_EXT ".exe"
#else
#define MKSH_EXE_EXT ""
#endif
#ifdef __OS2__
#define MKSH_UNIXROOT "/@unixroot"
#else
#define MKSH_UNIXROOT ""
#endif
#ifdef MKSH_DOSPATH
#ifndef __GNUC__
# error GCC extensions needed later on
#endif
#define MKSH_PATHSEPS ";"
#define MKSH_PATHSEPC ';'
#else
#define MKSH_PATHSEPS ":"
#define MKSH_PATHSEPC ':'
#endif
#if !HAVE_FLOCK_DECL
extern int flock(int, int);
#endif
#if !HAVE_GETTIMEOFDAY
#define mksh_TIME(tv) do { \
(tv).tv_usec = 0; \
(tv).tv_sec = time(NULL); \
} while ( 0)
#else
#define mksh_TIME(tv) gettimeofday(&(tv), NULL)
#endif
#if !HAVE_GETRUSAGE
extern int getrusage(int, struct rusage *);
#endif
#if !HAVE_MEMMOVE
#define memmove(dst,src,len) bcopy((src), (dst), (len))
#endif
#if !HAVE_REVOKE_DECL
extern int revoke(const char *);
#endif
#if defined(DEBUG) || !HAVE_STRERROR
#undef strerror
#define strerror dontuse_strerror
#define cstrerror cstrerror
extern const char *cstrerror(int);
#else
#define cstrerror(errnum) ((const char *)strerror(errnum))
#endif
#if !HAVE_STRLCPY
size_t strlcpy(char *, const char *, size_t);
#endif
#ifdef __INTERIX
#define makedev mkdev
extern int __cdecl seteuid(uid_t);
extern int __cdecl setegid(gid_t);
#endif
#if defined(__COHERENT__)
#ifndef O_ACCMODE
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#undef O_MAYEXEC
#define O_MAYEXEC 0
#ifdef MKSH__NO_SYMLINK
#undef S_ISLNK
#define S_ISLNK(m) ( 0)
#define mksh_lstat stat
#else
#define mksh_lstat lstat
#endif
#if HAVE_TERMIOS_H
#define mksh_ttyst struct termios
#define mksh_tcget(fd,st) tcgetattr((fd), (st))
#define mksh_tcset(fd,st) tcsetattr((fd), TCSADRAIN, (st))
#else
#define mksh_ttyst struct termio
#define mksh_tcget(fd,st) ioctl((fd), TCGETA, (st))
#define mksh_tcset(fd,st) ioctl((fd), TCSETAW, (st))
#endif
#ifndef ISTRIP
#define ISTRIP 0
#endif
#ifdef MKSH_EBCDIC
#define KSH_BEL '\a'
#define KSH_ESC 047
#define KSH_ESC_STRING "\047"
#define KSH_VTAB '\v'
#else
* According to the comments in pdksh, \007 seems to be more portable
* than \a (HP-UX cc, Ultrix cc, old pcc, etc.) so we avoid the escape
* sequence if ASCII can be assumed.
*/
#define KSH_BEL 7
#define KSH_ESC 033
#define KSH_ESC_STRING "\033"
#define KSH_VTAB 11
#endif
#ifdef EXTERN
# define E_INIT(i) = i
#else
# define E_INIT(i)
# define EXTERN extern
# define EXTERN_DEFINED
#endif
#define BIT(i) (1U << (i))
#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
* Make MAGIC a char that might be printed to make bugs more obvious, but
* not a char that is used often. Also, can't use the high bit as it causes
* portability problems (calling strchr(x, 0x80 | 'x') is error prone).
*
* MAGIC can be followed by MAGIC (to escape the octet itself) or one of:
* ' !)*,-?[]{|}' 0x80|' !*+?@' (probably… hysteric raisins abound)
*
* The |0x80 is likely unsafe on EBCDIC :( though the listed chars are
* low-bit7 at least on cp1047 so YMMV
*/
#define MAGIC KSH_BEL
#define ISMAGIC(c) (ord(c) == ORD(MAGIC))
EXTERN const char *safe_prompt;
#ifdef MKSH_LEGACY_MODE
#define KSH_VERSIONNAME_ISLEGACY "LEGACY"
#else
#define KSH_VERSIONNAME_ISLEGACY "MIRBSD"
#endif
#ifdef MKSH_WITH_TEXTMODE
#define KSH_VERSIONNAME_TEXTMODE " +TEXTMODE"
#else
#define KSH_VERSIONNAME_TEXTMODE ""
#endif
#ifdef MKSH_EBCDIC
#define KSH_VERSIONNAME_EBCDIC " +EBCDIC"
#else
#define KSH_VERSIONNAME_EBCDIC ""
#endif
#ifndef KSH_VERSIONNAME_VENDOR_EXT
#define KSH_VERSIONNAME_VENDOR_EXT ""
#endif
EXTERN const char initvsn[] E_INIT("KSH_VERSION=@(#)" KSH_VERSIONNAME_ISLEGACY \
" KSH " MKSH_VERSION KSH_VERSIONNAME_EBCDIC KSH_VERSIONNAME_TEXTMODE \
KSH_VERSIONNAME_VENDOR_EXT);
#define KSH_VERSION (initvsn + 16)
EXTERN const char digits_uc[] E_INIT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
EXTERN const char digits_lc[] E_INIT("0123456789abcdefghijklmnopqrstuvwxyz");
* Evil hack for const correctness due to API brokenness
*/
union mksh_cchack {
char *rw;
const char *ro;
};
union mksh_ccphack {
char **rw;
const char **ro;
};
* Evil hack since casting uint to sint is implementation-defined
*/
typedef union {
mksh_ari_t i;
mksh_uari_t u;
} mksh_ari_u;
#if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \
!defined(__INTEL_COMPILER) && !defined(__SUNPRO_C)
char *ucstrchr(char *, int);
char *ucstrstr(char *, const char *);
#undef strchr
#define strchr ucstrchr
#define strstr ucstrstr
#define cstrchr(s,c) ({ \
union mksh_cchack in, out; \
\
in.ro = (s); \
out.rw = ucstrchr(in.rw, (c)); \
(out.ro); \
})
#define cstrstr(b,l) ({ \
union mksh_cchack in, out; \
\
in.ro = (b); \
out.rw = ucstrstr(in.rw, (l)); \
(out.ro); \
})
#define vstrchr(s,c) (cstrchr((s), (c)) != NULL)
#define vstrstr(b,l) (cstrstr((b), (l)) != NULL)
#else
#define cstrchr(s,c) ((const char *)strchr((s), (c)))
#define cstrstr(s,c) ((const char *)strstr((s), (c)))
#define vstrchr(s,c) (strchr((s), (c)) != NULL)
#define vstrstr(b,l) (strstr((b), (l)) != NULL)
#endif
#if defined(DEBUG) || defined(__COVERITY__)
#ifndef DEBUG_LEAKS
#define DEBUG_LEAKS
#endif
#endif
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 593)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
im_sorry_dave(void)
{
return (thiswillneverbedefinedIhope());
}
#endif
#define strnul(s) ((s) + strlen((const void *)s))
#define utf_ptradjx(src,dst) do { \
(dst) = (src) + utf_ptradj(src); \
} while ( 0)
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
#define strdupx(d,s,ap) do { \
(d) = strdup_i((s), (ap)); \
} while ( 0)
#define strndupx(d,s,n,ap) do { \
(d) = strndup_i((s), (n), (ap)); \
} while ( 0)
#else
#define strdupx(d,s,ap) do { \
const char *strdup_src = (const void *)(s); \
char *strdup_dst = NULL; \
\
if (strdup_src != NULL) { \
size_t strdup_len = strlen(strdup_src) + 1; \
strdup_dst = alloc(strdup_len, (ap)); \
memcpy(strdup_dst, strdup_src, strdup_len); \
} \
(d) = strdup_dst; \
} while ( 0)
#define strndupx(d,s,n,ap) do { \
const char *strdup_src = (const void *)(s); \
char *strdup_dst = NULL; \
\
if (strdup_src != NULL) { \
size_t strndup_len = (n); \
strdup_dst = alloc(strndup_len + 1, (ap)); \
memcpy(strdup_dst, strdup_src, strndup_len); \
strdup_dst[strndup_len] = '\0'; \
} \
(d) = strdup_dst; \
} while ( 0)
#endif
#define strdup2x(d,s1,s2) do { \
const char *strdup_src = (const void *)(s1); \
const char *strdup_app = (const void *)(s2); \
size_t strndup_len = strlen(strdup_src); \
size_t strndup_ln2 = strlen(strdup_app) + 1; \
char *strdup_dst = alloc(strndup_len + strndup_ln2, ATEMP); \
\
memcpy(strdup_dst, strdup_src, strndup_len); \
memcpy(strdup_dst + strndup_len, strdup_app, strndup_ln2); \
(d) = strdup_dst; \
} while ( 0)
#define strpathx(d,s1,s2,cond) do { \
const char *strdup_src = (const void *)(s1); \
const char *strdup_app = (const void *)(s2); \
size_t strndup_len = strlen(strdup_src) + 1; \
size_t strndup_ln2 = ((cond) || *strdup_app) ? \
strlen(strdup_app) + 1 : 0; \
char *strdup_dst = alloc(strndup_len + strndup_ln2, ATEMP); \
\
memcpy(strdup_dst, strdup_src, strndup_len); \
if (strndup_ln2) { \
strdup_dst[strndup_len - 1] = '/'; \
memcpy(strdup_dst + strndup_len, strdup_app, \
strndup_ln2); \
} \
(d) = strdup_dst; \
} while ( 0)
#ifdef MKSH_SMALL
#ifndef MKSH_NOPWNAM
#define MKSH_NOPWNAM
#endif
#ifndef MKSH_S_NOVI
#define MKSH_S_NOVI 1
#endif
#endif
#ifndef MKSH_S_NOVI
#define MKSH_S_NOVI 0
#endif
#if defined(MKSH_NOPROSPECTOFWORK) && !defined(MKSH_UNEMPLOYED)
#define MKSH_UNEMPLOYED 1
#endif
#define NUFILE 32
#define FDBASE 10
* simple grouping allocator
*/
#define malloc_osi(sz) malloc(sz)
#define realloc_osi(p,sz) realloc((p), (sz))
#define free_osimalloc(p) free(p)
#define malloc_osfunc(sz) malloc(sz)
#define realloc_osfunc(p,sz) realloc((p), (sz))
#define free_osfunc(p) free(p)
#if HAVE_MKNOD
#define free_ossetmode(p) free(p)
#endif
#ifdef MKSH__NO_PATH_MAX
#define free_gnu_gcdn(p) free(p)
#endif
struct lalloc_common {
struct lalloc_common *next;
};
#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
struct lalloc_item {
struct lalloc_common *next;
size_t len;
char dummy[8192 - sizeof(struct lalloc_common *) - sizeof(size_t)];
};
#endif
#ifdef MKSH_ALLOC_CATCH_UNDERRUNS
#define ALLOC_ITEM struct lalloc_item
#define ALLOC_OVERHEAD 0
#else
#define ALLOC_ITEM struct lalloc_common
#define ALLOC_OVERHEAD (sizeof(ALLOC_ITEM))
#endif
typedef struct lalloc_common Area;
EXTERN Area aperm;
#define APERM &aperm
#define ATEMP &e->area
* flags (the order of these enums MUST match the order in misc.c(options[]))
*/
enum sh_flag {
#define SHFLAGS_ENUMS
#include "sh_flags.gen"
FNFLAGS
};
#define Flag(f) (shell_flags[(int)(f)])
#define UTFMODE Flag(FUNNYCODE)
* parsing & execution environment
*
* note that kshlongjmp MUST NOT be passed 0 as second argument!
*/
#ifdef MKSH_NO_SIGSETJMP
#define kshjmp_buf jmp_buf
#define kshsetjmp(jbuf) _setjmp(jbuf)
#define kshlongjmp _longjmp
#else
#define kshjmp_buf sigjmp_buf
#define kshsetjmp(jbuf) sigsetjmp((jbuf), 0)
#define kshlongjmp siglongjmp
#endif
struct sretrace_info;
struct yyrecursive_state;
EXTERN struct sretrace_info *retrace_info;
EXTERN unsigned int subshell_nesting_type;
extern struct env {
ALLOC_ITEM alloc_INT;
Area area;
struct env *oenv;
struct block *loc;
short *savefd;
struct temp *temps;
struct yyrecursive_state *yyrecursive_statep;
kshjmp_buf jbuf;
uint8_t type;
uint8_t flags;
} *e;
#define E_NONE 0
#define E_PARSE 1
#define E_FUNC 2
#define E_INCL 3
#define E_EXEC 4
#define E_LOOP 5
#define E_ERRH 6
#define E_GONE 7
#define E_EVAL 8
#define EF_BRKCONT_PASS BIT(1)
#define EF_FAKE_SIGDIE BIT(2)
#define EF_IN_EVAL BIT(3)
#define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE || \
(t) == E_FUNC || (t) == E_INCL)
#define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL)
#define LRETURN 1
#define LEXIT 2
#define LERROR 3
#define LERREXT 4
#define LINTR 5
#define LBREAK 6
#define LCONTIN 7
#define LSHELL 8
#define LAEXPR 9
#define LLEAVE 10
EXTERN pid_t procpid;
EXTERN int exstat;
EXTERN int subst_exstat;
EXTERN struct tbl *vp_pipest;
EXTERN short trap_exstat;
EXTERN uint8_t trap_nested;
EXTERN uint8_t shell_flags[FNFLAGS];
EXTERN uint8_t baseline_flags[FNFLAGS
#if !defined(MKSH_SMALL) || defined(DEBUG)
+ 1
#endif
];
EXTERN bool as_builtin;
EXTERN const char *kshname;
EXTERN struct {
uid_t kshuid_v;
uid_t ksheuid_v;
gid_t kshgid_v;
gid_t kshegid_v;
pid_t kshpgrp_v;
pid_t kshppid_v;
pid_t kshpid_v;
} rndsetupstate;
#define kshpid rndsetupstate.kshpid_v
#define kshpgrp rndsetupstate.kshpgrp_v
#define kshuid rndsetupstate.kshuid_v
#define ksheuid rndsetupstate.ksheuid_v
#define kshgid rndsetupstate.kshgid_v
#define kshegid rndsetupstate.kshegid_v
#define kshppid rndsetupstate.kshppid_v
#define OF_CMDLINE 0x01
#define OF_SET 0x02
#define OF_SPECIAL 0x04
#define OF_INTERNAL 0x08
#define OF_FIRSTTIME 0x10
#define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL)
EXTERN char null[] E_INIT("");
#ifndef HAVE_STRING_POOLING
#elif HAVE_STRING_POOLING == 2
#ifdef __GNUC__
#if __GNUC__ < 4
#undef HAVE_STRING_POOLING
#endif
#else
#endif
#elif HAVE_STRING_POOLING == 0
#undef HAVE_STRING_POOLING
#endif
#ifndef HAVE_STRING_POOLING
EXTERN const char T4spaces[] E_INIT(" ");
#define T1space (Treal_sp2 + 5)
#define Tcolsp (Tf_sD_ + 2)
#define TC_IFSWS (TinitIFS + 4)
EXTERN const char TinitIFS[] E_INIT("IFS= \t\n");
EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_");
#define Tspdollaru (TFCEDIT_dollaru + 18)
EXTERN const char Tsgdot[] E_INIT("*=.");
EXTERN const char Taugo[] E_INIT("augo");
EXTERN const char Tbracket[] E_INIT("[");
#define Tdot (Tsgdot + 2)
#define Talias (Tunalias + 2)
EXTERN const char Tbadnum[] E_INIT("bad number");
#define Tbadsubst (Tfg_badsubst + 10)
EXTERN const char Tbg[] E_INIT("bg");
EXTERN const char Tbad_bsize[] E_INIT("bad shf/buf/bsize");
#define Tbsize (Tbad_bsize + 12)
EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'");
#define Tbad_sig_s (Tbad_sig_ss + 4)
EXTERN const char Tsgbreak[] E_INIT("*=break");
#define Tbreak (Tsgbreak + 2)
EXTERN const char T__builtin[] E_INIT("-\\builtin");
#define T_builtin (T__builtin + 1)
#define Tbuiltin (T__builtin + 2)
EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd");
EXTERN const char Tcant_find[] E_INIT("can't find");
EXTERN const char Tcant_open[] E_INIT("can't open");
#define Tbytes (Toomem + 24)
EXTERN const char Tbcat[] E_INIT("!cat");
#define Tcat (Tbcat + 1)
#define Tcd (Tcant_cd + 25)
#define T_command (T_funny_command + 9)
#define Tcommand (T_funny_command + 10)
EXTERN const char Tsgcontinue[] E_INIT("*=continue");
#define Tcontinue (Tsgcontinue + 2)
EXTERN const char Tcreate[] E_INIT("create");
EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected");
EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL");
EXTERN const char TENV[] E_INIT("ENV");
EXTERN const char Tdsgexport[] E_INIT("^*=export");
#define Texport (Tdsgexport + 3)
#ifdef __OS2__
EXTERN const char Textproc[] E_INIT("extproc");
#endif
EXTERN const char Tfalse[] E_INIT("false");
EXTERN const char Tfg[] E_INIT("fg");
EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
#define Tfile (Tfile_fd + 20)
EXTERN const char Tfile_fd[] E_INIT("function definition file");
EXTERN const char TFPATH[] E_INIT("FPATH");
EXTERN const char T_function[] E_INIT(" function");
#define Tfunction (T_function + 1)
EXTERN const char T_funny_command[] E_INIT("funny $()-command");
EXTERN const char Tgetopts[] E_INIT("getopts");
#define Thistory (Tnot_in_history + 7)
EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
EXTERN const char Tinvname[] E_INIT("%s: invalid %s name");
EXTERN const char Tjobs[] E_INIT("jobs");
EXTERN const char Tjob_not_started[] E_INIT("job not started");
EXTERN const char Tmksh[] E_INIT("mksh");
#define Tname (Tinvname + 15)
EXTERN const char Tno_args[] E_INIT("missing argument");
EXTERN const char Tno_OLDPWD[] E_INIT("no OLDPWD");
EXTERN const char Tnot_ident[] E_INIT("is not an identifier");
EXTERN const char Tnot_in_history[] E_INIT("not in history");
EXTERN const char Tnot_found_s[] E_INIT("%s not found");
#define Tnot_found (Tnot_found_s + 3)
#define Tnot_started (Tjob_not_started + 4)
#define TOLDPWD (Tno_OLDPWD + 3)
#define Topen (Tcant_open + 6)
EXTERN const char To_o_reset[] E_INIT(" -o .reset");
#define To_reset (To_o_reset + 4)
#define TPATH (TFPATH + 1)
#define Tpo (Tset_po + 4)
#define Tpv (TpVv + 1)
EXTERN const char TpVv[] E_INIT("Vpv");
#define TPWD (Tno_OLDPWD + 6)
#define Tread (Tshf_read + 4)
EXTERN const char Tdsgreadonly[] E_INIT("^*=readonly");
#define Treadonly (Tdsgreadonly + 3)
EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection");
#define Tredirection (Tredirection_dup + 19)
#define Treal_sp1 (Treal_sp2 + 1)
EXTERN const char Treal_sp2[] E_INIT(" real ");
EXTERN const char TREPLY[] E_INIT("REPLY");
EXTERN const char Treq_arg[] E_INIT("requires an argument");
EXTERN const char Tselect[] E_INIT("select");
#define Tset (Tf_parm + 18)
EXTERN const char Tset_po[] E_INIT("set +o");
EXTERN const char Tsghset[] E_INIT("*=#set");
#define Tsh (Tmksh + 2)
#define TSHELL (TEXECSHELL + 4)
#define Tshell (Ttoo_many_files + 23)
EXTERN const char Tshf_read[] E_INIT("shf_read");
EXTERN const char Tshf_write[] E_INIT("shf_write");
EXTERN const char Tgsource[] E_INIT("=source");
#define Tsource (Tgsource + 1)
EXTERN const char Tj_suspend[] E_INIT("j_suspend");
#define Tsuspend (Tj_suspend + 2)
EXTERN const char Tsynerr[] E_INIT("syntax error");
EXTERN const char Ttime[] E_INIT("time");
EXTERN const char Ttoo_many_args[] E_INIT("too many arguments");
EXTERN const char Ttoo_many_files[] E_INIT("too many open files in shell");
EXTERN const char Ttrue[] E_INIT("true");
EXTERN const char Ttty_fd_dupof[] E_INIT("dup of tty fd");
#define Ttty_fd (Ttty_fd_dupof + 7)
EXTERN const char Tdgtypeset[] E_INIT("^=typeset");
#define Ttypeset (Tdgtypeset + 2)
#define Tugo (Taugo + 1)
EXTERN const char Tunalias[] E_INIT("unalias");
#define Tunexpected (TELIF_unexpected + 6)
EXTERN const char Tunexpected_type[] E_INIT("%s: unexpected %s type %d");
EXTERN const char Tunknown_option[] E_INIT("unknown option");
EXTERN const char Tunwind[] E_INIT("unwind");
#define Tuser_sp1 (Tuser_sp2 + 1)
EXTERN const char Tuser_sp2[] E_INIT(" user ");
#define Twrite (Tshf_write + 4)
EXTERN const char Tf__S[] E_INIT(" %S");
#define Tf__d (Tunexpected_type + 22)
#define Tf_ss (Tf__ss + 1)
EXTERN const char Tf__ss[] E_INIT(" %s%s");
#define Tf__sN (Tf_s_s_sN + 5)
#define Tf_T (Tf_s_T + 3)
EXTERN const char Tf_dN[] E_INIT("%d\n");
EXTERN const char Tf_s_[] E_INIT("%s ");
EXTERN const char Tf_s_T[] E_INIT("%s %T");
EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n");
#define Tf_s_s (Tf_sD_s_s + 4)
#define Tf__s_s (Tf_sD_s_s + 3)
#define Tf_s_sD_s (Tf_cant_ss_s + 6)
EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s");
EXTERN const char Tf_sD_[] E_INIT("%s: ");
EXTERN const char Tf_szs[] E_INIT("%s: %zd %s");
EXTERN const char Tf_parm[] E_INIT("%s: parameter not set");
EXTERN const char Tf_coproc[] E_INIT("-p: %s");
EXTERN const char Tf_cant_s[] E_INIT("%s: can't %s");
EXTERN const char Tf_cant_ss_s[] E_INIT("can't %s %s: %s");
EXTERN const char Tf_heredoc[] E_INIT("here document '%s' unclosed");
#if HAVE_MKNOD
EXTERN const char Tf_nonnum[] E_INIT("non-numeric %s %s '%s'");
#endif
EXTERN const char Tf_S_[] E_INIT("%S ");
#define Tf_S (Tf__S + 1)
#define Tf_lu (Tf_toolarge + 17)
EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu");
EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s");
EXTERN const char Tf_sD_s_sD_s[] E_INIT("%s: %s %s: %s");
EXTERN const char Tf_toomany[] E_INIT("too many %ss");
EXTERN const char Tf_sd[] E_INIT("%s %d");
#define Tf_s (Tf_temp + 28)
EXTERN const char Tft_end[] E_INIT("%;");
EXTERN const char Tft_R[] E_INIT("%R");
#define Tf_d (Tunexpected_type + 23)
EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'");
EXTERN const char Tf_ro[] E_INIT("read-only: %s");
EXTERN const char Tf_flags[] E_INIT("%s: flags 0x%X");
EXTERN const char Tf_temp[] E_INIT("can't %s temporary file %s: %s");
EXTERN const char Tf_ssfaileds[] E_INIT("%s: %s failed: %s");
EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s");
EXTERN const char Tf__c_[] E_INIT("-%c ");
EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s");
#define Tf_sN (Tf_s_s_sN + 6)
#define Tf_sD_s (Tf_temp + 24)
EXTERN const char T_devtty[] E_INIT("/dev/tty");
#else
#define T4spaces " "
#define T1space " "
#define Tcolsp ": "
#define TC_IFSWS " \t\n"
#define TinitIFS "IFS= \t\n"
#define TFCEDIT_dollaru "${FCEDIT:-/bin/ed} $_"
#define Tspdollaru " $_"
#define Tsgdot "*=."
#define Taugo "augo"
#define Tbracket "["
#define Tdot "."
#define Talias "alias"
#define Tbadnum "bad number"
#define Tbadsubst "bad substitution"
#define Tbg "bg"
#define Tbad_bsize "bad shf/buf/bsize"
#define Tbsize "bsize"
#define Tbad_sig_ss "%s: bad signal '%s'"
#define Tbad_sig_s "bad signal '%s'"
#define Tsgbreak "*=break"
#define Tbreak "break"
#define T__builtin "-\\builtin"
#define T_builtin "\\builtin"
#define Tbuiltin "builtin"
#define Toomem "can't allocate %zu data bytes"
#define Tcant_cd "restricted shell - can't cd"
#define Tcant_find "can't find"
#define Tcant_open "can't open"
#define Tbytes "bytes"
#define Tbcat "!cat"
#define Tcat "cat"
#define Tcd "cd"
#define T_command "-command"
#define Tcommand "command"
#define Tsgcontinue "*=continue"
#define Tcontinue "continue"
#define Tcreate "create"
#define TELIF_unexpected "TELIF unexpected"
#define TEXECSHELL "EXECSHELL"
#define TENV "ENV"
#define Tdsgexport "^*=export"
#define Texport "export"
#ifdef __OS2__
#define Textproc "extproc"
#endif
#define Tfalse "false"
#define Tfg "fg"
#define Tfg_badsubst "fileglob: bad substitution"
#define Tfile "file"
#define Tfile_fd "function definition file"
#define TFPATH "FPATH"
#define T_function " function"
#define Tfunction "function"
#define T_funny_command "funny $()-command"
#define Tgetopts "getopts"
#define Thistory "history"
#define Tintovfl "integer overflow %zu %c %zu prevented"
#define Tinvname "%s: invalid %s name"
#define Tjobs "jobs"
#define Tjob_not_started "job not started"
#define Tmksh "mksh"
#define Tname "name"
#define Tno_args "missing argument"
#define Tno_OLDPWD "no OLDPWD"
#define Tnot_ident "is not an identifier"
#define Tnot_in_history "not in history"
#define Tnot_found_s "%s not found"
#define Tnot_found "not found"
#define Tnot_started "not started"
#define TOLDPWD "OLDPWD"
#define Topen "open"
#define To_o_reset " -o .reset"
#define To_reset ".reset"
#define TPATH "PATH"
#define Tpo "+o"
#define Tpv "pv"
#define TpVv "Vpv"
#define TPWD "PWD"
#define Tread "read"
#define Tdsgreadonly "^*=readonly"
#define Treadonly "readonly"
#define Tredirection_dup "can't finish (dup) redirection"
#define Tredirection "redirection"
#define Treal_sp1 "real "
#define Treal_sp2 " real "
#define TREPLY "REPLY"
#define Treq_arg "requires an argument"
#define Tselect "select"
#define Tset "set"
#define Tset_po "set +o"
#define Tsghset "*=#set"
#define Tsh "sh"
#define TSHELL "SHELL"
#define Tshell "shell"
#define Tshf_read "shf_read"
#define Tshf_write "shf_write"
#define Tgsource "=source"
#define Tsource "source"
#define Tj_suspend "j_suspend"
#define Tsuspend "suspend"
#define Tsynerr "syntax error"
#define Ttime "time"
#define Ttoo_many_args "too many arguments"
#define Ttoo_many_files "too many open files in shell"
#define Ttrue "true"
#define Ttty_fd_dupof "dup of tty fd"
#define Ttty_fd "tty fd"
#define Tdgtypeset "^=typeset"
#define Ttypeset "typeset"
#define Tugo "ugo"
#define Tunalias "unalias"
#define Tunexpected "unexpected"
#define Tunexpected_type "%s: unexpected %s type %d"
#define Tunknown_option "unknown option"
#define Tunwind "unwind"
#define Tuser_sp1 "user "
#define Tuser_sp2 " user "
#define Twrite "write"
#define Tf__S " %S"
#define Tf__d " %d"
#define Tf_ss "%s%s"
#define Tf__ss " %s%s"
#define Tf__sN " %s\n"
#define Tf_T "%T"
#define Tf_dN "%d\n"
#define Tf_s_ "%s "
#define Tf_s_T "%s %T"
#define Tf_s_s_sN "%s %s %s\n"
#define Tf_s_s "%s %s"
#define Tf__s_s " %s %s"
#define Tf_s_sD_s "%s %s: %s"
#define Tf_optfoo "%s%s-%c: %s"
#define Tf_sD_ "%s: "
#define Tf_szs "%s: %zd %s"
#define Tf_parm "%s: parameter not set"
#define Tf_coproc "-p: %s"
#define Tf_cant_s "%s: can't %s"
#define Tf_cant_ss_s "can't %s %s: %s"
#define Tf_heredoc "here document '%s' unclosed"
#if HAVE_MKNOD
#define Tf_nonnum "non-numeric %s %s '%s'"
#endif
#define Tf_S_ "%S "
#define Tf_S "%S"
#define Tf_lu "%lu"
#define Tf_toolarge "%s %s too large: %lu"
#define Tf_ldfailed "%s %s(%d, %ld) failed: %s"
#define Tf_sD_s_sD_s "%s: %s %s: %s"
#define Tf_toomany "too many %ss"
#define Tf_sd "%s %d"
#define Tf_s "%s"
#define Tft_end "%;"
#define Tft_R "%R"
#define Tf_d "%d"
#define Tf_sD_s_qs "%s: %s '%s'"
#define Tf_ro "read-only: %s"
#define Tf_flags "%s: flags 0x%X"
#define Tf_temp "can't %s temporary file %s: %s"
#define Tf_ssfaileds "%s: %s failed: %s"
#define Tf_sD_sD_s "%s: %s: %s"
#define Tf__c_ "-%c "
#define Tf_sD_s_s "%s: %s %s"
#define Tf_sN "%s\n"
#define Tf_sD_s "%s: %s"
#define T_devtty "/dev/tty"
#endif
typedef uint8_t Temp_type;
#define TT_HEREDOC_EXP 0
#define TT_HIST_EDIT 1
#define TT_FUNSUB 2
struct temp {
struct temp *next;
struct shf *shf;
pid_t pid;
Temp_type type;
char tffn[3];
};
* stdio and our IO routines
*/
#define shl_xtrace (&shf_iob[0])
#define shl_stdout (&shf_iob[1])
#define shl_out (&shf_iob[2])
#ifdef DF
#define shl_dbg (&shf_iob[3])
#endif
EXTERN bool shl_stdout_ok;
* trap handlers
*/
typedef struct trap {
const char *name;
const char *mess;
char *trap;
sig_t cursig;
sig_t shtrap;
int signal;
int flags;
volatile sig_atomic_t set;
} Trap;
#define TF_SHELL_USES BIT(0)
#define TF_USER_SET BIT(1)
#define TF_ORIG_IGN BIT(2)
#define TF_ORIG_DFL BIT(3)
#define TF_EXEC_IGN BIT(4)
#define TF_EXEC_DFL BIT(5)
#define TF_DFL_INTR BIT(6)
#define TF_TTY_INTR BIT(7)
#define TF_CHANGED BIT(8)
#define TF_FATAL BIT(9)
#define SS_RESTORE_MASK 0x3
#define SS_RESTORE_CURR 0
#define SS_RESTORE_ORIG 1
#define SS_RESTORE_DFL 2
#define SS_RESTORE_IGN 3
#define SS_FORCE BIT(3)
#define SS_USER BIT(4)
#define SS_SHTRAP BIT(5)
#define ksh_SIGEXIT 0
#define ksh_SIGERR ksh_NSIG
EXTERN volatile sig_atomic_t trap;
EXTERN volatile sig_atomic_t intrsig;
EXTERN volatile sig_atomic_t fatal_trap;
extern Trap sigtraps[ksh_NSIG + 1];
#ifdef SIGWINCH
EXTERN volatile sig_atomic_t got_winch E_INIT(1);
#else
#define got_winch true
#endif
* TMOUT support
*/
enum tmout_enum {
TMOUT_EXECUTING = 0,
TMOUT_READING,
TMOUT_LEAVING
};
EXTERN unsigned int ksh_tmout;
EXTERN enum tmout_enum ksh_tmout_state;
EXTERN bool really_exit;
* fast character classes
*/
#define CiIFS BIT(0)
#define CiCNTRL BIT(1)
#define CiUPPER BIT(2)
#define CiLOWER BIT(3)
#define CiHEXLT BIT(4)
#define CiOCTAL BIT(5)
#define CiQCL BIT(6)
#define CiALIAS BIT(7)
#define CiQCX BIT(8)
#define CiVAR1 BIT(9)
#define CiQCM BIT(10)
#define CiDIGIT BIT(11)
#define CiQC BIT(12)
#define CiSPX BIT(13)
#define CiCURLY BIT(14)
#define CiANGLE BIT(15)
#define CiNUL BIT(16)
#define CiTAB BIT(17)
#define CiNL BIT(18)
#define CiCR BIT(19)
#define CiSP BIT(20)
#define CiHASH BIT(21)
#define CiSS BIT(22)
#define CiPERCT BIT(23)
#define CiPLUS BIT(24)
#define CiMINUS BIT(25)
#define CiCOLON BIT(26)
#define CiEQUAL BIT(27)
#define CiQUEST BIT(28)
#define CiBRACK BIT(29)
#define CiUNDER BIT(30)
#define CiGRAVE BIT(31)
extern const uint32_t tpl_ctypes[128];
EXTERN uint32_t ksh_ctypes[256];
EXTERN char ifs0;
#define C_ALIAS (CiALIAS | CiBRACK | CiCOLON | CiDIGIT | CiLOWER | CiMINUS | CiOCTAL | CiPERCT | CiPLUS | CiUNDER | CiUPPER)
#define C_ALNUM (CiDIGIT | CiLOWER | CiOCTAL | CiUPPER)
#define C_ALNUX (CiDIGIT | CiLOWER | CiOCTAL | CiUNDER | CiUPPER)
#define C_ALPHA (CiLOWER | CiUPPER)
#define C_ALPHX (CiLOWER | CiUNDER | CiUPPER)
#define C_ASCII (CiALIAS | CiANGLE | CiBRACK | CiCNTRL | CiCOLON | CiCR | CiCURLY | CiDIGIT | CiEQUAL | CiGRAVE | CiHASH | CiLOWER | CiMINUS | CiNL | CiOCTAL | CiPERCT | CiPLUS | CiQC | CiQCL | CiQCM | CiQCX | CiQUEST | CiSP | CiSPX | CiSS | CiTAB | CiUNDER | CiUPPER)
#define C_BLANK (CiSP | CiTAB)
#define C_CFS (CiQC | CiSP | CiTAB)
#define C_CNTRL (CiCNTRL | CiCR | CiNL | CiNUL | CiSPX | CiTAB)
#define C_DIGIT (CiDIGIT | CiOCTAL)
#define C_EDCMD (CiGRAVE | CiQCL)
#define C_EDNWC (CiANGLE | CiCOLON | CiEQUAL | CiGRAVE | CiNL | CiQC | CiQCL | CiSP | CiTAB)
#define C_EDQ (CiANGLE | CiCOLON | CiCURLY | CiEQUAL | CiGRAVE | CiHASH | CiQC | CiQCL | CiQCX | CiQUEST | CiSS)
#define C_GRAPH (C_PUNCT | CiDIGIT | CiLOWER | CiOCTAL | CiUPPER)
#define C_HEXLT CiHEXLT
#define C_IFS (CiIFS | CiNUL)
#define C_IFSWS (CiNL | CiSP | CiTAB)
#define C_LEX1 (CiANGLE | CiNL | CiQCL | CiSP | CiTAB)
#define C_LOWER CiLOWER
#define C_MFS (CiALIAS | CiANGLE | CiBRACK | CiCNTRL | CiCOLON | CiCR | CiCURLY | CiEQUAL | CiGRAVE | CiHASH | CiMINUS | CiNL | CiNUL | CiPERCT | CiPLUS | CiQC | CiQCL | CiQCM | CiQCX | CiQUEST | CiSP | CiSPX | CiTAB)
#define C_OCTAL CiOCTAL
#define C_PATMO (CiPLUS | CiQUEST | CiVAR1)
#define C_PRINT (C_GRAPH | CiSP)
#define C_PUNCT (CiALIAS | CiANGLE | CiBRACK | CiCOLON | CiCURLY | CiEQUAL | CiGRAVE | CiHASH | CiMINUS | CiPERCT | CiPLUS | CiQC | CiQCL | CiQCM | CiQCX | CiQUEST | CiSS | CiUNDER)
#define C_QUOTE (CiANGLE | CiBRACK | CiEQUAL | CiGRAVE | CiHASH | CiNL | CiQC | CiQCL | CiQCX | CiQUEST | CiSS | CiTAB)
#define C_SEDEC (CiDIGIT | CiHEXLT | CiOCTAL)
#define C_SPACE (CiCR | CiNL | CiSP | CiSPX | CiTAB)
#define C_SUB1 (CiEQUAL | CiMINUS | CiPLUS | CiQUEST)
#define C_SUB2 (CiHASH | CiPERCT)
#define C_UPPER CiUPPER
#define C_VAR1 (CiHASH | CiMINUS | CiQUEST | CiSS | CiVAR1)
#define C_ANGLE CiANGLE
#define C_COLON CiCOLON
#define C_CR CiCR
#define C_DOLAR CiSS
#define C_EQUAL CiEQUAL
#define C_GRAVE CiGRAVE
#define C_HASH CiHASH
#define C_LF CiNL
#define C_MINUS CiMINUS
#ifdef MKSH_WITH_TEXTMODE
#define C_NL (CiNL | CiCR)
#else
#define C_NL CiNL
#endif
#define C_NUL CiNUL
#define C_PLUS CiPLUS
#define C_QC CiQC
#define C_QUEST CiQUEST
#define C_SPC CiSP
#define C_TAB CiTAB
#define C_UNDER CiUNDER
#if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \
!defined(__INTEL_COMPILER) && !defined(__SUNPRO_C)
extern unsigned int eek_ord;
#define ORD(c) ((size_t)(c) > 0xFF ? eek_ord : \
((unsigned int)(unsigned char)(c)))
#define ord(c) __builtin_choose_expr( \
__builtin_types_compatible_p(__typeof__(c), char) || \
__builtin_types_compatible_p(__typeof__(c), unsigned char), \
((unsigned int)(unsigned char)(c)), ({ \
size_t ord_c = (c); \
\
if (ord_c > (size_t)0xFFU) \
internal_errorf("%s:%d:ord(%zX)", \
__FILE__, __LINE__, ord_c); \
((unsigned int)(unsigned char)(ord_c)); \
}))
#else
#define ord(c) ((unsigned int)(unsigned char)(c))
#define ORD(c) ord(c)
#endif
#if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
EXTERN unsigned short ebcdic_map[256];
EXTERN unsigned char ebcdic_rtt_toascii[256];
EXTERN unsigned char ebcdic_rtt_fromascii[256];
extern void ebcdic_init(void);
#define asciibetical(c) ((unsigned int)ebcdic_map[(unsigned char)(c)])
#define rtt2asc(c) ebcdic_rtt_toascii[(unsigned char)(c)]
#define asc2rtt(c) ebcdic_rtt_fromascii[(unsigned char)(c)]
#define ksh_eq(c,u,l) (ord(c) == ord(u) || ord(c) == ord(l))
#else
#define asciibetical(c) ord(c)
#define rtt2asc(c) ((unsigned char)(c))
#define asc2rtt(c) ((unsigned char)(c))
#define ksh_eq(c,u,l) ((ord(c) | 0x20) == ord(l))
#endif
#ifdef MKSH_EBCDIC
#define ksh_isctrl(c) (ord(c) < 0x40 || ord(c) == 0xFF)
#else
#define ksh_isctrl(c) ((ord(c) & 0x7F) < 0x20 || ord(c) == 0x7F)
#endif
#define ctype(c,t) tobool(ksh_ctypes[ord(c)] & (t))
#define cinttype(c,t) ((c) >= 0 && (c) <= 0xFF ? \
tobool(ksh_ctypes[(unsigned char)(c)] & (t)) : false)
#define ksh_isdash(s) tobool(ord((s)[0]) == '-' && ord((s)[1]) == '\0')
#define ksh_tolower(c) (ctype(c, C_UPPER) ? (c) - 'A' + 'a' : (c))
#define ksh_toupper(c) (ctype(c, C_LOWER) ? (c) - 'a' + 'A' : (c))
#define ksh_numdig(c) (ord(c) - ORD('0'))
#define ksh_numuc(c) (rtt2asc(c) - rtt2asc('A'))
#define ksh_numlc(c) (rtt2asc(c) - rtt2asc('a'))
#define ksh_toctrl(c) asc2rtt(ord(c) == ORD('?') ? 0x7F : rtt2asc(c) & 0x9F)
#define ksh_unctrl(c) asc2rtt(rtt2asc(c) ^ 0x40U)
#ifdef MKSH_SMALL
#define SMALLP(x)
#else
#define SMALLP(x) , x
#endif
#define GF_ERROR BIT(0)
#define GF_PLUSOPT BIT(1)
#define GF_NONAME BIT(2)
#define GI_MINUS BIT(0)
#define GI_PLUS BIT(1)
#define GI_MINUSMINUS BIT(2)
#undef optarg
#undef optind
typedef struct {
const char *optarg;
int optind;
int uoptind;
int flags;
int info;
unsigned int p;
char buf[2];
} Getopt;
EXTERN Getopt builtin_opt;
EXTERN Getopt user_opt;
typedef int Coproc_id;
struct coproc {
void *job;
int read;
int readw;
int write;
int njobs;
Coproc_id id;
};
EXTERN struct coproc coproc;
#ifndef MKSH_NOPROSPECTOFWORK
EXTERN sigset_t sm_default, sm_sigchld;
#endif
EXTERN const char *builtin_argv0;
EXTERN bool builtin_spec;
EXTERN char *current_wd;
#ifdef MKSH_SMALL
#define LINE (4096 - ALLOC_OVERHEAD)
#else
#define LINE (16384 - ALLOC_OVERHEAD)
#endif
EXTERN mksh_ari_t x_cols E_INIT(80);
EXTERN mksh_ari_t x_lins E_INIT(24);
#ifndef MKSH_DEFAULT_PROFILEDIR
#define MKSH_DEFAULT_PROFILEDIR MKSH_UNIXROOT "/etc"
#endif
#define MKSH_SYSTEM_PROFILE MKSH_DEFAULT_PROFILEDIR "/profile"
#define MKSH_SUID_PROFILE MKSH_DEFAULT_PROFILEDIR "/suid_profile"
#define KSH_UNWIND_ERROR 0
#define KSH_RETURN_ERROR 1
* Shell file I/O routines
*/
#define SHF_BSIZE 512
#define shf_fileno(shf) ((shf)->fd)
#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd))
#define shf_getc_i(shf) ((shf)->rnleft > 0 ? \
(shf)->rnleft--, (int)ord(*(shf)->rp++) : \
shf_getchar(shf))
#define shf_putc_i(c,shf) ((shf)->wnleft == 0 ? \
shf_putchar((uint8_t)(c), (shf)) : \
((shf)->wnleft--, *(shf)->wp++ = (c)))
#define shf_eof(shf) ((shf)->flags & SHF_EOF)
#define shf_error(shf) ((shf)->flags & SHF_ERROR)
#define shf_errno(shf) ((shf)->errnosv)
#define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR))
#define SHF_RD 0x0001
#define SHF_WR 0x0002
#define SHF_RDWR (SHF_RD | SHF_WR)
#define SHF_ACCMODE 0x0003
#define SHF_GETFL 0x0004
#define SHF_UNBUF 0x0008
#define SHF_CLEXEC 0x0010
#define SHF_MAPHI 0x0020
* (shf_open() only) */
#define SHF_DYNAMIC 0x0040
#define SHF_INTERRUPT 0x0080
#define SHF_STRING 0x0100
#define SHF_ALLOCS 0x0200
#define SHF_ALLOCB 0x0400
#define SHF_ERROR 0x0800
#define SHF_EOF 0x1000
#define SHF_READING 0x2000
#define SHF_WRITING 0x4000
struct shf {
Area *areap;
unsigned char *rp;
unsigned char *wp;
unsigned char *buf;
ssize_t bsize;
ssize_t rbsize;
ssize_t rnleft;
ssize_t wbsize;
ssize_t wnleft;
int flags;
int fd;
int errnosv;
};
extern struct shf shf_iob[];
struct table {
Area *areap;
struct tbl **tbls;
size_t nfree;
uint8_t tshift;
};
struct tbl {
Area *areap;
union {
char *s;
mksh_ari_t i;
mksh_uari_t u;
int (*f)(const char **);
struct op *t;
} val;
union {
struct tbl *array;
const char *fpath;
} u;
union {
int field;
int errnov;
} u2;
union {
uint32_t hval;
uint32_t index;
} ua;
* command type (see below), base (if INTEGER),
* offset from val.s of value (if EXPORT)
*/
int type;
uint32_t flag;
char name[4];
};
EXTERN struct tbl *vtemp;
EXTERN bool last_lookup_was_array;
#define ALLOC BIT(0)
#define DEFINED BIT(1)
#define ISSET BIT(2)
#define EXPORT BIT(3)
#define TRACE BIT(4)
#define SPECIAL BIT(8)
#define INTEGER BIT(9)
#define RDONLY BIT(10)
#define LOCAL BIT(11)
#define ARRAY BIT(13)
#define LJUST BIT(14)
#define RJUST BIT(15)
#define ZEROFIL BIT(16)
#define LCASEV BIT(17)
#define UCASEV_AL BIT(18)
#define INT_U BIT(19)
#define INT_L BIT(20)
#define IMPORT BIT(21)
#define LOCAL_COPY BIT(22)
#define EXPRINEVAL BIT(23)
#define EXPRLVALUE BIT(24)
#define AINDEX BIT(25)
#define ASSOC BIT(26)
#define KEEPASN BIT(8)
#define FINUSE BIT(9)
#define FDELETE BIT(10)
#define FKSH BIT(11)
#define SPEC_BI BIT(12)
#define LOWER_BI BIT(13)
#define LOW_BI BIT(14)
#define DECL_UTIL BIT(15)
#define DECL_FWDR BIT(16)
#define NEXTLOC_BI BIT(17)
* Attributes that can be set by the user (used to decide if an unset
* param should be repoted by set/typeset). Does not include ARRAY or
* LOCAL.
*/
#define USERATTRIB (EXPORT | INTEGER | RDONLY | LJUST | RJUST | ZEROFIL | \
LCASEV | UCASEV_AL | INT_U | INT_L)
#define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
(vp)->ua.index : 0))
enum namerefflag {
SRF_NOP,
SRF_ENABLE,
SRF_DISABLE
};
#define CNONE 0
#define CSHELL 1
#define CFUNC 2
#define CEXEC 4
#define CALIAS 5
#define CKEYWD 6
#define CTALIAS 7
#define FC_SPECBI BIT(0)
#define FC_FUNC BIT(1)
#define FC_NORMBI BIT(2)
#define FC_BI (FC_SPECBI | FC_NORMBI)
#define FC_PATH BIT(3)
#define FC_DEFPATH BIT(4)
#define FC_WHENCE BIT(5)
#define AF_ARGV_ALLOC 0x1
#define AF_ARGS_ALLOCED 0x2
#define AI_ARGV(a,i) ((i) == 0 ? (a).argv[0] : (a).argv[(i) - (a).skip])
#define AI_ARGC(a) ((a).ai_argc - (a).skip)
struct arg_info {
const char **argv;
int flags;
int ai_argc;
int skip;
};
* activation record for function blocks
*/
struct block {
Area area;
const char **argv;
char *error;
char *exit;
struct block *next;
struct table vars;
struct table funs;
Getopt getopts_state;
int argc;
int flags;
};
#define BF_DOGETOPTS BIT(0)
#define BF_STOPENV BIT(1)
#define BF_RESETSPEC BIT(17)
* Used by ktwalk() and ktnext() routines.
*/
struct tstate {
struct tbl **next;
ssize_t left;
};
EXTERN struct table taliases;
EXTERN struct table builtins;
EXTERN struct table aliases;
EXTERN struct table keywords;
#ifndef MKSH_NOPWNAM
EXTERN struct table homedirs;
#endif
struct builtin {
const char *name;
int (*func)(const char **);
};
extern const struct builtin mkshbuiltins[];
#define PS1 0
#define PS2 1
EXTERN char *path;
EXTERN const char *def_path;
EXTERN char *tmpdir;
EXTERN const char *prompt;
EXTERN uint8_t cur_prompt;
EXTERN int current_lineno;
* Description of a command or an operation on commands.
*/
struct op {
const char **args;
char **vars;
struct ioword **ioact;
struct op *left, *right;
char *str;
* select, and functions;
* path to execute for TEXEC;
* time hook for TCOM.
*/
int lineno;
short type;
union {
short evalflags;
short ksh_func;
char charflag;
} u;
};
#define TEOF 0
#define TCOM 1
#define TPAREN 2
#define TPIPE 3
#define TLIST 4
#define TOR 5
#define TAND 6
#define TBANG 7
#define TDBRACKET 8
#define TFOR 9
#define TSELECT 10
#define TCASE 11
#define TIF 12
#define TWHILE 13
#define TUNTIL 14
#define TELIF 15
#define TPAT 16
#define TBRACE 17
#define TASYNC 18
#define TFUNCT 19
#define TTIME 20
#define TEXEC 21
#define TCOPROC 22
* prefix codes for words in command tree
*/
#define EOS 0
#define CHAR 1
#define QCHAR 2
#define COMSUB 3
#define EXPRSUB 4
#define OQUOTE 5
#define CQUOTE 6
#define OSUBST 7
#define CSUBST 8
#define OPAT 9
#define SPAT 10
#define CPAT 11
#define ADELIM 12
#define FUNSUB 14
#define VALSUB 15
#define COMASUB 16
#define FUNASUB 17
* IO redirection
*/
struct ioword {
char *ioname;
char *delim;
char *heredoc;
unsigned short ioflag;
short unit;
};
#define IOTYPE 0xF
#define IOREAD 0x1
#define IOWRITE 0x2
#define IORDWR 0x3
#define IOHERE 0x4
#define IOCAT 0x5
#define IODUP 0x6
#define IOEVAL BIT(4)
#define IOSKIP BIT(5)
#define IOCLOB BIT(6)
#define IORDUP BIT(7)
#define IODUPSELF BIT(8)
#define IONAMEXP BIT(9)
#define IOBASH BIT(10)
#define IOHERESTR BIT(11)
#define IONDELIM BIT(12)
#define XEXEC BIT(0)
#define XFORK BIT(1)
#define XBGND BIT(2)
#define XPIPEI BIT(3)
#define XPIPEO BIT(4)
#define XXCOM BIT(5)
#define XPCLOSE BIT(6)
#define XCCLOSE BIT(7)
#define XERROK BIT(8)
#define XCOPROC BIT(9)
#define XTIME BIT(10)
#define XPIPEST BIT(11)
* flags to control expansion of words (assumed by t->evalflags to fit
* in a short)
*/
#define DOBLANK BIT(0)
#define DOGLOB BIT(1)
#define DOPAT BIT(2)
#define DOTILDE BIT(3)
#define DONTRUNCOMMAND BIT(4)
#define DOASNTILDE BIT(5)
#define DOBRACE BIT(6)
#define DOMAGIC BIT(7)
#define DOTEMP BIT(8)
#define DOVACHECK BIT(9)
#define DOMARKDIRS BIT(10)
#define DOTCOMEXEC BIT(11)
#define DOSCALAR BIT(12)
#define DOHEREDOC BIT(13)
#define DOHERESTR BIT(14)
#define DODBMAGIC BIT(15)
#define X_EXTRA 20
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
#define X_WASTE 15
#else
#define X_WASTE 255
#endif
typedef struct XString {
char *beg;
size_t len;
char *end;
Area *areap;
} XString;
#define XinitN(xs,length,area) do { \
(xs).len = (length); \
(xs).areap = (area); \
(xs).beg = alloc((xs).len + X_EXTRA, (xs).areap); \
(xs).end = (xs).beg + (xs).len; \
} while ( 0)
#define Xinit(xs,xp,length,area) do { \
XinitN((xs), (length), (area)); \
(xp) = (xs).beg; \
} while ( 0)
#define Xput(xs,xp,c) (*xp++ = (c))
#define XcheckN(xs,xp,n) do { \
ssize_t more = ((xp) + (n)) - (xs).end; \
if (more > 0) \
(xp) = Xcheck_grow(&(xs), (xp), (size_t)more); \
} while ( 0)
#define Xcheck(xs,xp) XcheckN((xs), (xp), 1)
#define Xfree(xs,xp) afree((xs).beg, (xs).areap)
#define Xclose(xs,xp) aresize((xs).beg, (xp) - (xs).beg, (xs).areap)
#define Xstring(xs,xp) ((xs).beg)
#define Xnleft(xs,xp) ((xs).end - (xp))
#define Xlength(xs,xp) ((xp) - (xs).beg)
#define Xsize(xs,xp) ((xs).end - (xs).beg)
#define Xsavepos(xs,xp) ((xp) - (xs).beg)
#define Xrestpos(xs,xp,n) ((xs).beg + (n))
char *Xcheck_grow(XString *, const char *, size_t);
* expandable vector of generic pointers
*/
typedef struct {
void **beg;
size_t len;
size_t siz;
} XPtrV;
#define XPinit(x,n) do { \
(x).siz = (n); \
(x).len = 0; \
(x).beg = alloc2((x).siz, sizeof(void *), ATEMP); \
} while ( 0) \
#define XPput(x,p) do { \
if ((x).len == (x).siz) { \
(x).beg = aresize2((x).beg, (x).siz, \
2 * sizeof(void *), ATEMP); \
(x).siz <<= 1; \
} \
(x).beg[(x).len++] = (p); \
} while ( 0)
#define XPptrv(x) ((x).beg)
#define XPsize(x) ((x).len)
#define XPclose(x) aresize2((x).beg, XPsize(x), sizeof(void *), ATEMP)
#define XPfree(x) afree((x).beg, ATEMP)
struct columnise_opts {
struct shf *shf;
char linesep;
bool do_last;
bool prefcol;
};
* Lexer internals
*/
typedef struct source Source;
struct source {
XString xs;
Area *areap;
Source *next;
const char *str;
const char *start;
const char *file;
union {
const char **strv;
struct shf *shf;
struct tbl *tblp;
char *freeme;
} u;
int flags;
int type;
int line;
int errline;
char ugbuf[2];
};
#define SEOF 0
#define SFILE 1
#define SSTDIN 2
#define SSTRING 3
#define SWSTR 4
#define SWORDS 5
#define SWORDSEP 6
#define SALIAS 7
#define SREREAD 8
#define SSTRINGCMDLINE 9
#define SF_ECHO BIT(0)
#define SF_ALIAS BIT(1)
#define SF_ALIASEND BIT(2)
#define SF_TTY BIT(3)
#define SF_HASALIAS BIT(4)
#define SF_MAYEXEC BIT(5)
typedef union {
int i;
char *cp;
char **wp;
struct op *o;
struct ioword *iop;
} YYSTYPE;
#define LWORD 256
#define LOGAND 257
#define LOGOR 258
#define BREAK 259
#define IF 260
#define THEN 261
#define ELSE 262
#define ELIF 263
#define FI 264
#define CASE 265
#define ESAC 266
#define FOR 267
#define SELECT 268
#define WHILE 269
#define UNTIL 270
#define DO 271
#define DONE 272
#define IN 273
#define FUNCTION 274
#define TIME 275
#define REDIR 276
#define MDPAREN 277
#define BANG 278
#define DBRACKET 279
#define COPROC 280
#define BRKEV 281
#define BRKFT 282
#define YYERRCODE 300
#define CONTIN BIT(0)
#define ONEWORD BIT(1)
#define ALIAS BIT(2)
#define KEYWORD BIT(3)
#define LETEXPR BIT(4)
#define CMDASN BIT(5)
#define HEREDOC BIT(6)
#define ESACONLY BIT(7)
#define CMDWORD BIT(8)
#define HEREDELIM BIT(9)
#define LQCHAR BIT(10)
#define HERES 10
#ifdef MKSH_EBCDIC
#define CTRL_AT (0x00U)
#define CTRL_A (0x01U)
#define CTRL_B (0x02U)
#define CTRL_C (0x03U)
#define CTRL_D (0x37U)
#define CTRL_E (0x2DU)
#define CTRL_F (0x2EU)
#define CTRL_G (0x2FU)
#define CTRL_H (0x16U)
#define CTRL_I (0x05U)
#define CTRL_J (0x15U)
#define CTRL_K (0x0BU)
#define CTRL_L (0x0CU)
#define CTRL_M (0x0DU)
#define CTRL_N (0x0EU)
#define CTRL_O (0x0FU)
#define CTRL_P (0x10U)
#define CTRL_Q (0x11U)
#define CTRL_R (0x12U)
#define CTRL_S (0x13U)
#define CTRL_T (0x3CU)
#define CTRL_U (0x3DU)
#define CTRL_V (0x32U)
#define CTRL_W (0x26U)
#define CTRL_X (0x18U)
#define CTRL_Y (0x19U)
#define CTRL_Z (0x3FU)
#define CTRL_BO (0x27U)
#define CTRL_BK (0x1CU)
#define CTRL_BC (0x1DU)
#define CTRL_CA (0x1EU)
#define CTRL_US (0x1FU)
#define CTRL_QM (0x07U)
#else
#define CTRL_AT (0x00U)
#define CTRL_A (0x01U)
#define CTRL_B (0x02U)
#define CTRL_C (0x03U)
#define CTRL_D (0x04U)
#define CTRL_E (0x05U)
#define CTRL_F (0x06U)
#define CTRL_G (0x07U)
#define CTRL_H (0x08U)
#define CTRL_I (0x09U)
#define CTRL_J (0x0AU)
#define CTRL_K (0x0BU)
#define CTRL_L (0x0CU)
#define CTRL_M (0x0DU)
#define CTRL_N (0x0EU)
#define CTRL_O (0x0FU)
#define CTRL_P (0x10U)
#define CTRL_Q (0x11U)
#define CTRL_R (0x12U)
#define CTRL_S (0x13U)
#define CTRL_T (0x14U)
#define CTRL_U (0x15U)
#define CTRL_V (0x16U)
#define CTRL_W (0x17U)
#define CTRL_X (0x18U)
#define CTRL_Y (0x19U)
#define CTRL_Z (0x1AU)
#define CTRL_BO (0x1BU)
#define CTRL_BK (0x1CU)
#define CTRL_BC (0x1DU)
#define CTRL_CA (0x1EU)
#define CTRL_US (0x1FU)
#define CTRL_QM (0x7FU)
#endif
#define IDENT 64
EXTERN Source *source;
EXTERN YYSTYPE yylval;
EXTERN struct ioword *heres[HERES], **herep;
EXTERN char ident[IDENT + 1];
EXTERN char **history;
EXTERN char **histptr;
EXTERN mksh_ari_t histsize;
#define HIST_FLUSH 0
#define HIST_QUEUE 1
#define HIST_APPEND 2
#define HIST_STORE 3
#define HIST_NOTE 4
EXTERN struct timeval j_usrtime, j_systime;
#define notok2mul(max,val,c) (((val) != 0) && ((c) != 0) && \
(((max) / (c)) < (val)))
#define notok2add(max,val,c) ((val) > ((max) - (c)))
#define notoktomul(val,cnst) notok2mul(SIZE_MAX, (val), (cnst))
#define notoktoadd(val,cnst) notok2add(SIZE_MAX, (val), (cnst))
#define checkoktoadd(val,cnst) do { \
if (notoktoadd((val), (cnst))) \
internal_errorf(Tintovfl, (size_t)(val), \
'+', (size_t)(cnst)); \
} while ( 0)
void ainit(Area *);
void afreeall(Area *);
#define alloc(n,ap) aresize(NULL, (n), (ap))
#define alloc2(m,n,ap) aresize2(NULL, (m), (n), (ap))
void *aresize(void *, size_t, Area *);
void *aresize2(void *, size_t, size_t, Area *);
void afree(void *, Area *);
#define aresizeif(z,p,n,ap) (((p) == NULL) || ((z) < (n)) || \
(((z) & ~X_WASTE) > ((n) & ~X_WASTE)) ? \
aresize((p), (n), (ap)) : (p))
#ifndef MKSH_NO_CMDLINE_EDITING
int x_bind(const char * SMALLP(bool));
int x_bind_check(void);
int x_bind_list(void);
int x_bind_showall(void);
void x_init(void);
#ifdef DEBUG_LEAKS
void x_done(void);
#endif
int x_read(char *);
#endif
void x_mkraw(int, mksh_ttyst *, bool);
void x_initterm(const char *);
char *substitute(const char *, int);
char **eval(const char **, int);
char *evalstr(const char *cp, int);
char *evalonestr(const char *cp, int);
char *debunk(char *, const char *, size_t);
void expand(const char *, XPtrV *, int);
int glob_str(char *, XPtrV *, bool);
char *do_tilde(char *);
int execute(struct op * volatile, volatile int, volatile int * volatile);
int c_builtin(const char **);
struct tbl *get_builtin(const char *);
struct tbl *findfunc(const char *, uint32_t, bool);
int define(const char *, struct op *);
const char *builtin(const char *, int (*)(const char **));
struct tbl *findcom(const char *, int);
void flushcom(bool);
int search_access(const char *, int);
const char *search_path(const char *, const char *, int, int *);
void pr_menu(const char * const *);
void pr_list(struct columnise_opts *, char * const *);
int herein(struct ioword *, char **);
int evaluate(const char *, mksh_ari_t *, int, bool);
int v_evaluate(struct tbl *, const char *, volatile int, bool);
size_t utf_mbtowc(unsigned int *, const char *);
size_t utf_wctomb(char *, unsigned int);
int utf_widthadj(const char *, const char **);
size_t utf_mbswidth(const char *) MKSH_A_PURE;
const char *utf_skipcols(const char *, int, int *);
size_t utf_ptradj(const char *) MKSH_A_PURE;
#ifdef MIRBSD_BOOTFLOPPY
#define utf_wcwidth(i) wcwidth((wchar_t)(i))
#else
int utf_wcwidth(unsigned int) MKSH_A_PURE;
#endif
int ksh_access(const char *, int);
struct tbl *tempvar(const char *);
int c_hash(const char **);
int c_pwd(const char **);
int c_print(const char **);
#ifdef MKSH_PRINTF_BUILTIN
int c_printf(const char **);
#endif
int c_whence(const char **);
int c_command(const char **);
int c_typeset(const char **);
bool valid_alias_name(const char *);
int c_alias(const char **);
int c_unalias(const char **);
int c_let(const char **);
int c_jobs(const char **);
#ifndef MKSH_UNEMPLOYED
int c_fgbg(const char **);
#endif
int c_kill(const char **);
void getopts_reset(int);
int c_getopts(const char **);
#ifndef MKSH_NO_CMDLINE_EDITING
int c_bind(const char **);
#endif
int c_shift(const char **);
int c_umask(const char **);
int c_dot(const char **);
int c_wait(const char **);
int c_read(const char **);
int c_eval(const char **);
int c_trap(const char **);
int c_brkcont(const char **);
int c_exitreturn(const char **);
int c_set(const char **);
int c_unset(const char **);
int c_ulimit(const char **);
int c_times(const char **);
int timex(struct op *, int, volatile int *);
void timex_hook(struct op *, char ** volatile *);
int c_exec(const char **);
int c_test(const char **);
#if HAVE_MKNOD
int c_mknod(const char **);
#endif
int c_realpath(const char **);
int c_rename(const char **);
int c_cat(const char **);
int c_sleep(const char **);
void init_histvec(void);
void hist_init(Source *);
#if HAVE_PERSISTENT_HISTORY
void hist_finish(void);
#endif
void histsave(int *, const char *, int, bool);
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
bool histsync(void);
#endif
int c_fc(const char **);
void sethistsize(mksh_ari_t);
#if HAVE_PERSISTENT_HISTORY
void sethistfile(const char *);
#endif
#if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI
char **histpos(void) MKSH_A_PURE;
int histnum(int);
#endif
int findhist(int, const char *, bool, bool) MKSH_A_PURE;
char **hist_get_newest(bool);
void inittraps(void);
void alarm_init(void);
Trap *gettrap(const char *, bool, bool);
void trapsig(int);
void intrcheck(void);
int fatal_trap_check(void);
int trap_pending(void);
void runtraps(int intr);
void runtrap(Trap *, bool);
void cleartraps(void);
void restoresigs(void);
void settrap(Trap *, const char *);
bool block_pipe(void);
void restore_pipe(void);
int setsig(Trap *, sig_t, int);
void setexecsig(Trap *, int);
#if HAVE_FLOCK || HAVE_LOCK_FCNTL
void mksh_lockfd(int);
void mksh_unlkfd(int);
#endif
void j_init(void);
void j_exit(void);
#ifndef MKSH_UNEMPLOYED
void j_change(void);
#endif
int exchild(struct op *, int, volatile int *, int);
void startlast(void);
int waitlast(void);
int waitfor(const char *, int *);
int j_kill(const char *, int);
#ifndef MKSH_UNEMPLOYED
int j_resume(const char *, int);
#endif
#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
void j_suspend(void);
#endif
int j_jobs(const char *, int, int);
void j_notify(void);
pid_t j_async(void);
int j_stopped_running(void);
int yylex(int);
void yyskiputf8bom(void);
void yyerror(const char *, ...)
MKSH_A_NORETURN
MKSH_A_FORMAT(__printf__, 1, 2);
Source *pushs(int, Area *);
void set_prompt(int, Source *);
int pprompt(const char *, int);
int include(const char *, int, const char **, bool);
int command(const char *, int);
int shell(Source * volatile, volatile int);
void unwind(int) MKSH_A_NORETURN;
void newenv(int);
void quitenv(struct shf *);
void cleanup_parents_env(void);
void cleanup_proc_env(void);
void errorf(const char *, ...)
MKSH_A_NORETURN
MKSH_A_FORMAT(__printf__, 1, 2);
void errorfx(int, const char *, ...)
MKSH_A_NORETURN
MKSH_A_FORMAT(__printf__, 2, 3);
void warningf(bool, const char *, ...)
MKSH_A_FORMAT(__printf__, 2, 3);
void bi_errorf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
void maybe_errorf(int *, int, const char *, ...)
MKSH_A_FORMAT(__printf__, 3, 4);
#define errorfz() errorf(NULL)
#define errorfxz(rc) errorfx((rc), NULL)
#define bi_errorfz() bi_errorf(NULL)
void internal_errorf(const char *, ...)
MKSH_A_NORETURN
MKSH_A_FORMAT(__printf__, 1, 2);
void internal_warningf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
void error_prefix(bool);
void shellf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
void shprintf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
int can_seek(int);
void initio(void);
void recheck_ctype(void);
int ksh_dup2(int, int, bool);
short savefd(int);
void restfd(int, int);
void openpipe(int *);
void closepipe(int *);
int check_fd(const char *, int, const char **);
void coproc_init(void);
void coproc_read_close(int);
void coproc_readw_close(int);
void coproc_write_close(int);
int coproc_getfd(int, const char **);
void coproc_cleanup(int);
struct temp *maketemp(Area *, Temp_type, struct temp **);
void ktinit(Area *, struct table *, uint8_t);
struct tbl *ktscan(struct table *, const char *, uint32_t, struct tbl ***);
#define ktsearch(tp,s,h) ktscan((tp), (s), (h), NULL)
struct tbl *ktenter(struct table *, const char *, uint32_t);
#define ktdelete(p) do { p->flag = 0; } while ( 0)
void ktwalk(struct tstate *, struct table *);
struct tbl *ktnext(struct tstate *);
struct tbl **ktsort(struct table *);
#ifdef DF
void DF(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
#endif
size_t option(const char *) MKSH_A_PURE;
char *getoptions(void);
void change_flag(enum sh_flag, int, bool);
void change_xtrace(unsigned char, bool);
int parse_args(const char **, int, bool *);
int getn(const char *, int *);
int gmatchx(const char *, const char *, bool);
bool has_globbing(const char *) MKSH_A_PURE;
int ascstrcmp(const void *, const void *) MKSH_A_PURE;
int ascpstrcmp(const void *, const void *) MKSH_A_PURE;
void ksh_getopt_reset(Getopt *, int);
int ksh_getopt(const char **, Getopt *, const char *);
void print_value_quoted(struct shf *, const char *);
char *quote_value(const char *);
void print_columns(struct columnise_opts *, unsigned int,
void (*)(char *, size_t, unsigned int, const void *),
const void *, size_t, size_t);
void strip_nuls(char *, size_t)
MKSH_A_BOUNDED(__string__, 1, 2);
ssize_t blocking_read(int, char *, size_t)
MKSH_A_BOUNDED(__buffer__, 2, 3);
int reset_nonblock(int);
char *ksh_get_wd(void);
char *do_realpath(const char *);
void simplify_path(char *);
void set_current_wd(const char *);
int c_cd(const char **);
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
char *strdup_i(const char *, Area *);
char *strndup_i(const char *, size_t, Area *);
#endif
int unbksl(bool, int (*)(void), void (*)(int));
#ifdef __OS2__
void os2_init(int *, const char ***);
void setextlibpath(const char *, const char *);
int access_ex(int (*)(const char *, int), const char *, int);
int stat_ex(int (*)(const char *, struct stat *), const char *, struct stat *);
const char *real_exec_name(const char *);
#endif
struct shf *shf_open(const char *, int, int, int);
struct shf *shf_fdopen(int, int, struct shf *);
struct shf *shf_reopen(int, int, struct shf *);
struct shf *shf_sopen(char *, ssize_t, int, struct shf *);
int shf_close(struct shf *);
int shf_fdclose(struct shf *);
char *shf_sclose(struct shf *);
int shf_flush(struct shf *);
ssize_t shf_read(char *, ssize_t, struct shf *);
char *shf_getse(char *, ssize_t, struct shf *);
int shf_getchar(struct shf *s);
int shf_ungetc(int, struct shf *);
#ifdef MKSH_SHF_NO_INLINE
int shf_getc(struct shf *);
int shf_putc(int, struct shf *);
#else
#define shf_getc shf_getc_i
#define shf_putc shf_putc_i
#endif
int shf_putchar(int, struct shf *);
ssize_t shf_puts(const char *, struct shf *);
ssize_t shf_write(const char *, ssize_t, struct shf *);
ssize_t shf_fprintf(struct shf *, const char *, ...)
MKSH_A_FORMAT(__printf__, 2, 3);
ssize_t shf_snprintf(char *, ssize_t, const char *, ...)
MKSH_A_FORMAT(__printf__, 3, 4)
MKSH_A_BOUNDED(__string__, 1, 2);
char *shf_smprintf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2);
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
MKSH_A_FORMAT(__printf__, 2, 0);
void set_ifs(const char *);
void initkeywords(void);
struct op *compile(Source *, bool, bool);
bool parse_usec(const char *, struct timeval *);
char *yyrecursive(int);
void yyrecursive_pop(bool);
void fptreef(struct shf *, int, const char *, ...);
char *snptreef(char *, ssize_t, const char *, ...);
struct op *tcopy(struct op *, Area *);
char *wdcopy(const char *, Area *);
const char *wdscan(const char *, int);
#define WDS_TPUTS BIT(0)
char *wdstrip(const char *, int);
void tfree(struct op *, Area *);
void dumpchar(struct shf *, unsigned char);
void dumptree(struct shf *, struct op *);
void dumpwdvar(struct shf *, const char *);
void dumpioact(struct shf *shf, struct op *t);
void vistree(char *, size_t, struct op *)
MKSH_A_BOUNDED(__string__, 1, 2);
void fpFUNCTf(struct shf *, int, bool, const char *, struct op *);
void newblock(void);
void popblock(void);
void initvar(void);
struct block *varsearch(struct block *, struct tbl **, const char *, uint32_t);
struct tbl *global(const char *);
struct tbl *isglobal(const char *, bool);
struct tbl *local(const char *, bool);
char *str_val(struct tbl *);
int setstr(struct tbl *, const char *, int);
struct tbl *setint_v(struct tbl *, struct tbl *, bool);
void setint(struct tbl *, mksh_ari_t);
void setint_n(struct tbl *, mksh_ari_t, int);
struct tbl *typeset(const char *, uint32_t, uint32_t, int, int);
void unset(struct tbl *, int);
const char *skip_varname(const char *, bool) MKSH_A_PURE;
const char *skip_wdvarname(const char *, bool) MKSH_A_PURE;
int is_wdvarname(const char *, bool) MKSH_A_PURE;
int is_wdvarassign(const char *) MKSH_A_PURE;
struct tbl *arraysearch(struct tbl *, uint32_t);
char **makenv(void);
void change_winsz(void);
size_t array_ref_len(const char *) MKSH_A_PURE;
struct tbl *arraybase(const char*);
mksh_uari_t set_array(const char *, bool, const char **);
uint32_t hash(const void *) MKSH_A_PURE;
uint32_t chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
mksh_ari_t rndget(void);
void rndset(unsigned long);
void rndpush(const void *);
void record_match(const char *);
enum Test_op {
TO_NONOP = 0,
TO_STNZE, TO_STZER, TO_ISSET, TO_OPTION,
TO_FILAXST,
TO_FILEXST,
TO_FILREG, TO_FILBDEV, TO_FILCDEV, TO_FILSYM, TO_FILFIFO, TO_FILSOCK,
TO_FILCDF, TO_FILID, TO_FILGID, TO_FILSETG, TO_FILSTCK, TO_FILUID,
TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX,
TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT,
TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT,
TO_NONNULL
};
typedef enum Test_op Test_op;
enum Test_meta {
TM_OR,
TM_AND,
TM_NOT,
TM_OPAREN,
TM_CPAREN,
TM_UNOP,
TM_BINOP,
TM_END
};
typedef enum Test_meta Test_meta;
struct t_op {
const char op_text[4];
Test_op op_num;
};
extern const struct t_op u_ops[];
extern const struct t_op b_ops[];
#define Tda (u_ops[0].op_text)
#define Tdn (u_ops[12].op_text)
#define Tdo (u_ops[14].op_text)
#define Tdr (u_ops[16].op_text)
#define Tdu (u_ops[20].op_text)
#define Tdx (u_ops[23].op_text)
#define Tu (Tdu + 1)
#define TEF_ERROR BIT(0)
#define TEF_DBRACKET BIT(1)
typedef struct test_env {
union {
const char **wp;
XPtrV *av;
} pos;
const char **wp_end;
Test_op (*isa)(struct test_env *, Test_meta);
const char *(*getopnd) (struct test_env *, Test_op, bool);
int (*eval)(struct test_env *, Test_op, const char *, const char *, bool);
void (*error)(struct test_env *, int, const char *);
int flags;
} Test_env;
extern const char * const dbtest_tokens[];
Test_op test_isop(Test_meta, const char *) MKSH_A_PURE;
int test_eval(Test_env *, Test_op, const char *, const char *, bool);
int test_parse(Test_env *);
EXTERN int tty_fd E_INIT(-1);
EXTERN bool tty_devtty;
EXTERN mksh_ttyst tty_state;
EXTERN bool tty_hasstate;
extern int tty_init_fd(void);
#ifdef __OS2__
#define binopen2(path,flags) __extension__({ \
int binopen2_fd = open((path), (flags) | O_BINARY); \
if (binopen2_fd >= 0) \
setmode(binopen2_fd, O_BINARY); \
(binopen2_fd); \
})
#define binopen3(path,flags,mode) __extension__({ \
int binopen3_fd = open((path), (flags) | O_BINARY, (mode)); \
if (binopen3_fd >= 0) \
setmode(binopen3_fd, O_BINARY); \
(binopen3_fd); \
})
#else
#define binopen2(path,flags) open((path), (flags) | O_BINARY)
#define binopen3(path,flags,mode) open((path), (flags) | O_BINARY, (mode))
#endif
#ifdef MKSH_DOSPATH
#define mksh_drvltr(s) __extension__({ \
const char *mksh_drvltr_s = (s); \
(ctype(mksh_drvltr_s[0], C_ALPHA) && mksh_drvltr_s[1] == ':'); \
})
#define mksh_abspath(s) __extension__({ \
const char *mksh_abspath_s = (s); \
(mksh_cdirsep(mksh_abspath_s[0]) || \
(mksh_drvltr(mksh_abspath_s) && \
mksh_cdirsep(mksh_abspath_s[2]))); \
})
#define mksh_cdirsep(c) __extension__({ \
char mksh_cdirsep_c = (c); \
(mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\'); \
})
#define mksh_sdirsep(s) strpbrk((s), "/\\")
#define mksh_vdirsep(s) __extension__({ \
const char *mksh_vdirsep_s = (s); \
(((mksh_drvltr(mksh_vdirsep_s) && \
!mksh_cdirsep(mksh_vdirsep_s[2])) ? (!0) : \
(mksh_sdirsep(mksh_vdirsep_s) != NULL)) && \
(strcmp(mksh_vdirsep_s, T_builtin) != 0)); \
})
int getdrvwd(char **, unsigned int);
#else
#define mksh_abspath(s) (ord((s)[0]) == ORD('/'))
#define mksh_cdirsep(c) (ord(c) == ORD('/'))
#define mksh_sdirsep(s) strchr((s), '/')
#define mksh_vdirsep(s) vstrchr((s), '/')
#endif
#ifdef EXTERN_DEFINED
# undef EXTERN_DEFINED
# undef EXTERN
#endif
#undef E_INIT
#endif