1/* $OpenBSD: sh.h,v 1.77 2023/06/21 22:22:08 millert Exp $ */ 2 3/* 4 * Public Domain Bourne/Korn shell 5 */ 6 7/* $From: sh.h,v 1.2 1994/05/19 18:32:40 michael Exp michael $ */ 8 9#include "config.h" /* system and option configuration info */ 10 11/* Start of common headers */ 12 13#include <limits.h> 14#include <setjmp.h> 15#include <stdarg.h> 16#include <stddef.h> 17#include <signal.h> 18#include <stdbool.h> 19 20/* end of common headers */ 21 22#define NELEM(a) (sizeof(a) / sizeof((a)[0])) 23#define BIT(i) (1<<(i)) /* define bit in flag */ 24 25#define NUFILE 32 /* Number of user-accessible files */ 26#define FDBASE 10 /* First file usable by Shell */ 27 28#define BITS(t) (CHAR_BIT * sizeof(t)) 29 30/* Make MAGIC a char that might be printed to make bugs more obvious, but 31 * not a char that is used often. Also, can't use the high bit as it causes 32 * portability problems (calling strchr(x, 0x80|'x') is error prone). 33 */ 34#define MAGIC (7) /* prefix for *?[!{,} during expand */ 35#define ISMAGIC(c) ((unsigned char)(c) == MAGIC) 36 37#define LINE 4096 /* input line size */ 38 39extern const char *kshname; /* $0 */ 40extern pid_t kshpid; /* $$, shell pid */ 41extern pid_t procpid; /* pid of executing process */ 42extern uid_t ksheuid; /* effective uid of shell */ 43extern int exstat; /* exit status */ 44extern int subst_exstat; /* exit status of last $(..)/`..` */ 45extern const char *safe_prompt; /* safe prompt if PS1 substitution fails */ 46extern char username[]; /* username for \u prompt expansion */ 47extern int disable_subst; /* disable substitution during evaluation */ 48 49/* 50 * Area-based allocation built on malloc/free 51 */ 52typedef struct Area { 53 struct link *freelist; /* free list */ 54} Area; 55 56extern Area aperm; /* permanent object space */ 57#define APERM &aperm 58#define ATEMP &genv->area 59 60#ifdef KSH_DEBUG 61# define kshdebug_init() kshdebug_init_() 62# define kshdebug_printf(a) kshdebug_printf_ a 63# define kshdebug_dump(a) kshdebug_dump_ a 64#else /* KSH_DEBUG */ 65# define kshdebug_init() 66# define kshdebug_printf(a) 67# define kshdebug_dump(a) 68#endif /* KSH_DEBUG */ 69 70/* 71 * parsing & execution environment 72 */ 73struct env { 74 short type; /* environment type - see below */ 75 short flags; /* EF_* */ 76 Area area; /* temporary allocation area */ 77 struct block *loc; /* local variables and functions */ 78 short *savefd; /* original redirected fd's */ 79 struct env *oenv; /* link to previous environment */ 80 sigjmp_buf jbuf; /* long jump back to env creator */ 81 struct temp *temps; /* temp files */ 82}; 83extern struct env *genv; 84 85/* struct env.type values */ 86#define E_NONE 0 /* dummy environment */ 87#define E_PARSE 1 /* parsing command # */ 88#define E_FUNC 2 /* executing function # */ 89#define E_INCL 3 /* including a file via . # */ 90#define E_EXEC 4 /* executing command tree */ 91#define E_LOOP 5 /* executing for/while # */ 92#define E_ERRH 6 /* general error handler # */ 93/* # indicates env has valid jbuf (see unwind()) */ 94 95/* struct env.flag values */ 96#define EF_FUNC_PARSE BIT(0) /* function being parsed */ 97#define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */ 98#define EF_FAKE_SIGDIE BIT(2) /* hack to get info from unwind to quitenv */ 99 100/* Do breaks/continues stop at env type e? */ 101#define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE \ 102 || (t) == E_FUNC || (t) == E_INCL) 103/* Do returns stop at env type e? */ 104#define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL) 105 106/* values for siglongjmp(e->jbuf, 0) */ 107#define LRETURN 1 /* return statement */ 108#define LEXIT 2 /* exit statement */ 109#define LERROR 3 /* errorf() called */ 110#define LLEAVE 4 /* untrappable exit/error */ 111#define LINTR 5 /* ^C noticed */ 112#define LBREAK 6 /* break statement */ 113#define LCONTIN 7 /* continue statement */ 114#define LSHELL 8 /* return to interactive shell() */ 115#define LAEXPR 9 /* error in arithmetic expression */ 116 117/* option processing */ 118#define OF_CMDLINE 0x01 /* command line */ 119#define OF_SET 0x02 /* set builtin */ 120#define OF_SPECIAL 0x04 /* a special variable changing */ 121#define OF_INTERNAL 0x08 /* set internally by shell */ 122#define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL) 123 124struct option { 125 const char *name; /* long name of option */ 126 char c; /* character flag (if any) */ 127 short flags; /* OF_* */ 128}; 129extern const struct option sh_options[]; 130 131/* 132 * flags (the order of these enums MUST match the order in misc.c(options[])) 133 */ 134enum sh_flag { 135 FEXPORT = 0, /* -a: export all */ 136 FBRACEEXPAND, /* enable {} globbing */ 137 FBGNICE, /* bgnice */ 138 FCOMMAND, /* -c: (invocation) execute specified command */ 139 FCSHHISTORY, /* csh-style history enabled */ 140#ifdef EMACS 141 FEMACS, /* emacs command editing */ 142#endif 143 FERREXIT, /* -e: quit on error */ 144#ifdef EMACS 145 FGMACS, /* gmacs command editing */ 146#endif 147 FIGNOREEOF, /* eof does not exit */ 148 FTALKING, /* -i: interactive */ 149 FKEYWORD, /* -k: name=value anywhere */ 150 FLOGIN, /* -l: a login shell */ 151 FMARKDIRS, /* mark dirs with / in file name completion */ 152 FMONITOR, /* -m: job control monitoring */ 153 FNOCLOBBER, /* -C: don't overwrite existing files */ 154 FNOEXEC, /* -n: don't execute any commands */ 155 FNOGLOB, /* -f: don't do file globbing */ 156 FNOHUP, /* -H: don't kill running jobs when login shell exits */ 157 FNOLOG, /* don't save functions in history (ignored) */ 158 FNOTIFY, /* -b: asynchronous job completion notification */ 159 FNOUNSET, /* -u: using an unset var is an error */ 160 FPHYSICAL, /* -o physical: don't do logical cd's/pwd's */ 161 FPIPEFAIL, /* -o pipefail: all commands in pipeline can affect $? */ 162 FPOSIX, /* -o posix: be posixly correct */ 163 FPRIVILEGED, /* -p: use suid_profile */ 164 FRESTRICTED, /* -r: restricted shell */ 165 FSH, /* -o sh: favor sh behaviour */ 166 FSTDIN, /* -s: (invocation) parse stdin */ 167 FTRACKALL, /* -h: create tracked aliases for all commands */ 168 FVERBOSE, /* -v: echo input */ 169#ifdef VI 170 FVI, /* vi command editing */ 171 FVIRAW, /* always read in raw mode (ignored) */ 172 FVISHOW8, /* display chars with 8th bit set as is (versus M-) */ 173 FVITABCOMPLETE, /* enable tab as file name completion char */ 174 FVIESCCOMPLETE, /* enable ESC as file name completion in command mode */ 175#endif 176 FXTRACE, /* -x: execution trace */ 177 FTALKING_I, /* (internal): initial shell was interactive */ 178 FNFLAGS /* (place holder: how many flags are there) */ 179}; 180 181#define Flag(f) (shell_flags[(int) (f)]) 182 183extern char shell_flags[FNFLAGS]; 184 185extern char null[]; /* null value for variable */ 186 187enum temp_type { 188 TT_HEREDOC_EXP, /* expanded heredoc */ 189 TT_HIST_EDIT /* temp file used for history editing (fc -e) */ 190}; 191typedef enum temp_type Temp_type; 192/* temp/heredoc files. The file is removed when the struct is freed. */ 193struct temp { 194 struct temp *next; 195 struct shf *shf; 196 int pid; /* pid of process parsed here-doc */ 197 Temp_type type; 198 char *name; 199}; 200 201/* 202 * stdio and our IO routines 203 */ 204 205#define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ 206#define shl_stdout (&shf_iob[1]) 207#define shl_out (&shf_iob[2]) 208extern int shl_stdout_ok; 209 210/* 211 * trap handlers 212 */ 213typedef struct trap { 214 int signal; /* signal number */ 215 const char *name; /* short name */ 216 const char *mess; /* descriptive name */ 217 char *trap; /* trap command */ 218 volatile sig_atomic_t set; /* trap pending */ 219 int flags; /* TF_* */ 220 sig_t cursig; /* current handler (valid if TF_ORIG_* set) */ 221 sig_t shtrap; /* shell signal handler */ 222} Trap; 223 224/* values for Trap.flags */ 225#define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */ 226#define TF_USER_SET BIT(1) /* user has (tried to) set trap */ 227#define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */ 228#define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */ 229#define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */ 230#define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */ 231#define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */ 232#define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */ 233#define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */ 234#define TF_FATAL BIT(9) /* causes termination if not trapped */ 235 236/* values for setsig()/setexecsig() flags argument */ 237#define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */ 238#define SS_RESTORE_CURR 0 /* leave current handler in place */ 239#define SS_RESTORE_ORIG 1 /* restore original handler */ 240#define SS_RESTORE_DFL 2 /* restore to SIG_DFL */ 241#define SS_RESTORE_IGN 3 /* restore to SIG_IGN */ 242#define SS_FORCE BIT(3) /* set signal even if original signal ignored */ 243#define SS_USER BIT(4) /* user is doing the set (ie, trap command) */ 244#define SS_SHTRAP BIT(5) /* trap for internal use (CHLD,ALRM,WINCH) */ 245 246#define SIGEXIT_ 0 /* for trap EXIT */ 247#define SIGERR_ NSIG /* for trap ERR */ 248 249extern volatile sig_atomic_t trap; /* traps pending? */ 250extern volatile sig_atomic_t intrsig; /* pending trap interrupts command */ 251extern volatile sig_atomic_t fatal_trap; /* received a fatal signal */ 252extern volatile sig_atomic_t got_sigwinch; 253extern Trap sigtraps[NSIG+1]; 254 255/* 256 * TMOUT support 257 */ 258/* values for ksh_tmout_state */ 259enum tmout_enum { 260 TMOUT_EXECUTING = 0, /* executing commands */ 261 TMOUT_READING, /* waiting for input */ 262 TMOUT_LEAVING /* have timed out */ 263}; 264extern unsigned int ksh_tmout; 265extern enum tmout_enum ksh_tmout_state; 266 267/* For "You have stopped jobs" message */ 268extern int really_exit; 269 270/* 271 * fast character classes 272 */ 273#define C_ALPHA BIT(0) /* a-z_A-Z */ 274/* was C_DIGIT */ 275#define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */ 276#define C_VAR1 BIT(3) /* *@#!$-? */ 277#define C_IFSWS BIT(4) /* \t \n (IFS white space) */ 278#define C_SUBOP1 BIT(5) /* "=-+?" */ 279#define C_SUBOP2 BIT(6) /* "#%" */ 280#define C_IFS BIT(7) /* $IFS */ 281#define C_QUOTE BIT(8) /* \n\t"#$&'()*;<>?[\`| (needing quoting) */ 282 283extern short ctypes []; 284 285#define ctype(c, t) !!(ctypes[(unsigned char)(c)]&(t)) 286#define letter(c) ctype(c, C_ALPHA) 287#define digit(c) isdigit((unsigned char)(c)) 288#define letnum(c) (ctype(c, C_ALPHA) || isdigit((unsigned char)(c))) 289 290extern int ifs0; /* for "$*" */ 291 292/* Argument parsing for built-in commands and getopts command */ 293 294/* Values for Getopt.flags */ 295#define GF_ERROR BIT(0) /* call errorf() if there is an error */ 296#define GF_PLUSOPT BIT(1) /* allow +c as an option */ 297#define GF_NONAME BIT(2) /* don't print argv[0] in errors */ 298 299/* Values for Getopt.info */ 300#define GI_MINUS BIT(0) /* an option started with -... */ 301#define GI_PLUS BIT(1) /* an option started with +... */ 302#define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */ 303 304typedef struct { 305 int optind; 306 int uoptind;/* what user sees in $OPTIND */ 307 char *optarg; 308 int flags; /* see GF_* */ 309 int info; /* see GI_* */ 310 unsigned int p; /* 0 or index into argv[optind - 1] */ 311 char buf[2]; /* for bad option OPTARG value */ 312} Getopt; 313 314extern Getopt builtin_opt; /* for shell builtin commands */ 315extern Getopt user_opt; /* parsing state for getopts builtin command */ 316 317/* This for co-processes */ 318 319typedef int Coproc_id; /* something that won't (realistically) wrap */ 320struct coproc { 321 int read; /* pipe from co-process's stdout */ 322 int readw; /* other side of read (saved temporarily) */ 323 int write; /* pipe to co-process's stdin */ 324 Coproc_id id; /* id of current output pipe */ 325 int njobs; /* number of live jobs using output pipe */ 326 void *job; /* 0 or job of co-process using input pipe */ 327}; 328extern struct coproc coproc; 329 330/* Used in jobs.c and by coprocess stuff in exec.c */ 331extern sigset_t sm_default, sm_sigchld; 332 333extern const char ksh_version[]; 334 335/* name of called builtin function (used by error functions) */ 336extern char *builtin_argv0; 337extern int builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ 338 339/* current working directory, and size of memory allocated for same */ 340extern char *current_wd; 341extern int current_wd_size; 342 343/* Minimum required space to work with on a line - if the prompt leaves less 344 * space than this on a line, the prompt is truncated. 345 */ 346#define MIN_EDIT_SPACE 7 347/* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line 348 */ 349#define MIN_COLS (2 + MIN_EDIT_SPACE + 3) 350extern int x_cols; /* tty columns */ 351 352/* These to avoid bracket matching problems */ 353#define OPAREN '(' 354#define CPAREN ')' 355#define OBRACK '[' 356#define CBRACK ']' 357#define OBRACE '{' 358#define CBRACE '}' 359 360/* Determine the location of the system (common) profile */ 361#define KSH_SYSTEM_PROFILE "/etc/profile" 362 363/* Used by v_evaluate() and setstr() to control action when error occurs */ 364#define KSH_UNWIND_ERROR 0x0 /* unwind the stack (longjmp) */ 365#define KSH_RETURN_ERROR 0x1 /* return 1/0 for success/failure */ 366#define KSH_IGNORE_RDONLY 0x4 /* ignore the read-only flag */ 367 368#include "shf.h" 369#include "table.h" 370#include "tree.h" 371#include "expand.h" 372#include "lex.h" 373 374/* alloc.c */ 375Area * ainit(Area *); 376void afreeall(Area *); 377void * alloc(size_t, Area *); 378void * areallocarray(void *, size_t, size_t, Area *); 379void * aresize(void *, size_t, Area *); 380void afree(void *, Area *); 381/* c_ksh.c */ 382int c_cd(char **); 383int c_pwd(char **); 384int c_print(char **); 385int c_whence(char **); 386int c_command(char **); 387int c_type(char **); 388int c_typeset(char **); 389int c_alias(char **); 390int c_unalias(char **); 391int c_let(char **); 392int c_jobs(char **); 393int c_fgbg(char **); 394int c_kill(char **); 395void getopts_reset(int); 396int c_getopts(char **); 397int c_bind(char **); 398/* c_sh.c */ 399int c_label(char **); 400int c_shift(char **); 401int c_umask(char **); 402int c_dot(char **); 403int c_wait(char **); 404int c_read(char **); 405int c_eval(char **); 406int c_trap(char **); 407int c_brkcont(char **); 408int c_exitreturn(char **); 409int c_set(char **); 410int c_unset(char **); 411int c_ulimit(char **); 412int c_times(char **); 413int timex(struct op *, int, volatile int *); 414void timex_hook(struct op *, char ** volatile *); 415int c_exec(char **); 416int c_builtin(char **); 417/* c_test.c */ 418int c_test(char **); 419/* edit.c: most prototypes in edit.h */ 420void x_init(void); 421int x_read(char *, size_t); 422void set_editmode(const char *); 423/* emacs.c: most prototypes in edit.h */ 424int x_bind(const char *, const char *, int, int); 425/* eval.c */ 426char * substitute(const char *, int); 427char ** eval(char **, int); 428char * evalstr(char *cp, int); 429char * evalonestr(char *cp, int); 430char *debunk(char *, const char *, size_t); 431void expand(char *, XPtrV *, int); 432int glob_str(char *, XPtrV *, int); 433/* exec.c */ 434int execute(struct op * volatile, volatile int, volatile int *); 435int shcomexec(char **); 436struct tbl * findfunc(const char *, unsigned int, int); 437int define(const char *, struct op *); 438void builtin(const char *, int (*)(char **)); 439struct tbl * findcom(const char *, int); 440void flushcom(int); 441char * search(const char *, const char *, int, int *); 442int search_access(const char *, int, int *); 443int pr_menu(char *const *); 444/* expr.c */ 445int evaluate(const char *, int64_t *, int, bool); 446int v_evaluate(struct tbl *, const char *, volatile int, bool); 447/* history.c */ 448void init_histvec(void); 449void hist_init(Source *); 450void hist_finish(void); 451void histsave(int, const char *, int); 452int c_fc(char **); 453void c_fc_reset(void); 454void sethistcontrol(const char *); 455void sethistsize(int); 456void sethistfile(const char *); 457char ** histpos(void); 458int histnum(int); 459int findhist(int, int, const char *, int); 460int findhistrel(const char *); 461char **hist_get_newest(int); 462 463/* io.c */ 464void errorf(const char *, ...) 465 __attribute__((__noreturn__, __format__ (printf, 1, 2))); 466void warningf(bool, const char *, ...) 467 __attribute__((__format__ (printf, 2, 3))); 468void bi_errorf(const char *, ...) 469 __attribute__((__format__ (printf, 1, 2))); 470void internal_errorf(const char *, ...) 471 __attribute__((__noreturn__, __format__ (printf, 1, 2))); 472void internal_warningf(const char *, ...) 473 __attribute__((__format__ (printf, 1, 2))); 474void error_prefix(int); 475void shellf(const char *, ...) 476 __attribute__((__format__ (printf, 1, 2))); 477void shprintf(const char *, ...) 478 __attribute__((__format__ (printf, 1, 2))); 479#ifdef KSH_DEBUG 480void kshdebug_init_(void); 481void kshdebug_printf_(const char *, ...) 482 __attribute__((__format__ (printf, 1, 2))); 483void kshdebug_dump_(const char *, const void *, int); 484#endif /* KSH_DEBUG */ 485int can_seek(int); 486void initio(void); 487int ksh_dup2(int, int, int); 488int savefd(int); 489void restfd(int, int); 490void openpipe(int *); 491void closepipe(int *); 492int check_fd(char *, int, const char **); 493void coproc_init(void); 494void coproc_read_close(int); 495void coproc_readw_close(int); 496void coproc_write_close(int); 497int coproc_getfd(int, const char **); 498void coproc_cleanup(int); 499struct temp *maketemp(Area *, Temp_type, struct temp **); 500/* jobs.c */ 501void j_init(int); 502void j_suspend(void); 503void j_exit(void); 504void j_change(void); 505int exchild(struct op *, int, volatile int *, int); 506void startlast(void); 507int waitlast(void); 508int waitfor(const char *, int *); 509int j_kill(const char *, int); 510int j_resume(const char *, int); 511int j_jobs(const char *, int, int); 512int j_njobs(void); 513void j_notify(void); 514pid_t j_async(void); 515int j_stopped_running(void); 516/* mail.c */ 517void mcheck(void); 518void mcset(int64_t); 519void mbset(char *); 520void mpset(char *); 521/* main.c */ 522int include(const char *, int, char **, int); 523int command(const char *, int); 524int shell(Source *volatile, int volatile); 525void unwind(int) __attribute__((__noreturn__)); 526void newenv(int); 527void quitenv(struct shf *); 528void cleanup_parents_env(void); 529void cleanup_proc_env(void); 530/* misc.c */ 531void setctypes(const char *, int); 532void initctypes(void); 533char * u64ton(uint64_t, int); 534char * str_save(const char *, Area *); 535char * str_nsave(const char *, int, Area *); 536int option(const char *); 537char * getoptions(void); 538void change_flag(enum sh_flag, int, int); 539int parse_args(char **, int, int *); 540int getn(const char *, int *); 541int bi_getn(const char *, int *); 542int gmatch(const char *, const char *, int); 543int has_globbing(const char *, const char *); 544const unsigned char *pat_scan(const unsigned char *, const unsigned char *, 545 int); 546void qsortp(void **, size_t, int (*)(const void *, const void *)); 547int xstrcmp(const void *, const void *); 548void ksh_getopt_reset(Getopt *, int); 549int ksh_getopt(char **, Getopt *, const char *); 550void print_value_quoted(const char *); 551void print_columns(struct shf *, int, char *(*)(void *, int, char *, int), 552 void *, int, int prefcol); 553int strip_nuls(char *, int); 554int blocking_read(int, char *, int); 555int reset_nonblock(int); 556char *ksh_get_wd(char *, int); 557/* path.c */ 558int make_path(const char *, const char *, char **, XString *, int *); 559void simplify_path(char *); 560char *get_phys_path(const char *); 561void set_current_wd(char *); 562/* syn.c */ 563void initkeywords(void); 564struct op * compile(Source *); 565/* trap.c */ 566void inittraps(void); 567void alarm_init(void); 568Trap * gettrap(const char *, int); 569void trapsig(int); 570void intrcheck(void); 571int fatal_trap_check(void); 572int trap_pending(void); 573void runtraps(int intr); 574void runtrap(Trap *); 575void cleartraps(void); 576void restoresigs(void); 577void settrap(Trap *, char *); 578int block_pipe(void); 579void restore_pipe(int); 580int setsig(Trap *, sig_t, int); 581void setexecsig(Trap *, int); 582/* var.c */ 583void newblock(void); 584void popblock(void); 585void initvar(void); 586struct tbl * global(const char *); 587struct tbl * local(const char *, bool); 588char * str_val(struct tbl *); 589int64_t intval(struct tbl *); 590int setstr(struct tbl *, const char *, int); 591struct tbl *setint_v(struct tbl *, struct tbl *, bool); 592void setint(struct tbl *, int64_t); 593int getint(struct tbl *, int64_t *, bool); 594struct tbl *typeset(const char *, int, int, int, int); 595void unset(struct tbl *, int); 596char * skip_varname(const char *, int); 597char *skip_wdvarname(const char *, int); 598int is_wdvarname(const char *, int); 599int is_wdvarassign(const char *); 600char ** makenv(void); 601void change_random(void); 602int array_ref_len(const char *); 603char * arrayname(const char *); 604void set_array(const char *, int, char **); 605/* vi.c: see edit.h */ 606