5 Command parsing results in "pipe" structures. "Pipe" structure
6 does not always correspond to what sh language calls "pipe",
7 it also controls execution of if, while, etc statements.
10 smallint res_word - "none" for normal commands,
11 "if" for if condition etc
12 struct child_prog progs[] - array of commands in pipe
13 smallint followup - how this pipe is related to next: is it
14 "pipe; pipe", "pipe & pipe" "pipe && pipe",
17 Blocks of commands { pipe; pipe; } and (pipe; pipe) are represented
18 as one pipe struct with one progs[0] element which is a "group" -
19 struct child_prog can contain a list of pipes. Sometimes these
20 "groups" are created implicitly, e.g. every control
21 statement (if, while, etc) sits inside its own "pipe" struct).
23 res_word controls statement execution. Examples:
26 pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
27 pipe 1 res_word=NONE followup=1 SEQ
29 "echo foo || echo bar" -
30 pipe 0 res_word=NONE followup=OR prog[0] 'echo' 'foo'
31 pipe 1 res_word=NONE followup=SEQ prog[0] 'echo' 'bar'
32 pipe 2 res_word=NONE followup=SEQ
34 "if true; then echo Hello; true; fi" -
35 res_word=NONE followup=SEQ
37 pipe 0 res_word=IF followup=SEQ prog[0] 'true'
38 pipe 1 res_word=THEN followup=SEQ prog[0] 'echo' 'Hello'
39 pipe 2 res_word=THEN followup=SEQ prog[0] 'true'
40 pipe 3 res_word=FI followup=SEQ
41 pipe 4 res_word=NONE followup=(null)
42 pipe 1 res_word=NONE followup=SEQ
44 "if true; then { echo Hello; true; }; fi" -
45 pipe 0 res_word=NONE followup=SEQ
47 pipe 0 res_word=IF followup=SEQ prog[0] 'true'
48 pipe 1 res_word=THEN followup=SEQ
50 pipe 0 res_word=NONE followup=SEQ prog[0] 'echo' 'Hello'
51 pipe 1 res_word=NONE followup=SEQ prog[0] 'true'
52 pipe 2 res_word=NONE followup=SEQ
53 pipe 2 res_word=NONE followup=(null)
54 pipe 1 res_word=NONE followup=1 SEQ
56 "for v in a b; do echo $v; true; done" -
57 pipe 0 res_word=NONE followup=SEQ
59 pipe 0 res_word=FOR followup=SEQ prog[0] 'v'
60 pipe 1 res_word=IN followup=SEQ prog[0] 'a' 'b'
61 pipe 2 res_word=DO followup=SEQ prog[0] 'echo' '$v'
62 pipe 3 res_word=DO followup=SEQ prog[0] 'true'
63 pipe 4 res_word=DONE followup=SEQ
64 pipe 5 res_word=NONE followup=(null)
65 pipe 1 res_word=NONE followup=SEQ
67 Note how "THEN" and "DO" does not just mark the first pipe,
68 it "sticks" to all pipes in the body. This is used when
69 hush executes parsed pipes.
71 Dummy trailing pipes with no commands are artifacts of imperfect
72 parsing algorithm - done_pipe() appends new pipe struct beforehand
73 and last one ends up empty and unused.
78 This is how hush runs commands:
80 /* callsite: process_command_subs */
81 generate_stream_from_list(struct pipe *head) - handles `cmds`
85 redirect pipe output to stdout
86 _exit(run_list(head)); /* leaks memory */
88 return UNIX pipe's output fd
89 /* head is freed by the caller */
91 /* callsite: parse_and_run_stream */
92 run_and_free_list(struct pipe *)
93 run_list(struct pipe *)
94 free_pipe_list(struct pipe *)
96 /* callsites: generate_stream_from_list, run_and_free_list, pseudo_exec, run_pipe */
97 run_list(struct pipe *) - handles "cmd; cmd2 && cmd3", while/for/do loops
98 run_pipe - for every pipe in list
100 /* callsite: run_list */
101 run_pipe - runs "cmd1 | cmd2 | cmd3 [&]"
102 run_list - used if only one cmd and it is of the form "{cmds;}"
103 forks for every cmd if more than one cmd or if & is there
104 pseudo_exec - runs each "cmdN" (handles builtins etc)
106 /* callsite: run_pipe */
107 pseudo_exec - runs "cmd" (handles builtins etc)
108 exec - execs external programs
109 run_list - used if cmdN is "(cmds)" or "{cmds;}"
110 /* problem: putenv's malloced strings into environ -
111 ** with vfork they will leak into parent process
113 /* problem with ENABLE_FEATURE_SH_STANDALONE:
114 ** run_applet_no_and_exit(a, argv) uses exit - this can interfere
115 ** with vfork - switch to _exit there?