1 /* $OpenBSD: sh.h,v 1.30 2010/01/04 18:07:11 deraadt Exp $ */ 2 /* $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */ 3 /* $OpenBSD: table.h,v 1.7 2005/12/11 20:31:21 otto Exp $ */ 4 /* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */ 5 /* $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $ */ 6 /* $OpenBSD: lex.h,v 1.11 2006/05/29 18:22:24 otto Exp $ */ 7 /* $OpenBSD: proto.h,v 1.33 2010/05/19 17:36:08 jasper Exp $ */ 8 /* $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 /*- 12 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 13 * Thorsten Glaser <tg (at) mirbsd.org> 14 * 15 * Provided that these terms and disclaimer and all copyright notices 16 * are retained or reproduced in an accompanying document, permission 17 * is granted to deal in this work without restriction, including un- 18 * limited rights to use, publicly perform, distribute, sell, modify, 19 * merge, give away, or sublicence. 20 * 21 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 22 * the utmost extent permitted by applicable law, neither express nor 23 * implied; without malicious intent or gross negligence. In no event 24 * may a licensor, author or contributor be held liable for indirect, 25 * direct, other damage, loss, or other issues arising in any way out 26 * of dealing in the work, even if advised of the possibility of such 27 * damage or existence of a defect, except proven that it results out 28 * of said person's immediate fault when using the work as intended. 29 */ 30 31 #ifdef __dietlibc__ 32 /* XXX imake style */ 33 #define _BSD_SOURCE /* live, BSD, live! */ 34 #endif 35 36 #if HAVE_SYS_PARAM_H 37 #include <sys/param.h> 38 #endif 39 #include <sys/types.h> 40 #include <sys/time.h> 41 #include <sys/ioctl.h> 42 #if HAVE_SYS_SYSMACROS_H 43 #include <sys/sysmacros.h> 44 #endif 45 #if HAVE_SYS_MKDEV_H 46 #include <sys/mkdev.h> 47 #endif 48 #if HAVE_SYS_MMAN_H 49 #include <sys/mman.h> 50 #endif 51 #include <sys/resource.h> 52 #include <sys/stat.h> 53 #include <sys/wait.h> 54 #include <dirent.h> 55 #include <errno.h> 56 #include <fcntl.h> 57 #if HAVE_LIBGEN_H 58 #include <libgen.h> 59 #endif 60 #if HAVE_LIBUTIL_H 61 #include <libutil.h> 62 #endif 63 #include <limits.h> 64 #if HAVE_PATHS_H 65 #include <paths.h> 66 #endif 67 #include <pwd.h> 68 #include <setjmp.h> 69 #include <signal.h> 70 #include <stdarg.h> 71 #if HAVE_STDBOOL_H 72 #include <stdbool.h> 73 #endif 74 #include <stddef.h> 75 #if HAVE_STDINT_H 76 #include <stdint.h> 77 #endif 78 #include <stdio.h> 79 #include <stdlib.h> 80 #include <string.h> 81 #if HAVE_STRINGS_H 82 #include <strings.h> 83 #endif 84 #include <termios.h> 85 #include <time.h> 86 #if HAVE_ULIMIT_H 87 #include <ulimit.h> 88 #endif 89 #include <unistd.h> 90 #if HAVE_VALUES_H 91 #include <values.h> 92 #endif 93 94 #undef __attribute__ 95 #if HAVE_ATTRIBUTE_BOUNDED 96 #define MKSH_A_BOUNDED(x,y,z) __attribute__((bounded (x, y, z))) 97 #else 98 #define MKSH_A_BOUNDED(x,y,z) /* nothing */ 99 #endif 100 #if HAVE_ATTRIBUTE_FORMAT 101 #define MKSH_A_FORMAT(x,y,z) __attribute__((format (x, y, z))) 102 #else 103 #define MKSH_A_FORMAT(x,y,z) /* nothing */ 104 #endif 105 #if HAVE_ATTRIBUTE_NONNULL 106 #define MKSH_A_NONNULL(a) __attribute__(a) 107 #else 108 #define MKSH_A_NONNULL(a) /* nothing */ 109 #endif 110 #if HAVE_ATTRIBUTE_NORETURN 111 #define MKSH_A_NORETURN __attribute__((noreturn)) 112 #else 113 #define MKSH_A_NORETURN /* nothing */ 114 #endif 115 #if HAVE_ATTRIBUTE_UNUSED 116 #define MKSH_A_UNUSED __attribute__((unused)) 117 #else 118 #define MKSH_A_UNUSED /* nothing */ 119 #endif 120 #if HAVE_ATTRIBUTE_USED 121 #define MKSH_A_USED __attribute__((used)) 122 #else 123 #define MKSH_A_USED /* nothing */ 124 #endif 125 126 #if defined(MirBSD) && (MirBSD >= 0x09A1) && \ 127 defined(__ELF__) && defined(__GNUC__) && \ 128 !defined(__llvm__) && !defined(__NWCC__) 129 /* 130 * We got usable __IDSTRING __COPYRIGHT __RCSID __SCCSID macros 131 * which work for all cases; no need to redefine them using the 132 * "portable" macros from below when we might have the "better" 133 * gcc+ELF specific macros or other system dependent ones. 134 */ 135 #else 136 #undef __IDSTRING 137 #undef __IDSTRING_CONCAT 138 #undef __IDSTRING_EXPAND 139 #undef __COPYRIGHT 140 #undef __RCSID 141 #undef __SCCSID 142 #define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p 143 #define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p) 144 #define __IDSTRING(prefix, string) \ 145 static const char __IDSTRING_EXPAND(__LINE__,prefix) [] \ 146 MKSH_A_USED = "@(""#)" #prefix ": " string 147 #define __COPYRIGHT(x) __IDSTRING(copyright,x) 148 #define __RCSID(x) __IDSTRING(rcsid,x) 149 #define __SCCSID(x) __IDSTRING(sccsid,x) 150 #endif 151 152 #ifdef EXTERN 153 __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.405 2010/08/24 15:19:54 tg Exp $"); 154 #endif 155 #define MKSH_VERSION "R39 2010/08/24" 156 157 #ifndef MKSH_INCLUDES_ONLY 158 159 /* extra types */ 160 161 #if !HAVE_GETRUSAGE 162 #undef rusage 163 #undef RUSAGE_SELF 164 #undef RUSAGE_CHILDREN 165 #define rusage mksh_rusage 166 #define RUSAGE_SELF 0 167 #define RUSAGE_CHILDREN -1 168 169 struct rusage { 170 struct timeval ru_utime; 171 struct timeval ru_stime; 172 }; 173 #endif 174 175 #if !HAVE_RLIM_T 176 typedef long rlim_t; 177 #endif 178 179 #if !HAVE_SIG_T 180 #undef sig_t 181 typedef void (*sig_t)(int); 182 #endif 183 184 #if !HAVE_STDBOOL_H 185 /* kludge, but enough for mksh */ 186 typedef int bool; 187 #define false 0 188 #define true 1 189 #endif 190 191 #if !HAVE_CAN_INTTYPES 192 #if !HAVE_CAN_UCBINTS 193 typedef signed int int32_t; 194 typedef unsigned int uint32_t; 195 #else 196 typedef u_int32_t uint32_t; 197 #endif 198 #endif 199 200 #if !HAVE_CAN_INT8TYPE 201 #if !HAVE_CAN_UCBINT8 202 typedef unsigned char uint8_t; 203 #else 204 typedef u_int8_t uint8_t; 205 #endif 206 #endif 207 208 /* extra macros */ 209 210 #ifndef timerclear 211 #define timerclear(tvp) \ 212 do { \ 213 (tvp)->tv_sec = (tvp)->tv_usec = 0; \ 214 } while (/* CONSTCOND */ 0) 215 #endif 216 #ifndef timeradd 217 #define timeradd(tvp, uvp, vvp) \ 218 do { \ 219 (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ 220 (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ 221 if ((vvp)->tv_usec >= 1000000) { \ 222 (vvp)->tv_sec++; \ 223 (vvp)->tv_usec -= 1000000; \ 224 } \ 225 } while (/* CONSTCOND */ 0) 226 #endif 227 #ifndef timersub 228 #define timersub(tvp, uvp, vvp) \ 229 do { \ 230 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 231 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ 232 if ((vvp)->tv_usec < 0) { \ 233 (vvp)->tv_sec--; \ 234 (vvp)->tv_usec += 1000000; \ 235 } \ 236 } while (/* CONSTCOND */ 0) 237 #endif 238 239 #define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9')) 240 #define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z')) 241 #define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z')) 242 #define ksh_tolower(c) (((c) >= 'A') && ((c) <= 'Z') ? (c) - 'A' + 'a' : (c)) 243 #define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (c) - 'a' + 'A' : (c)) 244 #define ksh_isdash(s) (((s) != NULL) && ((s)[0] == '-') && ((s)[1] == '\0')) 245 #define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20)) 246 247 #ifdef NO_PATH_MAX 248 #undef PATH_MAX 249 #else 250 #ifndef PATH_MAX 251 #define PATH_MAX 1024 252 #endif 253 #endif 254 #ifndef SIZE_MAX 255 #ifdef SIZE_T_MAX 256 #define SIZE_MAX SIZE_T_MAX 257 #else 258 #define SIZE_MAX ((size_t)-1) 259 #endif 260 #endif 261 #ifndef S_ISLNK 262 #define S_ISLNK(m) ((m & 0170000) == 0120000) 263 #endif 264 #ifndef S_ISSOCK 265 #define S_ISSOCK(m) ((m & 0170000) == 0140000) 266 #endif 267 #ifndef DEFFILEMODE 268 #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 269 #endif 270 271 #if !defined(MAP_FAILED) 272 /* XXX imake style */ 273 # if defined(__linux) 274 #define MAP_FAILED ((void *)-1) 275 # elif defined(__bsdi__) || defined(__osf__) || defined(__ultrix) 276 #define MAP_FAILED ((caddr_t)-1) 277 # endif 278 #endif 279 280 #ifndef NSIG 281 #if defined(_NSIG) 282 #define NSIG _NSIG 283 #elif defined(SIGMAX) 284 #define NSIG (SIGMAX+1) 285 #endif 286 #endif 287 288 #undef BAD /* AIX defines that somewhere */ 289 290 /* OS-dependent additions (functions, variables, by OS) */ 291 292 #if !HAVE_FLOCK_DECL 293 extern int flock(int, int); 294 #endif 295 296 #if !HAVE_GETRUSAGE 297 extern int getrusage(int, struct rusage *); 298 #endif 299 300 #if !HAVE_REVOKE_DECL 301 extern int revoke(const char *); 302 #endif 303 304 #if !HAVE_SETMODE 305 mode_t getmode(const void *, mode_t); 306 void *setmode(const char *); 307 #endif 308 309 #ifdef __ultrix 310 /* XXX imake style */ 311 int strcasecmp(const char *, const char *); 312 #endif 313 314 #if !HAVE_STRCASESTR 315 const char *stristr(const char *, const char *); 316 #endif 317 318 #if !HAVE_STRLCPY 319 size_t strlcpy(char *, const char *, size_t); 320 #endif 321 322 #if !HAVE_SYS_SIGLIST_DECL 323 extern const char *const sys_siglist[]; 324 #endif 325 326 #ifdef __INTERIX 327 /* XXX imake style */ 328 #define makedev mkdev 329 extern int __cdecl seteuid(uid_t); 330 extern int __cdecl setegid(gid_t); 331 #endif 332 333 /* remove redundances */ 334 335 #if defined(MirBSD) && (MirBSD >= 0x08A8) 336 #define MKSH_mirbsd_wcwidth 337 #define utf_wcwidth(i) wcwidth((__WCHAR_TYPE__)i) 338 extern int wcwidth(__WCHAR_TYPE__); 339 #endif 340 341 342 /* some useful #defines */ 343 #ifdef EXTERN 344 # define I__(i) = i 345 #else 346 # define I__(i) 347 # define EXTERN extern 348 # define EXTERN_DEFINED 349 #endif 350 351 #define NELEM(a) (sizeof(a) / sizeof((a)[0])) 352 #define BIT(i) (1 << (i)) /* define bit in flag */ 353 354 /* Table flag type - needs > 16 and < 32 bits */ 355 typedef int32_t Tflag; 356 357 /* arithmetics types */ 358 typedef int32_t mksh_ari_t; 359 typedef uint32_t mksh_uari_t; 360 361 /* these shall be smaller than 100 */ 362 #ifdef MKSH_CONSERVATIVE_FDS 363 #define NUFILE 32 /* Number of user-accessible files */ 364 #define FDBASE 10 /* First file usable by Shell */ 365 #else 366 #define NUFILE 56 /* Number of user-accessible files */ 367 #define FDBASE 24 /* First file usable by Shell */ 368 #endif 369 370 /* Make MAGIC a char that might be printed to make bugs more obvious, but 371 * not a char that is used often. Also, can't use the high bit as it causes 372 * portability problems (calling strchr(x, 0x80|'x') is error prone). 373 */ 374 #define MAGIC (7) /* prefix for *?[!{,} during expand */ 375 #define ISMAGIC(c) ((unsigned char)(c) == MAGIC) 376 #define NOT '!' /* might use ^ (ie, [!...] vs [^..]) */ 377 378 #define LINE 4096 /* input line size */ 379 380 EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ 381 EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION); 382 #define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16) 383 384 EXTERN const char digits_uc[] I__("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 385 EXTERN const char digits_lc[] I__("0123456789abcdefghijklmnopqrstuvwxyz"); 386 387 /* 388 * Evil hack for const correctness due to API brokenness 389 */ 390 union mksh_cchack { 391 char *rw; 392 const char *ro; 393 }; 394 union mksh_ccphack { 395 char **rw; 396 const char **ro; 397 }; 398 399 /* for const debugging */ 400 #if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \ 401 !defined(__INTEL_COMPILER) && !defined(__SUNPRO_C) 402 char *ucstrchr(char *, int); 403 char *ucstrstr(char *, const char *); 404 #undef strchr 405 #define strchr ucstrchr 406 #define strstr ucstrstr 407 #define cstrchr(s,c) ({ \ 408 union mksh_cchack in, out; \ 409 \ 410 in.ro = (s); \ 411 out.rw = ucstrchr(in.rw, (c)); \ 412 (out.ro); \ 413 }) 414 #define cstrstr(b,l) ({ \ 415 union mksh_cchack in, out; \ 416 \ 417 in.ro = (b); \ 418 out.rw = ucstrstr(in.rw, (l)); \ 419 (out.ro); \ 420 }) 421 #define vstrchr(s,c) (cstrchr((s), (c)) != NULL) 422 #define vstrstr(b,l) (cstrstr((b), (l)) != NULL) 423 #define mkssert(e) ((e) ? (void)0 : exit(255)) 424 #else /* !DEBUG, !gcc */ 425 #define cstrchr(s,c) ((const char *)strchr((s), (c))) 426 #define cstrstr(s,c) ((const char *)strstr((s), (c))) 427 #define vstrchr(s,c) (strchr((s), (c)) != NULL) 428 #define vstrstr(b,l) (strstr((b), (l)) != NULL) 429 #define mkssert(e) ((void)0) 430 #endif 431 432 /* use this ipv strchr(s, 0) but no side effects in s! */ 433 #define strnul(s) ((s) + strlen(s)) 434 435 #define utf_ptradjx(src, dst) do { \ 436 (dst) = (src) + utf_ptradj(src); \ 437 } while (/* CONSTCOND */ 0) 438 439 #ifdef MKSH_SMALL 440 #define strdupx(d, s, ap) do { \ 441 (d) = strdup_((s), (ap)); \ 442 } while (/* CONSTCOND */ 0) 443 #define strndupx(d, s, n, ap) do { \ 444 (d) = strndup_((s), (n), (ap)); \ 445 } while (/* CONSTCOND */ 0) 446 #else 447 /* be careful to evaluate arguments only once! */ 448 #define strdupx(d, s, ap) do { \ 449 const char *strdup_src = (s); \ 450 char *strdup_dst = NULL; \ 451 \ 452 if (strdup_src != NULL) { \ 453 size_t strdup_len = strlen(strdup_src) + 1; \ 454 strdup_dst = alloc(strdup_len, (ap)); \ 455 memcpy(strdup_dst, strdup_src, strdup_len); \ 456 } \ 457 (d) = strdup_dst; \ 458 } while (/* CONSTCOND */ 0) 459 #define strndupx(d, s, n, ap) do { \ 460 const char *strdup_src = (s); \ 461 char *strdup_dst = NULL; \ 462 \ 463 if (strdup_src != NULL) { \ 464 size_t strndup_len = (n); \ 465 strdup_dst = alloc(strndup_len + 1, (ap)); \ 466 memcpy(strdup_dst, strdup_src, strndup_len); \ 467 strdup_dst[strndup_len] = '\0'; \ 468 } \ 469 (d) = strdup_dst; \ 470 } while (/* CONSTCOND */ 0) 471 #endif 472 473 #if HAVE_STRCASESTR 474 #define stristr(b,l) ((const char *)strcasestr((b), (l))) 475 #endif 476 477 #ifdef MKSH_SMALL 478 #ifndef MKSH_CONSERVATIVE_FDS 479 #define MKSH_CONSERVATIVE_FDS /* defined */ 480 #endif 481 #ifndef MKSH_NOPWNAM 482 #define MKSH_NOPWNAM /* defined */ 483 #endif 484 #ifndef MKSH_S_NOVI 485 #define MKSH_S_NOVI 1 486 #endif 487 #endif 488 489 #ifndef MKSH_S_NOVI 490 #define MKSH_S_NOVI 0 491 #endif 492 493 /* 494 * simple grouping allocator 495 */ 496 497 /* 1. internal structure */ 498 struct lalloc { 499 struct lalloc *next; 500 }; 501 502 /* 2. sizes */ 503 #define ALLOC_ITEM struct lalloc 504 #define ALLOC_SIZE (sizeof(ALLOC_ITEM)) 505 506 /* 3. group structure (only the same for lalloc.c) */ 507 typedef struct lalloc Area; 508 509 510 EXTERN Area aperm; /* permanent object space */ 511 #define APERM &aperm 512 #define ATEMP &e->area 513 514 /* 515 * flags (the order of these enums MUST match the order in misc.c(options[])) 516 */ 517 enum sh_flag { 518 #define SHFLAGS_ENUMS 519 #include "sh_flags.h" 520 FNFLAGS /* (place holder: how many flags are there) */ 521 }; 522 523 #define Flag(f) (kshstate_v.shell_flags_[(int)(f)]) 524 #define UTFMODE Flag(FUNICODE) 525 526 /* 527 * parsing & execution environment 528 */ 529 extern struct env { 530 ALLOC_ITEM __alloc_i; /* internal, do not touch */ 531 Area area; /* temporary allocation area */ 532 struct env *oenv; /* link to previous environment */ 533 struct block *loc; /* local variables and functions */ 534 short *savefd; /* original redirected fds */ 535 struct temp *temps; /* temp files */ 536 sigjmp_buf jbuf; /* long jump back to env creator */ 537 short type; /* environment type - see below */ 538 short flags; /* EF_* */ 539 } *e; 540 541 /* struct env.type values */ 542 #define E_NONE 0 /* dummy environment */ 543 #define E_PARSE 1 /* parsing command # */ 544 #define E_FUNC 2 /* executing function # */ 545 #define E_INCL 3 /* including a file via . # */ 546 #define E_EXEC 4 /* executing command tree */ 547 #define E_LOOP 5 /* executing for/while # */ 548 #define E_ERRH 6 /* general error handler # */ 549 /* # indicates env has valid jbuf (see unwind()) */ 550 551 /* struct env.flag values */ 552 #define EF_FUNC_PARSE BIT(0) /* function being parsed */ 553 #define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */ 554 #define EF_FAKE_SIGDIE BIT(2) /* hack to get info from unwind to quitenv */ 555 556 /* Do breaks/continues stop at env type e? */ 557 #define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE \ 558 || (t) == E_FUNC || (t) == E_INCL) 559 /* Do returns stop at env type e? */ 560 #define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL) 561 562 /* values for siglongjmp(e->jbuf, 0) */ 563 #define LRETURN 1 /* return statement */ 564 #define LEXIT 2 /* exit statement */ 565 #define LERROR 3 /* errorf() called */ 566 #define LLEAVE 4 /* untrappable exit/error */ 567 #define LINTR 5 /* ^C noticed */ 568 #define LBREAK 6 /* break statement */ 569 #define LCONTIN 7 /* continue statement */ 570 #define LSHELL 8 /* return to interactive shell() */ 571 #define LAEXPR 9 /* error in arithmetic expression */ 572 573 /* 574 * some kind of global shell state, for change_random() mostly 575 */ 576 577 EXTERN struct mksh_kshstate_v { 578 /* for change_random */ 579 struct timeval cr_tv; /* timestamp */ 580 const void *cr_dp; /* argument address */ 581 size_t cr_dsz; /* argument length */ 582 uint32_t lcg_state_; /* previous LCG state */ 583 /* global state */ 584 pid_t procpid_; /* PID of executing process */ 585 int exstat_; /* exit status */ 586 int subst_exstat_; /* exit status of last $(..)/`..` */ 587 struct env env_; /* top-level parsing & execution env. */ 588 uint8_t shell_flags_[FNFLAGS]; 589 } kshstate_v; 590 EXTERN struct mksh_kshstate_f { 591 const char *kshname_; /* $0 */ 592 pid_t kshpid_; /* $$, shell PID */ 593 pid_t kshpgrp_; /* process group of shell */ 594 uid_t ksheuid_; /* effective UID of shell */ 595 pid_t kshppid_; /* PID of parent of shell */ 596 uint32_t h; /* some kind of hash */ 597 } kshstate_f; 598 #define kshname kshstate_f.kshname_ 599 #define kshpid kshstate_f.kshpid_ 600 #define procpid kshstate_v.procpid_ 601 #define kshpgrp kshstate_f.kshpgrp_ 602 #define ksheuid kshstate_f.ksheuid_ 603 #define kshppid kshstate_f.kshppid_ 604 #define exstat kshstate_v.exstat_ 605 #define subst_exstat kshstate_v.subst_exstat_ 606 607 /* evil hack: return hash(kshstate_f concat (kshstate_f'.h:=hash(arg))) */ 608 uint32_t evilhash(const char *); 609 610 611 /* option processing */ 612 #define OF_CMDLINE 0x01 /* command line */ 613 #define OF_SET 0x02 /* set builtin */ 614 #define OF_SPECIAL 0x04 /* a special variable changing */ 615 #define OF_INTERNAL 0x08 /* set internally by shell */ 616 #define OF_FIRSTTIME 0x10 /* as early as possible, once */ 617 #define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL) 618 619 struct shoption { 620 const char *name; /* long name of option */ 621 char c; /* character flag (if any) */ 622 unsigned char flags; /* OF_* */ 623 }; 624 extern const struct shoption options[]; 625 626 /* null value for variable; comparision pointer for unset */ 627 EXTERN char null[] I__(""); 628 /* helpers for string pooling */ 629 #define T_synerr "syntax error" 630 EXTERN const char r_fc_e_[] I__("r=fc -e -"); 631 #define fc_e_ (r_fc_e_ + 2) /* "fc -e -" */ 632 #define fc_e_n 7 /* strlen(fc_e_) */ 633 EXTERN const char T_local_typeset[] I__("local=typeset"); 634 #define T__typeset (T_local_typeset + 5) /* "=typeset" */ 635 #define T_typeset (T_local_typeset + 6) /* "typeset" */ 636 637 enum temp_type { 638 TT_HEREDOC_EXP, /* expanded heredoc */ 639 TT_HIST_EDIT /* temp file used for history editing (fc -e) */ 640 }; 641 typedef enum temp_type Temp_type; 642 /* temp/heredoc files. The file is removed when the struct is freed. */ 643 struct temp { 644 struct temp *next; 645 struct shf *shf; 646 char *name; 647 int pid; /* pid of process parsed here-doc */ 648 Temp_type type; 649 }; 650 651 /* 652 * stdio and our IO routines 653 */ 654 655 #define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ 656 #define shl_stdout (&shf_iob[1]) 657 #define shl_out (&shf_iob[2]) 658 EXTERN int shl_stdout_ok; 659 660 /* 661 * trap handlers 662 */ 663 typedef struct trap { 664 const char *name; /* short name */ 665 const char *mess; /* descriptive name */ 666 char *trap; /* trap command */ 667 sig_t cursig; /* current handler (valid if TF_ORIG_* set) */ 668 sig_t shtrap; /* shell signal handler */ 669 int signal; /* signal number */ 670 int flags; /* TF_* */ 671 volatile sig_atomic_t set; /* trap pending */ 672 } Trap; 673 674 /* values for Trap.flags */ 675 #define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */ 676 #define TF_USER_SET BIT(1) /* user has (tried to) set trap */ 677 #define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */ 678 #define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */ 679 #define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */ 680 #define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */ 681 #define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */ 682 #define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */ 683 #define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */ 684 #define TF_FATAL BIT(9) /* causes termination if not trapped */ 685 686 /* values for setsig()/setexecsig() flags argument */ 687 #define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */ 688 #define SS_RESTORE_CURR 0 /* leave current handler in place */ 689 #define SS_RESTORE_ORIG 1 /* restore original handler */ 690 #define SS_RESTORE_DFL 2 /* restore to SIG_DFL */ 691 #define SS_RESTORE_IGN 3 /* restore to SIG_IGN */ 692 #define SS_FORCE BIT(3) /* set signal even if original signal ignored */ 693 #define SS_USER BIT(4) /* user is doing the set (ie, trap command) */ 694 #define SS_SHTRAP BIT(5) /* trap for internal use (ALRM, CHLD, WINCH) */ 695 696 #define SIGEXIT_ 0 /* for trap EXIT */ 697 #define SIGERR_ NSIG /* for trap ERR */ 698 699 EXTERN volatile sig_atomic_t trap; /* traps pending? */ 700 EXTERN volatile sig_atomic_t intrsig; /* pending trap interrupts command */ 701 EXTERN volatile sig_atomic_t fatal_trap;/* received a fatal signal */ 702 extern Trap sigtraps[NSIG+1]; 703 704 /* got_winch = 1 when we need to re-adjust the window size */ 705 #ifdef SIGWINCH 706 EXTERN volatile sig_atomic_t got_winch I__(1); 707 #else 708 #define got_winch true 709 #endif 710 711 /* 712 * TMOUT support 713 */ 714 /* values for ksh_tmout_state */ 715 enum tmout_enum { 716 TMOUT_EXECUTING = 0, /* executing commands */ 717 TMOUT_READING, /* waiting for input */ 718 TMOUT_LEAVING /* have timed out */ 719 }; 720 EXTERN unsigned int ksh_tmout; 721 EXTERN enum tmout_enum ksh_tmout_state I__(TMOUT_EXECUTING); 722 723 /* For "You have stopped jobs" message */ 724 EXTERN int really_exit; 725 726 /* 727 * fast character classes 728 */ 729 #define C_ALPHA BIT(0) /* a-z_A-Z */ 730 #define C_DIGIT BIT(1) /* 0-9 */ 731 #define C_LEX1 BIT(2) /* \t \n\0|&;<>() */ 732 #define C_VAR1 BIT(3) /* *@#!$-? */ 733 #define C_IFSWS BIT(4) /* \t \n (IFS white space) */ 734 #define C_SUBOP1 BIT(5) /* "=-+?" */ 735 #define C_QUOTE BIT(6) /* \t\n "#$&'()*;<=>?[\]`| (needing quoting) */ 736 #define C_IFS BIT(7) /* $IFS */ 737 #define C_SUBOP2 BIT(8) /* "#%" (magic, see below) */ 738 739 extern unsigned char chtypes[]; 740 741 #define ctype(c, t) !!( ((t) == C_SUBOP2) ? \ 742 (((c) == '#' || (c) == '%') ? 1 : 0) : \ 743 (chtypes[(unsigned char)(c)]&(t)) ) 744 #define ksh_isalphx(c) ctype((c), C_ALPHA) 745 #define ksh_isalnux(c) ctype((c), C_ALPHA | C_DIGIT) 746 747 EXTERN int ifs0 I__(' '); /* for "$*" */ 748 749 /* Argument parsing for built-in commands and getopts command */ 750 751 /* Values for Getopt.flags */ 752 #define GF_ERROR BIT(0) /* call errorf() if there is an error */ 753 #define GF_PLUSOPT BIT(1) /* allow +c as an option */ 754 #define GF_NONAME BIT(2) /* don't print argv[0] in errors */ 755 756 /* Values for Getopt.info */ 757 #define GI_MINUS BIT(0) /* an option started with -... */ 758 #define GI_PLUS BIT(1) /* an option started with +... */ 759 #define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */ 760 761 typedef struct { 762 const char *optarg; 763 int optind; 764 int uoptind;/* what user sees in $OPTIND */ 765 int flags; /* see GF_* */ 766 int info; /* see GI_* */ 767 unsigned int p; /* 0 or index into argv[optind - 1] */ 768 char buf[2]; /* for bad option OPTARG value */ 769 } Getopt; 770 771 EXTERN Getopt builtin_opt; /* for shell builtin commands */ 772 EXTERN Getopt user_opt; /* parsing state for getopts builtin command */ 773 774 /* This for co-processes */ 775 776 typedef int32_t Coproc_id; /* something that won't (realisticly) wrap */ 777 struct coproc { 778 void *job; /* 0 or job of co-process using input pipe */ 779 int read; /* pipe from co-process's stdout */ 780 int readw; /* other side of read (saved temporarily) */ 781 int write; /* pipe to co-process's stdin */ 782 int njobs; /* number of live jobs using output pipe */ 783 Coproc_id id; /* id of current output pipe */ 784 }; 785 EXTERN struct coproc coproc; 786 787 /* Used in jobs.c and by coprocess stuff in exec.c */ 788 EXTERN sigset_t sm_default, sm_sigchld; 789 790 /* name of called builtin function (used by error functions) */ 791 EXTERN const char *builtin_argv0; 792 EXTERN Tflag builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ 793 794 /* current working directory, and size of memory allocated for same */ 795 EXTERN char *current_wd; 796 EXTERN size_t current_wd_size; 797 798 /* Minimum required space to work with on a line - if the prompt leaves less 799 * space than this on a line, the prompt is truncated. 800 */ 801 #define MIN_EDIT_SPACE 7 802 /* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line 803 */ 804 #define MIN_COLS (2 + MIN_EDIT_SPACE + 3) 805 #define MIN_LINS 3 806 EXTERN mksh_ari_t x_cols I__(80); /* tty columns */ 807 EXTERN mksh_ari_t x_lins I__(-1); /* tty lines */ 808 809 /* These to avoid bracket matching problems */ 810 #define OPAREN '(' 811 #define CPAREN ')' 812 #define OBRACK '[' 813 #define CBRACK ']' 814 #define OBRACE '{' 815 #define CBRACE '}' 816 817 /* Determine the location of the system (common) profile */ 818 #define KSH_SYSTEM_PROFILE "/etc/profile" 819 820 /* Used by v_evaluate() and setstr() to control action when error occurs */ 821 #define KSH_UNWIND_ERROR 0 /* unwind the stack (longjmp) */ 822 #define KSH_RETURN_ERROR 1 /* return 1/0 for success/failure */ 823 824 /* 825 * Shell file I/O routines 826 */ 827 828 #define SHF_BSIZE 512 829 830 #define shf_fileno(shf) ((shf)->fd) 831 #define shf_setfileno(shf,nfd) ((shf)->fd = (nfd)) 832 #ifdef MKSH_SMALL 833 int shf_getc(struct shf *); 834 int shf_putc(int, struct shf *); 835 #else 836 #define shf_getc(shf) ((shf)->rnleft > 0 ? \ 837 (shf)->rnleft--, *(shf)->rp++ : \ 838 shf_getchar(shf)) 839 #define shf_putc(c, shf) ((shf)->wnleft == 0 ? \ 840 shf_putchar((c), (shf)) : \ 841 ((shf)->wnleft--, *(shf)->wp++ = (c))) 842 #endif 843 #define shf_eof(shf) ((shf)->flags & SHF_EOF) 844 #define shf_error(shf) ((shf)->flags & SHF_ERROR) 845 #define shf_errno(shf) ((shf)->errno_) 846 #define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR)) 847 848 /* Flags passed to shf_*open() */ 849 #define SHF_RD 0x0001 850 #define SHF_WR 0x0002 851 #define SHF_RDWR (SHF_RD|SHF_WR) 852 #define SHF_ACCMODE 0x0003 /* mask */ 853 #define SHF_GETFL 0x0004 /* use fcntl() to figure RD/WR flags */ 854 #define SHF_UNBUF 0x0008 /* unbuffered I/O */ 855 #define SHF_CLEXEC 0x0010 /* set close on exec flag */ 856 #define SHF_MAPHI 0x0020 /* make fd > FDBASE (and close orig) 857 * (shf_open() only) */ 858 #define SHF_DYNAMIC 0x0040 /* string: increase buffer as needed */ 859 #define SHF_INTERRUPT 0x0080 /* EINTR in read/write causes error */ 860 /* Flags used internally */ 861 #define SHF_STRING 0x0100 /* a string, not a file */ 862 #define SHF_ALLOCS 0x0200 /* shf and shf->buf were alloc()ed */ 863 #define SHF_ALLOCB 0x0400 /* shf->buf was alloc()ed */ 864 #define SHF_ERROR 0x0800 /* read()/write() error */ 865 #define SHF_EOF 0x1000 /* read eof (sticky) */ 866 #define SHF_READING 0x2000 /* currently reading: rnleft,rp valid */ 867 #define SHF_WRITING 0x4000 /* currently writing: wnleft,wp valid */ 868 869 870 struct shf { 871 Area *areap; /* area shf/buf were allocated in */ 872 unsigned char *rp; /* read: current position in buffer */ 873 unsigned char *wp; /* write: current position in buffer */ 874 unsigned char *buf; /* buffer */ 875 int flags; /* see SHF_* */ 876 int rbsize; /* size of buffer (1 if SHF_UNBUF) */ 877 int rnleft; /* read: how much data left in buffer */ 878 int wbsize; /* size of buffer (0 if SHF_UNBUF) */ 879 int wnleft; /* write: how much space left in buffer */ 880 int fd; /* file descriptor */ 881 int errno_; /* saved value of errno after error */ 882 int bsize; /* actual size of buf */ 883 }; 884 885 extern struct shf shf_iob[]; 886 887 struct table { 888 Area *areap; /* area to allocate entries */ 889 struct tbl **tbls; /* hashed table items */ 890 short size, nfree; /* hash size (always 2^^n), free entries */ 891 }; 892 893 struct tbl { /* table item */ 894 Area *areap; /* area to allocate from */ 895 union { 896 char *s; /* string */ 897 mksh_ari_t i; /* integer */ 898 mksh_uari_t u; /* unsigned integer */ 899 int (*f)(const char **);/* int function */ 900 struct op *t; /* "function" tree */ 901 } val; /* value */ 902 union { 903 struct tbl *array; /* array values */ 904 const char *fpath; /* temporary path to undef function */ 905 } u; 906 union { 907 int field; /* field with for -L/-R/-Z */ 908 int errno_; /* CEXEC/CTALIAS */ 909 } u2; 910 int type; /* command type (see below), base (if INTEGER), 911 * or offset from val.s of value (if EXPORT) */ 912 Tflag flag; /* flags */ 913 union { 914 uint32_t hval; /* hash(name) */ 915 uint32_t index; /* index for an array */ 916 } ua; 917 char name[4]; /* name -- variable length */ 918 }; 919 920 /* common flag bits */ 921 #define ALLOC BIT(0) /* val.s has been allocated */ 922 #define DEFINED BIT(1) /* is defined in block */ 923 #define ISSET BIT(2) /* has value, vp->val.[si] */ 924 #define EXPORT BIT(3) /* exported variable/function */ 925 #define TRACE BIT(4) /* var: user flagged, func: execution tracing */ 926 /* (start non-common flags at 8) */ 927 /* flag bits used for variables */ 928 #define SPECIAL BIT(8) /* PATH, IFS, SECONDS, etc */ 929 #define INTEGER BIT(9) /* val.i contains integer value */ 930 #define RDONLY BIT(10) /* read-only variable */ 931 #define LOCAL BIT(11) /* for local typeset() */ 932 #define ARRAY BIT(13) /* array */ 933 #define LJUST BIT(14) /* left justify */ 934 #define RJUST BIT(15) /* right justify */ 935 #define ZEROFIL BIT(16) /* 0 filled if RJUSTIFY, strip 0s if LJUSTIFY */ 936 #define LCASEV BIT(17) /* convert to lower case */ 937 #define UCASEV_AL BIT(18) /* convert to upper case / autoload function */ 938 #define INT_U BIT(19) /* unsigned integer */ 939 #define INT_L BIT(20) /* long integer (no-op) */ 940 #define IMPORT BIT(21) /* flag to typeset(): no arrays, must have = */ 941 #define LOCAL_COPY BIT(22) /* with LOCAL - copy attrs from existing var */ 942 #define EXPRINEVAL BIT(23) /* contents currently being evaluated */ 943 #define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */ 944 #define AINDEX BIT(25) /* array index >0 = ua.index filled in */ 945 #define ASSOC BIT(26) /* ARRAY ? associative : reference */ 946 /* flag bits used for taliases/builtins/aliases/keywords/functions */ 947 #define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */ 948 #define FINUSE BIT(9) /* function being executed */ 949 #define FDELETE BIT(10) /* function deleted while it was executing */ 950 #define FKSH BIT(11) /* function defined with function x (vs x()) */ 951 #define SPEC_BI BIT(12) /* a POSIX special builtin */ 952 #define REG_BI BIT(13) /* a POSIX regular builtin */ 953 /* Attributes that can be set by the user (used to decide if an unset param 954 * should be repoted by set/typeset). Does not include ARRAY or LOCAL. 955 */ 956 #define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL|\ 957 LCASEV|UCASEV_AL|INT_U|INT_L) 958 959 #define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \ 960 (vp)->ua.index : 0)) 961 962 /* command types */ 963 #define CNONE 0 /* undefined */ 964 #define CSHELL 1 /* built-in */ 965 #define CFUNC 2 /* function */ 966 #define CEXEC 4 /* executable command */ 967 #define CALIAS 5 /* alias */ 968 #define CKEYWD 6 /* keyword */ 969 #define CTALIAS 7 /* tracked alias */ 970 971 /* Flags for findcom()/comexec() */ 972 #define FC_SPECBI BIT(0) /* special builtin */ 973 #define FC_FUNC BIT(1) /* function builtin */ 974 #define FC_REGBI BIT(2) /* regular builtin */ 975 #define FC_UNREGBI BIT(3) /* un-regular builtin (!special,!regular) */ 976 #define FC_BI (FC_SPECBI|FC_REGBI|FC_UNREGBI) 977 #define FC_PATH BIT(4) /* do path search */ 978 #define FC_DEFPATH BIT(5) /* use default path in path search */ 979 980 981 #define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */ 982 #define AF_ARGS_ALLOCED 0x2 /* argument strings allocated */ 983 #define AI_ARGV(a, i) ((i) == 0 ? (a).argv[0] : (a).argv[(i) - (a).skip]) 984 #define AI_ARGC(a) ((a).argc_ - (a).skip) 985 986 /* Argument info. Used for $#, $* for shell, functions, includes, etc. */ 987 struct arg_info { 988 const char **argv; 989 int flags; /* AF_* */ 990 int argc_; 991 int skip; /* first arg is argv[0], second is argv[1 + skip] */ 992 }; 993 994 /* 995 * activation record for function blocks 996 */ 997 struct block { 998 Area area; /* area to allocate things */ 999 const char **argv; 1000 char *error; /* error handler */ 1001 char *exit; /* exit handler */ 1002 struct block *next; /* enclosing block */ 1003 struct table vars; /* local variables */ 1004 struct table funs; /* local functions */ 1005 Getopt getopts_state; 1006 int argc; 1007 int flags; /* see BF_* */ 1008 }; 1009 1010 /* Values for struct block.flags */ 1011 #define BF_DOGETOPTS BIT(0) /* save/restore getopts state */ 1012 1013 /* 1014 * Used by ktwalk() and ktnext() routines. 1015 */ 1016 struct tstate { 1017 struct tbl **next; 1018 ssize_t left; 1019 }; 1020 1021 EXTERN struct table taliases; /* tracked aliases */ 1022 EXTERN struct table builtins; /* built-in commands */ 1023 EXTERN struct table aliases; /* aliases */ 1024 EXTERN struct table keywords; /* keywords */ 1025 #ifndef MKSH_NOPWNAM 1026 EXTERN struct table homedirs; /* homedir() cache */ 1027 #endif 1028 1029 struct builtin { 1030 const char *name; 1031 int (*func)(const char **); 1032 }; 1033 1034 extern const struct builtin mkshbuiltins[]; 1035 1036 /* values for set_prompt() */ 1037 #define PS1 0 /* command */ 1038 #define PS2 1 /* command continuation */ 1039 1040 EXTERN char *path; /* copy of either PATH or def_path */ 1041 EXTERN const char *def_path; /* path to use if PATH not set */ 1042 EXTERN char *tmpdir; /* TMPDIR value */ 1043 EXTERN const char *prompt; 1044 EXTERN int cur_prompt; /* PS1 or PS2 */ 1045 EXTERN int current_lineno; /* LINENO value */ 1046 1047 #define NOBLOCK ((struct op *)NULL) 1048 #define NOWORD ((char *)NULL) 1049 #define NOWORDS ((char **)NULL) 1050 1051 /* 1052 * Description of a command or an operation on commands. 1053 */ 1054 struct op { 1055 const char **args; /* arguments to a command */ 1056 char **vars; /* variable assignments */ 1057 struct ioword **ioact; /* IO actions (eg, < > >>) */ 1058 struct op *left, *right; /* descendents */ 1059 char *str; /* word for case; identifier for for, 1060 * select, and functions; 1061 * path to execute for TEXEC; 1062 * time hook for TCOM. 1063 */ 1064 int lineno; /* TCOM/TFUNC: LINENO for this */ 1065 short type; /* operation type, see below */ 1066 union { /* WARNING: newtp(), tcopy() use evalflags = 0 to clear union */ 1067 short evalflags; /* TCOM: arg expansion eval() flags */ 1068 short ksh_func; /* TFUNC: function x (vs x()) */ 1069 } u; 1070 }; 1071 1072 /* Tree.type values */ 1073 #define TEOF 0 1074 #define TCOM 1 /* command */ 1075 #define TPAREN 2 /* (c-list) */ 1076 #define TPIPE 3 /* a | b */ 1077 #define TLIST 4 /* a ; b */ 1078 #define TOR 5 /* || */ 1079 #define TAND 6 /* && */ 1080 #define TBANG 7 /* ! */ 1081 #define TDBRACKET 8 /* [[ .. ]] */ 1082 #define TFOR 9 1083 #define TSELECT 10 1084 #define TCASE 11 1085 #define TIF 12 1086 #define TWHILE 13 1087 #define TUNTIL 14 1088 #define TELIF 15 1089 #define TPAT 16 /* pattern in case */ 1090 #define TBRACE 17 /* {c-list} */ 1091 #define TASYNC 18 /* c & */ 1092 #define TFUNCT 19 /* function name { command; } */ 1093 #define TTIME 20 /* time pipeline */ 1094 #define TEXEC 21 /* fork/exec eval'd TCOM */ 1095 #define TCOPROC 22 /* coprocess |& */ 1096 1097 /* 1098 * prefix codes for words in command tree 1099 */ 1100 #define EOS 0 /* end of string */ 1101 #define CHAR 1 /* unquoted character */ 1102 #define QCHAR 2 /* quoted character */ 1103 #define COMSUB 3 /* $() substitution (0 terminated) */ 1104 #define EXPRSUB 4 /* $(()) substitution (0 terminated) */ 1105 #define OQUOTE 5 /* opening " or ' */ 1106 #define CQUOTE 6 /* closing " or ' */ 1107 #define OSUBST 7 /* opening ${ subst (followed by { or X) */ 1108 #define CSUBST 8 /* closing } of above (followed by } or X) */ 1109 #define OPAT 9 /* open pattern: *(, @(, etc. */ 1110 #define SPAT 10 /* separate pattern: | */ 1111 #define CPAT 11 /* close pattern: ) */ 1112 #define ADELIM 12 /* arbitrary delimiter: ${foo:2:3} ${foo/bar/baz} */ 1113 1114 /* 1115 * IO redirection 1116 */ 1117 struct ioword { 1118 int unit; /* unit affected */ 1119 int flag; /* action (below) */ 1120 char *name; /* file name (unused if heredoc) */ 1121 char *delim; /* delimiter for <<,<<- */ 1122 char *heredoc;/* content of heredoc */ 1123 }; 1124 1125 /* ioword.flag - type of redirection */ 1126 #define IOTYPE 0xF /* type: bits 0:3 */ 1127 #define IOREAD 0x1 /* < */ 1128 #define IOWRITE 0x2 /* > */ 1129 #define IORDWR 0x3 /* <>: todo */ 1130 #define IOHERE 0x4 /* << (here file) */ 1131 #define IOCAT 0x5 /* >> */ 1132 #define IODUP 0x6 /* <&/>& */ 1133 #define IOEVAL BIT(4) /* expand in << */ 1134 #define IOSKIP BIT(5) /* <<-, skip ^\t* */ 1135 #define IOCLOB BIT(6) /* >|, override -o noclobber */ 1136 #define IORDUP BIT(7) /* x<&y (as opposed to x>&y) */ 1137 #define IONAMEXP BIT(8) /* name has been expanded */ 1138 #define IOBASH BIT(9) /* &> etc. */ 1139 1140 /* execute/exchild flags */ 1141 #define XEXEC BIT(0) /* execute without forking */ 1142 #define XFORK BIT(1) /* fork before executing */ 1143 #define XBGND BIT(2) /* command & */ 1144 #define XPIPEI BIT(3) /* input is pipe */ 1145 #define XPIPEO BIT(4) /* output is pipe */ 1146 #define XPIPE (XPIPEI|XPIPEO) /* member of pipe */ 1147 #define XXCOM BIT(5) /* `...` command */ 1148 #define XPCLOSE BIT(6) /* exchild: close close_fd in parent */ 1149 #define XCCLOSE BIT(7) /* exchild: close close_fd in child */ 1150 #define XERROK BIT(8) /* non-zero exit ok (for set -e) */ 1151 #define XCOPROC BIT(9) /* starting a co-process */ 1152 #define XTIME BIT(10) /* timing TCOM command */ 1153 1154 /* 1155 * flags to control expansion of words (assumed by t->evalflags to fit 1156 * in a short) 1157 */ 1158 #define DOBLANK BIT(0) /* perform blank interpretation */ 1159 #define DOGLOB BIT(1) /* expand [?* */ 1160 #define DOPAT BIT(2) /* quote *?[ */ 1161 #define DOTILDE BIT(3) /* normal ~ expansion (first char) */ 1162 #define DONTRUNCOMMAND BIT(4) /* do not run $(command) things */ 1163 #define DOASNTILDE BIT(5) /* assignment ~ expansion (after =, :) */ 1164 #define DOBRACE_ BIT(6) /* used by expand(): do brace expansion */ 1165 #define DOMAGIC_ BIT(7) /* used by expand(): string contains MAGIC */ 1166 #define DOTEMP_ BIT(8) /* ditto : in word part of ${..[%#=?]..} */ 1167 #define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */ 1168 #define DOMARKDIRS BIT(10) /* force markdirs behaviour */ 1169 1170 /* 1171 * The arguments of [[ .. ]] expressions are kept in t->args[] and flags 1172 * indicating how the arguments have been munged are kept in t->vars[]. 1173 * The contents of t->vars[] are stuffed strings (so they can be treated 1174 * like all other t->vars[]) in which the second character is the one that 1175 * is examined. The DB_* defines are the values for these second characters. 1176 */ 1177 #define DB_NORM 1 /* normal argument */ 1178 #define DB_OR 2 /* || -> -o conversion */ 1179 #define DB_AND 3 /* && -> -a conversion */ 1180 #define DB_BE 4 /* an inserted -BE */ 1181 #define DB_PAT 5 /* a pattern argument */ 1182 1183 #define X_EXTRA 8 /* this many extra bytes in X string */ 1184 1185 typedef struct XString { 1186 char *end, *beg; /* end, begin of string */ 1187 size_t len; /* length */ 1188 Area *areap; /* area to allocate/free from */ 1189 } XString; 1190 1191 typedef char *XStringP; 1192 1193 /* initialise expandable string */ 1194 #define XinitN(xs, length, area) do { \ 1195 (xs).len = (length); \ 1196 (xs).areap = (area); \ 1197 (xs).beg = alloc((xs).len + X_EXTRA, (xs).areap); \ 1198 (xs).end = (xs).beg + (xs).len; \ 1199 } while (/* CONSTCOND */ 0) 1200 #define Xinit(xs, xp, length, area) do { \ 1201 XinitN((xs), (length), (area)); \ 1202 (xp) = (xs).beg; \ 1203 } while (/* CONSTCOND */ 0) 1204 1205 /* stuff char into string */ 1206 #define Xput(xs, xp, c) (*xp++ = (c)) 1207 1208 /* check if there are at least n bytes left */ 1209 #define XcheckN(xs, xp, n) do { \ 1210 int more = ((xp) + (n)) - (xs).end; \ 1211 if (more > 0) \ 1212 (xp) = Xcheck_grow_(&(xs), (xp), more); \ 1213 } while (/* CONSTCOND */ 0) 1214 1215 /* check for overflow, expand string */ 1216 #define Xcheck(xs, xp) XcheckN((xs), (xp), 1) 1217 1218 /* free string */ 1219 #define Xfree(xs, xp) afree((xs).beg, (xs).areap) 1220 1221 /* close, return string */ 1222 #define Xclose(xs, xp) aresize((xs).beg, (xp) - (xs).beg, (xs).areap) 1223 1224 /* begin of string */ 1225 #define Xstring(xs, xp) ((xs).beg) 1226 1227 #define Xnleft(xs, xp) ((xs).end - (xp)) /* may be less than 0 */ 1228 #define Xlength(xs, xp) ((xp) - (xs).beg) 1229 #define Xsize(xs, xp) ((xs).end - (xs).beg) 1230 #define Xsavepos(xs, xp) ((xp) - (xs).beg) 1231 #define Xrestpos(xs, xp, n) ((xs).beg + (n)) 1232 1233 char *Xcheck_grow_(XString *, const char *, unsigned int); 1234 1235 /* 1236 * expandable vector of generic pointers 1237 */ 1238 1239 typedef struct XPtrV { 1240 void **cur; /* next avail pointer */ 1241 void **beg, **end; /* begin, end of vector */ 1242 } XPtrV; 1243 1244 #define XPinit(x, n) do { \ 1245 void **vp__; \ 1246 vp__ = alloc((n) * sizeof(void *), ATEMP); \ 1247 (x).cur = (x).beg = vp__; \ 1248 (x).end = vp__ + (n); \ 1249 } while (/* CONSTCOND */ 0) 1250 1251 #define XPput(x, p) do { \ 1252 if ((x).cur >= (x).end) { \ 1253 size_t n = XPsize(x); \ 1254 (x).beg = aresize((x).beg, \ 1255 n * 2 * sizeof(void *), ATEMP); \ 1256 (x).cur = (x).beg + n; \ 1257 (x).end = (x).cur + n; \ 1258 } \ 1259 *(x).cur++ = (p); \ 1260 } while (/* CONSTCOND */ 0) 1261 1262 #define XPptrv(x) ((x).beg) 1263 #define XPsize(x) ((x).cur - (x).beg) 1264 #define XPclose(x) aresize((x).beg, XPsize(x) * sizeof(void *), ATEMP) 1265 #define XPfree(x) afree((x).beg, ATEMP) 1266 1267 #define IDENT 64 1268 1269 typedef struct source Source; 1270 struct source { 1271 const char *str; /* input pointer */ 1272 const char *start; /* start of current buffer */ 1273 union { 1274 const char **strv; /* string [] */ 1275 struct shf *shf; /* shell file */ 1276 struct tbl *tblp; /* alias (SF_HASALIAS) */ 1277 char *freeme; /* also for SREREAD */ 1278 } u; 1279 const char *file; /* input file name */ 1280 int type; /* input type */ 1281 int line; /* line number */ 1282 int errline; /* line the error occurred on (0 if not set) */ 1283 int flags; /* SF_* */ 1284 Area *areap; 1285 Source *next; /* stacked source */ 1286 XString xs; /* input buffer */ 1287 char ugbuf[2]; /* buffer for ungetsc() (SREREAD) and 1288 * alias (SALIAS) */ 1289 }; 1290 1291 /* Source.type values */ 1292 #define SEOF 0 /* input EOF */ 1293 #define SFILE 1 /* file input */ 1294 #define SSTDIN 2 /* read stdin */ 1295 #define SSTRING 3 /* string */ 1296 #define SWSTR 4 /* string without \n */ 1297 #define SWORDS 5 /* string[] */ 1298 #define SWORDSEP 6 /* string[] separator */ 1299 #define SALIAS 7 /* alias expansion */ 1300 #define SREREAD 8 /* read ahead to be re-scanned */ 1301 1302 /* Source.flags values */ 1303 #define SF_ECHO BIT(0) /* echo input to shlout */ 1304 #define SF_ALIAS BIT(1) /* faking space at end of alias */ 1305 #define SF_ALIASEND BIT(2) /* faking space at end of alias */ 1306 #define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */ 1307 #define SF_FIRST BIT(4) /* initial state (to ignore UTF-8 BOM) */ 1308 #define SF_HASALIAS BIT(5) /* u.tblp valid (SALIAS, SEOF) */ 1309 1310 typedef union { 1311 int i; 1312 char *cp; 1313 char **wp; 1314 struct op *o; 1315 struct ioword *iop; 1316 } YYSTYPE; 1317 1318 /* If something is added here, add it to tokentab[] in syn.c as well */ 1319 #define LWORD 256 1320 #define LOGAND 257 /* && */ 1321 #define LOGOR 258 /* || */ 1322 #define BREAK 259 /* ;; */ 1323 #define IF 260 1324 #define THEN 261 1325 #define ELSE 262 1326 #define ELIF 263 1327 #define FI 264 1328 #define CASE 265 1329 #define ESAC 266 1330 #define FOR 267 1331 #define SELECT 268 1332 #define WHILE 269 1333 #define UNTIL 270 1334 #define DO 271 1335 #define DONE 272 1336 #define IN 273 1337 #define FUNCTION 274 1338 #define TIME 275 1339 #define REDIR 276 1340 #define MDPAREN 277 /* (( )) */ 1341 #define BANG 278 /* ! */ 1342 #define DBRACKET 279 /* [[ .. ]] */ 1343 #define COPROC 280 /* |& */ 1344 #define YYERRCODE 300 1345 1346 /* flags to yylex */ 1347 #define CONTIN BIT(0) /* skip new lines to complete command */ 1348 #define ONEWORD BIT(1) /* single word for substitute() */ 1349 #define ALIAS BIT(2) /* recognise alias */ 1350 #define KEYWORD BIT(3) /* recognise keywords */ 1351 #define LETEXPR BIT(4) /* get expression inside (( )) */ 1352 #define VARASN BIT(5) /* check for var=word */ 1353 #define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */ 1354 #define ESACONLY BIT(7) /* only accept esac keyword */ 1355 #define CMDWORD BIT(8) /* parsing simple command (alias related) */ 1356 #define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ 1357 #define LQCHAR BIT(10) /* source string contains QCHAR */ 1358 #define HEREDOC BIT(11) /* parsing a here document */ 1359 #define LETARRAY BIT(12) /* copy expression inside =( ) */ 1360 1361 #define HERES 10 /* max << in line */ 1362 1363 #undef CTRL 1364 #define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */ 1365 #define UNCTRL(x) ((x) ^ 0x40) /* ASCII */ 1366 1367 EXTERN Source *source; /* yyparse/yylex source */ 1368 EXTERN YYSTYPE yylval; /* result from yylex */ 1369 EXTERN struct ioword *heres [HERES], **herep; 1370 EXTERN char ident [IDENT+1]; 1371 1372 #define HISTORYSIZE 500 /* size of saved history */ 1373 1374 EXTERN char **history; /* saved commands */ 1375 EXTERN char **histptr; /* last history item */ 1376 EXTERN int histsize; /* history size */ 1377 1378 /* user and system time of last j_waitjed job */ 1379 EXTERN struct timeval j_usrtime, j_systime; 1380 1381 /* lalloc.c */ 1382 void ainit(Area *); 1383 void afreeall(Area *); 1384 /* these cannot fail and can take NULL (not for ap) */ 1385 #define alloc(n, ap) aresize(NULL, (n), (ap)) 1386 void *aresize(void *, size_t, Area *); 1387 void afree(void *, Area *); /* can take NULL */ 1388 /* edit.c */ 1389 #ifndef MKSH_SMALL 1390 int x_bind(const char *, const char *, bool, bool); 1391 #else 1392 int x_bind(const char *, const char *, bool); 1393 #endif 1394 void x_init(void); 1395 int x_read(char *, size_t); 1396 /* eval.c */ 1397 char *substitute(const char *, int); 1398 char **eval(const char **, int); 1399 char *evalstr(const char *cp, int); 1400 char *evalonestr(const char *cp, int); 1401 char *debunk(char *, const char *, size_t); 1402 void expand(const char *, XPtrV *, int); 1403 int glob_str(char *, XPtrV *, int); 1404 /* exec.c */ 1405 int execute(struct op * volatile, volatile int, volatile int * volatile); 1406 int shcomexec(const char **); 1407 struct tbl *findfunc(const char *, uint32_t, bool); 1408 int define(const char *, struct op *); 1409 void builtin(const char *, int (*)(const char **)); 1410 struct tbl *findcom(const char *, int); 1411 void flushcom(int); 1412 const char *search(const char *, const char *, int, int *); 1413 int search_access(const char *, int, int *); 1414 int pr_menu(const char * const *); 1415 int pr_list(char * const *); 1416 /* expr.c */ 1417 int evaluate(const char *, mksh_ari_t *, int, bool); 1418 int v_evaluate(struct tbl *, const char *, volatile int, bool); 1419 /* UTF-8 stuff */ 1420 size_t utf_mbtowc(unsigned int *, const char *); 1421 size_t utf_wctomb(char *, unsigned int); 1422 int utf_widthadj(const char *, const char **); 1423 int utf_mbswidth(const char *); 1424 const char *utf_skipcols(const char *, int); 1425 size_t utf_ptradj(const char *); 1426 #ifndef MKSH_mirbsd_wcwidth 1427 int utf_wcwidth(unsigned int); 1428 #endif 1429 /* funcs.c */ 1430 int c_hash(const char **); 1431 int c_cd(const char **); 1432 int c_pwd(const char **); 1433 int c_print(const char **); 1434 #ifdef MKSH_PRINTF_BUILTIN 1435 int c_printf(const char **); 1436 #endif 1437 int c_whence(const char **); 1438 int c_command(const char **); 1439 int c_typeset(const char **); 1440 int c_alias(const char **); 1441 int c_unalias(const char **); 1442 int c_let(const char **); 1443 int c_jobs(const char **); 1444 #ifndef MKSH_UNEMPLOYED 1445 int c_fgbg(const char **); 1446 #endif 1447 int c_kill(const char **); 1448 void getopts_reset(int); 1449 int c_getopts(const char **); 1450 int c_bind(const char **); 1451 int c_label(const char **); 1452 int c_shift(const char **); 1453 int c_umask(const char **); 1454 int c_dot(const char **); 1455 int c_wait(const char **); 1456 int c_read(const char **); 1457 int c_eval(const char **); 1458 int c_trap(const char **); 1459 int c_brkcont(const char **); 1460 int c_exitreturn(const char **); 1461 int c_set(const char **); 1462 int c_unset(const char **); 1463 int c_ulimit(const char **); 1464 int c_times(const char **); 1465 int timex(struct op *, int, volatile int *); 1466 void timex_hook(struct op *, char ** volatile *); 1467 int c_exec(const char **); 1468 int c_builtin(const char **); 1469 int c_test(const char **); 1470 #if HAVE_MKNOD 1471 int c_mknod(const char **); 1472 #endif 1473 int c_realpath(const char **); 1474 int c_rename(const char **); 1475 /* histrap.c */ 1476 void init_histvec(void); 1477 void hist_init(Source *); 1478 #if HAVE_PERSISTENT_HISTORY 1479 void hist_finish(void); 1480 #endif 1481 void histsave(int *, const char *, bool, bool); 1482 #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY 1483 bool histsync(void); 1484 #endif 1485 int c_fc(const char **); 1486 void sethistsize(int); 1487 #if HAVE_PERSISTENT_HISTORY 1488 void sethistfile(const char *); 1489 #endif 1490 char **histpos(void); 1491 int histnum(int); 1492 int findhist(int, int, const char *, int); 1493 int findhistrel(const char *); 1494 char **hist_get_newest(bool); 1495 void inittraps(void); 1496 void alarm_init(void); 1497 Trap *gettrap(const char *, int); 1498 void trapsig(int); 1499 void intrcheck(void); 1500 int fatal_trap_check(void); 1501 int trap_pending(void); 1502 void runtraps(int intr); 1503 void runtrap(Trap *); 1504 void cleartraps(void); 1505 void restoresigs(void); 1506 void settrap(Trap *, const char *); 1507 int block_pipe(void); 1508 void restore_pipe(int); 1509 int setsig(Trap *, sig_t, int); 1510 void setexecsig(Trap *, int); 1511 /* jobs.c */ 1512 void j_init(void); 1513 void j_exit(void); 1514 #ifndef MKSH_UNEMPLOYED 1515 void j_change(void); 1516 #endif 1517 int exchild(struct op *, int, volatile int *, int); 1518 void startlast(void); 1519 int waitlast(void); 1520 int waitfor(const char *, int *); 1521 int j_kill(const char *, int); 1522 #ifndef MKSH_UNEMPLOYED 1523 int j_resume(const char *, int); 1524 #endif 1525 int j_jobs(const char *, int, int); 1526 int j_njobs(void); 1527 void j_notify(void); 1528 pid_t j_async(void); 1529 int j_stopped_running(void); 1530 /* lex.c */ 1531 int yylex(int); 1532 void yyerror(const char *, ...) 1533 MKSH_A_NORETURN 1534 MKSH_A_FORMAT(printf, 1, 2); 1535 Source *pushs(int, Area *); 1536 void set_prompt(int, Source *); 1537 void pprompt(const char *, int); 1538 int promptlen(const char *); 1539 /* main.c */ 1540 int include(const char *, int, const char **, int); 1541 int command(const char *, int); 1542 int shell(Source *volatile, int volatile); 1543 void unwind(int) MKSH_A_NORETURN; 1544 void newenv(int); 1545 void quitenv(struct shf *); 1546 void cleanup_parents_env(void); 1547 void cleanup_proc_env(void); 1548 void errorf(const char *, ...) 1549 MKSH_A_NORETURN 1550 MKSH_A_FORMAT(printf, 1, 2); 1551 void warningf(bool, const char *, ...) 1552 MKSH_A_FORMAT(printf, 2, 3); 1553 void bi_errorf(const char *, ...) 1554 MKSH_A_FORMAT(printf, 1, 2); 1555 #define errorfz() errorf("\1") 1556 #define bi_errorfz() bi_errorf("\1") 1557 void internal_verrorf(const char *, va_list) 1558 MKSH_A_FORMAT(printf, 1, 0); 1559 void internal_errorf(const char *, ...) 1560 MKSH_A_NORETURN 1561 MKSH_A_FORMAT(printf, 1, 2); 1562 void internal_warningf(const char *, ...) 1563 MKSH_A_FORMAT(printf, 1, 2); 1564 void error_prefix(bool); 1565 void shellf(const char *, ...) 1566 MKSH_A_FORMAT(printf, 1, 2); 1567 void shprintf(const char *, ...) 1568 MKSH_A_FORMAT(printf, 1, 2); 1569 int can_seek(int); 1570 void initio(void); 1571 int ksh_dup2(int, int, bool); 1572 short savefd(int); 1573 void restfd(int, int); 1574 void openpipe(int *); 1575 void closepipe(int *); 1576 int check_fd(const char *, int, const char **); 1577 void coproc_init(void); 1578 void coproc_read_close(int); 1579 void coproc_readw_close(int); 1580 void coproc_write_close(int); 1581 int coproc_getfd(int, const char **); 1582 void coproc_cleanup(int); 1583 struct temp *maketemp(Area *, Temp_type, struct temp **); 1584 #define hash(s) oaathash_full((const uint8_t *)(s)) 1585 uint32_t oaathash_full(register const uint8_t *); 1586 uint32_t hashmem(const void *, size_t); 1587 void ktinit(struct table *, Area *, size_t); 1588 struct tbl *ktsearch(struct table *, const char *, uint32_t); 1589 struct tbl *ktenter(struct table *, const char *, uint32_t); 1590 #define ktdelete(p) do { p->flag = 0; } while (/* CONSTCOND */ 0) 1591 void ktwalk(struct tstate *, struct table *); 1592 struct tbl *ktnext(struct tstate *); 1593 struct tbl **ktsort(struct table *); 1594 /* misc.c */ 1595 void setctypes(const char *, int); 1596 void initctypes(void); 1597 size_t option(const char *); 1598 char *getoptions(void); 1599 void change_flag(enum sh_flag, int, unsigned int); 1600 int parse_args(const char **, int, bool *); 1601 int getn(const char *, int *); 1602 int bi_getn(const char *, int *); 1603 int gmatchx(const char *, const char *, bool); 1604 int has_globbing(const char *, const char *); 1605 const unsigned char *pat_scan(const unsigned char *, const unsigned char *, int); 1606 int xstrcmp(const void *, const void *); 1607 void ksh_getopt_reset(Getopt *, int); 1608 int ksh_getopt(const char **, Getopt *, const char *); 1609 void print_value_quoted(const char *); 1610 void print_columns(struct shf *, int, 1611 char *(*)(char *, int, int, const void *), 1612 const void *, int, int, bool); 1613 void strip_nuls(char *, int); 1614 int blocking_read(int, char *, int) 1615 MKSH_A_BOUNDED(buffer, 2, 3); 1616 int reset_nonblock(int); 1617 char *ksh_get_wd(size_t *); 1618 int make_path(const char *, const char *, char **, XString *, int *); 1619 void simplify_path(char *); 1620 void set_current_wd(char *); 1621 #ifdef MKSH_SMALL 1622 char *strdup_(const char *, Area *); 1623 char *strndup_(const char *, size_t, Area *); 1624 #endif 1625 int unbksl(bool, int (*)(void), void (*)(int)); 1626 /* shf.c */ 1627 struct shf *shf_open(const char *, int, int, int); 1628 struct shf *shf_fdopen(int, int, struct shf *); 1629 struct shf *shf_reopen(int, int, struct shf *); 1630 struct shf *shf_sopen(char *, int, int, struct shf *); 1631 int shf_close(struct shf *); 1632 int shf_fdclose(struct shf *); 1633 char *shf_sclose(struct shf *); 1634 int shf_flush(struct shf *); 1635 int shf_read(char *, int, struct shf *); 1636 char *shf_getse(char *, int, struct shf *); 1637 int shf_getchar(struct shf *s); 1638 int shf_ungetc(int, struct shf *); 1639 int shf_putchar(int, struct shf *); 1640 int shf_puts(const char *, struct shf *); 1641 int shf_write(const char *, int, struct shf *); 1642 int shf_fprintf(struct shf *, const char *, ...) 1643 MKSH_A_FORMAT(printf, 2, 3); 1644 int shf_snprintf(char *, int, const char *, ...) 1645 MKSH_A_FORMAT(printf, 3, 4) 1646 MKSH_A_BOUNDED(string, 1, 2); 1647 char *shf_smprintf(const char *, ...) 1648 MKSH_A_FORMAT(printf, 1, 2); 1649 int shf_vfprintf(struct shf *, const char *, va_list) 1650 MKSH_A_FORMAT(printf, 2, 0); 1651 /* syn.c */ 1652 void initkeywords(void); 1653 struct op *compile(Source *); 1654 /* tree.c */ 1655 int fptreef(struct shf *, int, const char *, ...); 1656 char *snptreef(char *, int, const char *, ...); 1657 struct op *tcopy(struct op *, Area *); 1658 char *wdcopy(const char *, Area *); 1659 const char *wdscan(const char *, int); 1660 char *wdstrip(const char *, bool, bool); 1661 void tfree(struct op *, Area *); 1662 /* var.c */ 1663 void newblock(void); 1664 void popblock(void); 1665 void initvar(void); 1666 struct tbl *global(const char *); 1667 struct tbl *local(const char *, bool); 1668 char *str_val(struct tbl *); 1669 int setstr(struct tbl *, const char *, int); 1670 struct tbl *setint_v(struct tbl *, struct tbl *, bool); 1671 void setint(struct tbl *, mksh_ari_t); 1672 struct tbl *typeset(const char *, Tflag, Tflag, int, int) 1673 MKSH_A_NONNULL((nonnull (1))); 1674 void unset(struct tbl *, int); 1675 const char *skip_varname(const char *, int); 1676 const char *skip_wdvarname(const char *, int); 1677 int is_wdvarname(const char *, int); 1678 int is_wdvarassign(const char *); 1679 char **makenv(void); 1680 void change_random(const void *, size_t); 1681 void change_winsz(void); 1682 int array_ref_len(const char *); 1683 char *arrayname(const char *); 1684 mksh_uari_t set_array(const char *, bool, const char **); 1685 1686 enum Test_op { 1687 TO_NONOP = 0, /* non-operator */ 1688 /* unary operators */ 1689 TO_STNZE, TO_STZER, TO_OPTION, 1690 TO_FILAXST, 1691 TO_FILEXST, 1692 TO_FILREG, TO_FILBDEV, TO_FILCDEV, TO_FILSYM, TO_FILFIFO, TO_FILSOCK, 1693 TO_FILCDF, TO_FILID, TO_FILGID, TO_FILSETG, TO_FILSTCK, TO_FILUID, 1694 TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX, 1695 /* binary operators */ 1696 TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT, 1697 TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT, 1698 /* not an operator */ 1699 TO_NONNULL /* !TO_NONOP */ 1700 }; 1701 typedef enum Test_op Test_op; 1702 1703 /* Used by Test_env.isa() (order important - used to index *_tokens[] arrays) */ 1704 enum Test_meta { 1705 TM_OR, /* -o or || */ 1706 TM_AND, /* -a or && */ 1707 TM_NOT, /* ! */ 1708 TM_OPAREN, /* ( */ 1709 TM_CPAREN, /* ) */ 1710 TM_UNOP, /* unary operator */ 1711 TM_BINOP, /* binary operator */ 1712 TM_END /* end of input */ 1713 }; 1714 typedef enum Test_meta Test_meta; 1715 1716 #define TEF_ERROR BIT(0) /* set if we've hit an error */ 1717 #define TEF_DBRACKET BIT(1) /* set if [[ .. ]] test */ 1718 1719 typedef struct test_env { 1720 union { 1721 const char **wp;/* used by ptest_* */ 1722 XPtrV *av; /* used by dbtestp_* */ 1723 } pos; 1724 const char **wp_end; /* used by ptest_* */ 1725 Test_op (*isa)(struct test_env *, Test_meta); 1726 const char *(*getopnd) (struct test_env *, Test_op, bool); 1727 int (*eval)(struct test_env *, Test_op, const char *, const char *, bool); 1728 void (*error)(struct test_env *, int, const char *); 1729 int flags; /* TEF_* */ 1730 } Test_env; 1731 1732 extern const char *const dbtest_tokens[]; 1733 1734 Test_op test_isop(Test_meta, const char *); 1735 int test_eval(Test_env *, Test_op, const char *, const char *, bool); 1736 int test_parse(Test_env *); 1737 1738 EXTERN int tty_fd I__(-1); /* dup'd tty file descriptor */ 1739 EXTERN int tty_devtty; /* true if tty_fd is from /dev/tty */ 1740 EXTERN struct termios tty_state; /* saved tty state */ 1741 1742 extern void tty_init(bool, bool); 1743 extern void tty_close(void); 1744 1745 /* be sure not to interfere with anyone else's idea about EXTERN */ 1746 #ifdef EXTERN_DEFINED 1747 # undef EXTERN_DEFINED 1748 # undef EXTERN 1749 #endif 1750 #undef I__ 1751 1752 #endif /* !MKSH_INCLUDES_ONLY */ 1753