sh.h
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 shellnof(const char *, ...)
478 __attribute__((__format__ (printf, 1, 2)));
479void shprintf(const char *, ...)
480 __attribute__((__format__ (printf, 1, 2)));
481#ifdef KSH_DEBUG
482void kshdebug_init_(void);
483void kshdebug_printf_(const char *, ...)
484 __attribute__((__format__ (printf, 1, 2)));
485void kshdebug_dump_(const char *, const void *, int);
486#endif /* KSH_DEBUG */
487int can_seek(int);
488void initio(void);
489int ksh_dup2(int, int, int);
490int savefd(int);
491void restfd(int, int);
492void openpipe(int *);
493void closepipe(int *);
494int check_fd(char *, int, const char **);
495void coproc_init(void);
496void coproc_read_close(int);
497void coproc_readw_close(int);
498void coproc_write_close(int);
499int coproc_getfd(int, const char **);
500void coproc_cleanup(int);
501struct temp *maketemp(Area *, Temp_type, struct temp **);
502/* jobs.c */
503void j_init(int);
504void j_suspend(void);
505void j_exit(void);
506void j_change(void);
507int exchild(struct op *, int, volatile int *, int);
508void startlast(void);
509int waitlast(void);
510int waitfor(const char *, int *);
511int j_kill(const char *, int);
512int j_resume(const char *, int);
513int j_jobs(const char *, int, int);
514int j_njobs(void);
515void j_notify(void);
516pid_t j_async(void);
517int j_stopped_running(void);
518/* mail.c */
519void mcheck(void);
520void mcset(int64_t);
521void mbset(char *);
522void mpset(char *);
523/* main.c */
524int include(const char *, int, char **, int);
525int command(const char *, int);
526int shell(Source *volatile, int volatile);
527void unwind(int) __attribute__((__noreturn__));
528void newenv(int);
529void quitenv(struct shf *);
530void cleanup_parents_env(void);
531void cleanup_proc_env(void);
532/* misc.c */
533void setctypes(const char *, int);
534void initctypes(void);
535char * u64ton(uint64_t, int);
536char * str_save(const char *, Area *);
537char * str_nsave(const char *, int, Area *);
538int option(const char *);
539char * getoptions(void);
540void change_flag(enum sh_flag, int, int);
541int parse_args(char **, int, int *);
542int getn(const char *, int *);
543int bi_getn(const char *, int *);
544int gmatch_(const char *, const char *, int);
545int has_globbing(const char *, const char *);
546const unsigned char *pat_scan(const unsigned char *, const unsigned char *,
547 int);
548void qsortp(void **, size_t, int (*)(const void *, const void *));
549int xstrcmp(const void *, const void *);
550void ksh_getopt_reset(Getopt *, int);
551int ksh_getopt(char **, Getopt *, const char *);
552void print_value_quoted(const char *);
553void print_columns(struct shf *, int, char *(*)(void *, int, char *, int),
554 void *, int, int prefcol);
555int strip_nuls(char *, int);
556int blocking_read(int, char *, int);
557int reset_nonblock(int);
558char *ksh_get_wd(char *, int);
559/* path.c */
560int make_path(const char *, const char *, char **, XString *, int *);
561void simplify_path(char *);
562char *get_phys_path(const char *);
563void set_current_wd(char *);
564/* syn.c */
565void initkeywords(void);
566struct op * compile(Source *);
567/* trap.c */
568void inittraps(void);
569void alarm_init(void);
570Trap * gettrap(const char *, int);
571void trapsig(int);
572void intrcheck(void);
573int fatal_trap_check(void);
574int trap_pending(void);
575void runtraps(int intr);
576void runtrap(Trap *);
577void cleartraps(void);
578void restoresigs(void);
579void settrap(Trap *, char *);
580int block_pipe(void);
581void restore_pipe(int);
582int setsig(Trap *, sig_t, int);
583void setexecsig(Trap *, int);
584/* var.c */
585void newblock(void);
586void popblock(void);
587void initvar(void);
588struct tbl * global(const char *);
589struct tbl * local(const char *, bool);
590char * str_val(struct tbl *);
591int64_t intval(struct tbl *);
592int setstr(struct tbl *, const char *, int);
593struct tbl *setint_v(struct tbl *, struct tbl *, bool);
594void setint(struct tbl *, int64_t);
595int getint(struct tbl *, int64_t *, bool);
596struct tbl *typeset(const char *, int, int, int, int);
597void unset(struct tbl *, int);
598char * skip_varname(const char *, int);
599char *skip_wdvarname(const char *, int);
600int is_wdvarname(const char *, int);
601int is_wdvarassign(const char *);
602char ** makenv(void);
603void change_random(void);
604int array_ref_len(const char *);
605char * arrayname(const char *);
606void set_array(const char *, int, char **);
607/* vi.c: see edit.h */