1 /***********************************************************************
2  *                                                                      *
3  *               This software is part of the ast package               *
4  *          Copyright (c) 1982-2014 AT&T Intellectual Property          *
5  *                      and is licensed under the                       *
6  *                 Eclipse Public License, Version 1.0                  *
7  *                    by AT&T Intellectual Property                     *
8  *                                                                      *
9  *                A copy of the License is available at                 *
10  *          http://www.eclipse.org/org/documents/epl-v10.html           *
11  *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12  *                                                                      *
13  *              Information and Software Systems Research               *
14  *                            AT&T Research                             *
15  *                           Florham Park NJ                            *
16  *                                                                      *
17  *                    David Korn <dgkorn@gmail.com>                     *
18  *                                                                      *
19  ***********************************************************************/
20 //
21 // David Korn
22 // AT&T Labs
23 //
24 // Shell interface private definitions.
25 //
26 #ifndef _DEFS_H
27 #define _DEFS_H 1
28 
29 // This include shouldn't be necessary but without it compilation errors occur in modules like
30 // lex.c. But if we include it in that module IWYU complains it isn't needed.
31 #include <ctype.h>
32 
33 #include "argnod.h"
34 #include "fault.h"
35 #include "history.h"
36 #include "name.h"
37 
38 #define Empty ((char *)(e_sptbnl + 3))
39 #define env_change() (++ast.env_serial)
40 #define Env_t void
41 #define sh_envput(e, p) env_change()
42 #define env_delete(e, p) env_change()
43 
44 // Shell options.
45 typedef uint_fast64_t Shopt_t_data_t;
46 typedef struct {
47     Shopt_t_data_t v[(256 / 8) / sizeof(Shopt_t_data_t)];
48 } Shopt_t;
49 
50 extern char *sh_getenv(const char *);
51 extern char *sh_setenviron(const char *);
52 
53 //
54 // Note that the first few fields have to be the same as for Shscope_t in <shell.h>.
55 //
56 struct sh_scoped {
57     struct sh_scoped *prevst;  // pointer to previous state
58     int dolc;
59     char **dolv;
60     char *cmdname;
61     char *filename;
62     char *funname;
63     int64_t lineno;
64     Dt_t *save_tree;         // var_tree for calling function
65     struct sh_scoped *self;  // pointer to copy of this scope
66 
67     Dt_t *var_local;         // local level variables for name()
68     struct slnod *staklist;  // link list of function stacks
69     int states;
70     int breakcnt;
71     int execbrk;
72     int loopcnt;
73     int firstline;
74     int32_t optindex;
75     int32_t optnum;
76     int32_t tmout;  // value for TMOUT
77     short optchar;
78     short opterror;
79     int ioset;
80     unsigned short trapmax;
81     char *trap[SH_DEBUGTRAP + 1];
82     char **otrap;
83     char **trapcom;
84     char **otrapcom;
85     void *timetrap;
86     struct Ufunction *real_fun;  // current 'function name' function
87     int repl_index;
88     char *repl_arg;
89 };
90 
91 struct limits {
92     long arg_max;   // max arg+env exec() size
93     int open_max;   // maximum number of file descriptors
94     int child_max;  // maximum number of children
95 };
96 
97 #undef _FPATH  // Cygwin defines _FPATH in /usr/include/sys/_default_fcntl.h
98 
99 // This structure must be kept in sync with the shtab_variables[] array in data/variables.c.
100 // All structure member names have a leading underscore to avoid conflicts with #define symbols;
101 // e.g., LC_ALL.
102 struct bltin_vars {
103     Namval_t *_sh;                 // ${.sh}
104     Namval_t *_sh_command;         // ${.sh.command}
105     Namval_t *_sh_dollar;          // ${.sh.dollar}
106     Namval_t *_sh_edchar;          // ${.sh.dollar}
107     Namval_t *_sh_edcol;           // ${.sh.dollar}
108     Namval_t *_sh_edmode;          // ${.sh.dollar}
109     Namval_t *_sh_edtext;          // ${.sh.dollar}
110     Namval_t *_sh_file;            // ${.sh.dollar}
111     Namval_t *_sh_fun;             // ${.sh.dollar}
112     Namval_t *_sh_install_prefix;  // ${.sh.dollar}
113     Namval_t *_sh_level;           // ${.sh.dollar}
114     Namval_t *_sh_lineno;          // ${.sh.dollar}
115     Namval_t *_sh_match;           // ${.sh.dollar}
116     Namval_t *_sh_math;            // ${.sh.dollar}
117     Namval_t *_sh_name;            // ${.sh.dollar}
118     Namval_t *_sh_op_astbin;       // ${.sh.dollar}
119     Namval_t *_sh_pgrp;            // ${.sh.dollar}
120     Namval_t *_sh_pool;            // ${.sh.dollar}
121     Namval_t *_sh_pwdfd;           // ${.sh.dollar}
122     Namval_t *_sh_sig;             // ${.sh.dollar}
123     Namval_t *_sh_stats;           // ${.sh.dollar}
124     Namval_t *_sh_subscript;       // ${.sh.dollar}
125     Namval_t *_sh_subshell;        // ${.sh.dollar}
126     Namval_t *_sh_value;           // ${.sh.dollar}
127     Namval_t *_sh_version;         // ${.sh.dollar}
128     Namval_t *_CDPATH;
129     Namval_t *_COLUMNS;
130     Namval_t *_COMPREPLY;
131     Namval_t *_COMP_CWORD;
132     Namval_t *_COMP_KEY;
133     Namval_t *_COMP_LINE;
134     Namval_t *_COMP_POINT;
135     Namval_t *_COMP_TYPE;
136     Namval_t *_COMP_WORDBREAKS;
137     Namval_t *_COMP_WORDS;
138     Namval_t *_EDITOR;
139     Namval_t *_ENV;
140     Namval_t *_FCEDIT;
141     Namval_t *_FIGNORE;
142     Namval_t *_FPATH;
143     Namval_t *_HISTCMD;
144     Namval_t *_HISTEDIT;
145     Namval_t *_HISTFILE;
146     Namval_t *_HISTSIZE;
147     Namval_t *_HOME;
148     Namval_t *_IFS;
149     Namval_t *_JOBMAX;
150     Namval_t *_KSH_VERSION;
151     Namval_t *_LANG;
152     Namval_t *_LC_ALL;
153     Namval_t *_LC_COLLATE;
154     Namval_t *_LC_CTYPE;
155     Namval_t *_LC_MESSAGES;
156     Namval_t *_LC_NUMERIC;
157     Namval_t *_LC_TIME;
158     Namval_t *_LINENO;
159     Namval_t *_LINES;
160     Namval_t *_MAIL;
161     Namval_t *_MAILCHECK;
162     Namval_t *_MAILPATH;
163     Namval_t *_OLDPWD;
164     Namval_t *_OPTARG;
165     Namval_t *_OPTIND;
166     Namval_t *_PATH;
167     Namval_t *_PPID;
168     Namval_t *_PS1;
169     Namval_t *_PS2;
170     Namval_t *_PS3;
171     Namval_t *_PS4;
172     Namval_t *_PWD;
173     Namval_t *_RANDOM;
174     Namval_t *_REPLY;
175     Namval_t *_SECONDS;
176     Namval_t *_SHELL;
177     Namval_t *_SHLVL;
178     Namval_t *_SH_OPTIONS;
179     Namval_t *_TMOUT;
180     Namval_t *_VISUAL;
181     Namval_t *_underscore;  // $_
182 };
183 
184 struct shared {
185     struct limits lim;
186     uid_t userid;
187     uid_t euserid;
188     gid_t groupid;
189     gid_t egroupid;
190     pid_t pid;
191     pid_t ppid;
192     unsigned char sigruntime[2];
193     struct bltin_vars vars;
194     Namval_t *bltin_cmds;
195     History_t *hist_ptr;
196     char *shpath;
197     char *user;
198     const char **sigmsg;
199     char *rcfile;
200     char **login_files;
201     Edit_t *ed_context;
202     void *init_context;
203     void *job_context;
204     int *stats;
205     int sigmax;
206     int nforks;
207     int shtype;
208 };
209 
210 #include "shell.h"
211 #include "shtable.h"
212 
213 // Error exits from various parts of shell.
214 #define exitset(shp) (shp->savexit = shp->exitval)
215 
216 #ifndef SH_DICT
217 #define SH_DICT (void *)e_dict
218 #endif
219 
220 #define SH_CMDLIB_DIR "/opt/ast/bin"
221 
222 // States. Low numbered states are same as options.
223 #define SH_NOFORK 0      // set when fork not necessary
224 #define SH_FORKED 7      // set when process has been forked
225 #define SH_PROFILE 8     // set when processing profile
226 #define SH_NOALIAS 9     // do not expand non-exported aliases
227 #define SH_NOTRACK 10    // set to disable sftrack() function
228 #define SH_STOPOK 11     // set for stopable builtins
229 #define SH_GRACE 12      // set for timeout grace period
230 #define SH_TIMING 13     // set while timing pipelines
231 #define SH_DEFPATH 14    // set when using default path
232 #define SH_INIT 15       // set when initializing the shell
233 #define SH_TTYWAIT 16    // waiting for keyboard input
234 #define SH_FCOMPLETE 17  // set for filename completion
235 #define SH_PREINIT 18    // set with SH_INIT before parsing options
236 #define SH_COMPLETE 19   // set for command completion
237 #define SH_IOPROMPT 20   // set when prompting
238 
239 #define SH_BASH 41
240 #define SH_BRACEEXPAND 42
241 #define SH_POSIX 46
242 #define SH_MULTILINE 47
243 
244 #define SH_NOUSRPROFILE 79
245 #define SH_LOGIN_SHELL 67
246 #define SH_COMMANDLINE 0x100
247 #define SH_BASHEXTRA 0x200
248 #define SH_BASHOPT 0x400
249 
250 #define SH_ID "ksh"  // ksh id
251 #define SH_STD "sh"  // standard sh id
252 
253 // Defines for sh_type().
254 #define SH_TYPE_SH 001
255 #define SH_TYPE_KSH 002
256 #define SH_TYPE_BASH 004
257 #define SH_TYPE_LOGIN 010
258 #define SH_TYPE_PROFILE 020
259 #define SH_TYPE_RESTRICTED 040
260 
261 #if SHOPT_BASH
262 // Define for all the bash options.
263 #define SH_CDABLE_VARS 51
264 #define SH_CDSPELL 52
265 #define SH_CHECKHASH 53
266 #define SH_CHECKWINSIZE 54
267 #define SH_CMDHIST 55
268 #define SH_DOTGLOB 56
269 #define SH_EXECFAIL 57
270 #define SH_EXPAND_ALIASES 58
271 #define SH_EXTGLOB 59
272 #define SH_HOSTCOMPLETE 63
273 #define SH_HUPONEXIT 64
274 #define SH_INTERACTIVE_COMM 65
275 #define SH_LITHIST 66
276 #define SH_MAILWARN 68
277 #define SH_NOEMPTYCMDCOMPL 69
278 #define SH_NOCASEGLOB 70
279 #define SH_NULLGLOB 71
280 #define SH_PHYSICAL 45
281 #define SH_PROGCOMP 72
282 #define SH_PROMPTVARS 73
283 #define SH_RESTRICTED2 74
284 #define SH_SHIFT_VERBOSE 75
285 #define SH_SOURCEPATH 76
286 #define SH_XPG_ECHO 77
287 #define SH_LASTPIPE 78
288 #endif
289 
290 #define SH_HISTAPPEND 60
291 #define SH_HISTEXPAND 43
292 #define SH_HISTORY2 44
293 #define SH_HISTREEDIT 61
294 #define SH_HISTVERIFY 62
295 
296 #ifndef PIPE_BUF
297 #define PIPE_BUF 512
298 #endif
299 
300 #define MATCH_MAX 64
301 
302 #define SH_READEVAL 0x4000  // for sh_eval
303 #define SH_FUNEVAL 0x10000  // for sh_eval for function load
304 
305 extern struct shared *shgd;
306 extern void sh_outname(Shell_t *, Sfio_t *, char *, int);
307 extern void sh_applyopts(Shell_t *, Shopt_t);
308 extern char **sh_argbuild(Shell_t *, int *, const struct comnod *, int);
309 extern struct dolnod *sh_argfree(Shell_t *, struct dolnod *);
310 extern struct dolnod *sh_argnew(Shell_t *, char *[], struct dolnod **);
311 extern struct Shell_arg *sh_argopen(Shell_t *);
312 extern struct argnod *sh_argprocsub(Shell_t *, struct argnod *);
313 extern void sh_argreset(Shell_t *, struct dolnod *, struct dolnod *);
314 extern Namval_t *sh_assignok(Namval_t *, int);
315 extern struct dolnod *sh_arguse(Shell_t *);
316 extern char *sh_checkid(char *, char *);
317 extern void sh_chktrap(Shell_t *);
318 extern void sh_deparse(Sfio_t *, const Shnode_t *, int);
319 extern int sh_debug(Shell_t *shp, const char *, const char *, const char *, char *const[], int);
320 extern int sh_echolist(Shell_t *, Sfio_t *, int, char **);
321 extern struct argnod *sh_endword(Shell_t *, int);
322 extern char **sh_envgen(Shell_t *);
323 extern void sh_envnolocal(Namval_t *, void *);
324 extern Sfdouble_t sh_arith(Shell_t *, const char *);
325 extern void *sh_arithcomp(Shell_t *, char *);
326 extern pid_t sh_fork(Shell_t *, int, int *);
327 extern pid_t _sh_fork(Shell_t *, pid_t, int, int *);
328 extern char *sh_mactrim(Shell_t *, char *, int);
329 extern int sh_macexpand(Shell_t *, struct argnod *, struct argnod **, int);
330 extern bool sh_macfun(Shell_t *, const char *, int);
331 extern void sh_machere(Shell_t *, Sfio_t *, Sfio_t *, char *);
332 extern Mac_t *sh_macopen(Shell_t *);
333 extern char *sh_macpat(Shell_t *, struct argnod *, int);
334 extern Sfdouble_t sh_mathfun(Shell_t *, void *, int, Sfdouble_t *);
335 extern int sh_outtype(Shell_t *, Sfio_t *);
336 extern char *sh_mactry(Shell_t *, char *);
337 extern int sh_mathstd(const char *);
338 extern void sh_printopts(Shell_t *, Shopt_t, int, Shopt_t *);
339 extern int sh_readline(Shell_t *, char **, void *, volatile int, int, ssize_t, long);
340 extern Sfio_t *sh_sfeval(const char **);
341 extern char *sh_fmtstr(const char *, int);
342 extern void sh_setmatch(Shell_t *, const char *, int, int, int[], int);
343 extern Dt_t *sh_subaliastree(Shell_t *, int);
344 extern void sh_scope(Shell_t *, struct argnod *, int);
345 extern Namval_t *sh_scoped(Shell_t *, Namval_t *);
346 extern Namval_t **sh_setlist(Shell_t *, struct argnod *, nvflag_t, Namval_t *);
347 extern void sh_sigclear(Shell_t *, int);
348 extern void sh_sigdone(Shell_t *);
349 extern void sh_sigreset(Shell_t *, int);
350 extern void sh_sigtrap(Shell_t *, int);
351 extern void sh_siglist(Shell_t *, Sfio_t *, int);
352 extern Dt_t *sh_subfuntree(Shell_t *, bool);
353 extern void sh_subjobcheck(pid_t);
354 extern int sh_subsavefd(int);
355 extern void sh_subtmpfile(Shell_t *);
356 extern char *sh_substitute(Shell_t *, const char *, const char *, const char *);
357 extern const char *_sh_translate(const char *);
358 extern bool sh_trace(Shell_t *, char *[], int);
359 extern void sh_trim(char *);
360 extern int sh_type(const char *);
361 extern void sh_unscope(Shell_t *);
362 extern Namval_t *sh_fsearch(Shell_t *, const char *, nvflag_t);
363 extern int sh_diropenat(Shell_t *, int, const char *);
364 extern int sh_strchr(const char *, const char *, size_t);
365 
366 // These two magic pointers are used to distinguish the purpose of the `extra` parameter of the
367 // `sh_addbuiltin()` function. It should be one of these two values, NULL, or a `Namfun_t*`.
368 extern void *const builtin_delete;
369 extern void *const builtin_disable;
370 
371 #ifndef ERROR_dictionary
372 #define ERROR_dictionary(s) (s)
373 #endif
374 #define sh_translate(s) _sh_translate(ERROR_dictionary(s))
375 
376 #define WBITS (sizeof(Shopt_t_data_t) * 8)
377 #define WMASK (0xff)
378 
379 #define is_option(s, x) (((s)->v[((x)&WMASK) / WBITS] & (1ULL << ((x) % WBITS))) ? true : false)
380 #define on_option(s, x) ((void)((s)->v[((x)&WMASK) / WBITS] |= (1ULL << ((x) % WBITS))))
381 #define off_option(s, x) ((void)((s)->v[((x)&WMASK) / WBITS] &= ~(1ULL << ((x) % WBITS))))
382 
383 #define sh_isoption(shp, x) is_option(&(shp)->options, (x))
384 #define sh_onoption(shp, x) on_option(&(shp)->options, (x))
385 #define sh_offoption(shp, x) off_option(&(shp)->options, (x))
386 
387 #define sh_state(x) (1 << (x))
388 #define sh_isstate(shp, x) ((shp)->st.states & sh_state(x))
389 #define sh_onstate(shp, x) ((shp)->st.states |= sh_state(x))
390 #define sh_offstate(shp, x) ((shp)->st.states &= ~sh_state(x))
391 #define sh_getstate(shp) ((shp)->st.states)
392 #define sh_setstate(shp, x) ((shp)->st.states = (x))
393 
394 extern int32_t sh_mailchk;
395 extern const char e_dict[];
396 
397 // sh_printopts() mode flags -- set --[no]option by default.
398 #define PRINT_VERBOSE 0x01    // option on|off list
399 #define PRINT_ALL 0x02        // list unset options too
400 #define PRINT_NO_HEADER 0x04  // omit listing header
401 #define PRINT_SHOPT 0x08      // shopt -s|-u
402 #define PRINT_TABLE 0x10      // table of all options
403 
404 // Performance statistics.
405 #define STAT_ARGHITS 0
406 #define STAT_ARGEXPAND 1
407 #define STAT_COMSUB 2
408 #define STAT_FORKS 3
409 #define STAT_FUNCT 4
410 #define STAT_GLOBS 5
411 #define STAT_READS 6
412 #define STAT_NVHITS 7
413 #define STAT_NVOPEN 8
414 #define STAT_PATHS 9
415 // #define STAT_SVFUNCT 10
416 #define STAT_SCMDS 11
417 #define STAT_SPAWN 12
418 #define STAT_SUBSHELL 13
419 extern const Shtable_t shtab_stats[];
420 #define sh_stats(x) (shgd->stats[(x)]++)
421 extern const Shtable_t shtab_siginfo[];
422 
423 #define timeofday(p) gettimeofday(p, NULL)
424 
425 // sigqueue() may not be available on some platforms (e.g., macOS) or doesn't work on others
426 // (e.g., WSL). So provide a fallback that mostly does what we need.
427 #if !_lib_sigqueue || _WSL_
sigqueue_fallback(pid_t pid,int sig,const union sigval sig_val)428 static inline int sigqueue_fallback(pid_t pid, int sig, const union sigval sig_val) {
429     UNUSED(sig_val);
430     return kill(pid, sig);
431 }
432 #define sigqueue sigqueue_fallback
433 #endif
434 
435 #define sh_sigaction(s, action)         \
436     do {                                \
437         sigset_t ss;                    \
438         sigemptyset(&ss);               \
439         sigaddset(&ss, (s));            \
440         sigprocmask(action, &ss, NULL); \
441     } while (0)
442 
443 #ifndef CLD_EXITED
444 #define CLD_EXITED 1
445 #define CLD_KILLED 2
446 #define CLD_DUMPED 3
447 #define CLD_STOPPED 4
448 #define CLD_CONTINUED 5
449 #endif
450 
451 // TODO: Should this be removed when we move to standard locale functions?
getdecimal()452 static inline int getdecimal() {
453     struct lconv *lp;
454     lp = localeconv();
455     // cppcheck-suppress identicalInnerCondition
456     if (lp && lp->decimal_point && *lp->decimal_point) return *lp->decimal_point;
457     return '.';
458 }
459 
460 #endif  // _DEFS_H
461