-
Notifications
You must be signed in to change notification settings - Fork 2
/
minishell.h
429 lines (361 loc) · 10.3 KB
/
minishell.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* minishell.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jkong <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/05/20 20:36:15 by jkong #+# #+# */
/* Updated: 2022/06/28 18:41:47 by jkong ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MINISHELL_H
# define MINISHELL_H
# include <unistd.h>
# include <stdio.h>
# include <sys/types.h>
# include <readline/readline.h>
# include <readline/history.h>
# include <signal.h>
# include <stdlib.h>
# include <stdint.h>
# include <stddef.h>
extern sig_atomic_t g_exit_status;
# define HERE_DOCUMENT_MAX 16
# define NO_PIPE (-1)
# define EX_BADUSAGE 2
# define EX_NOEXEC 126
# define EX_NOTFOUND 127
enum e_char_flag_index
{
CF_META,
CF_BREAK,
CF_QUOTE,
CF_SPECIAL,
CF_EXPANSION,
CF_GLOB,
CF_BLANK,
};
typedef enum e_char_flag
{
CFV_WORD = 0,
CFV_META = 1 << CF_META,
CFV_BREAK = 1 << CF_BREAK,
CFV_QUOTE = 1 << CF_QUOTE,
CFV_SPECIAL = 1 << CF_SPECIAL,
CFV_EXPANSION = 1 << CF_EXPANSION,
CFV_GLOB = 1 << CF_GLOB,
CFV_BLANK = 1 << CF_BLANK,
} t_char_flags;
typedef enum e_token_kind
{
TK_EOF = 0,
TK_PAREN_L = '(',
TK_PAREN_R = ')',
TK_LESS = '<',
TK_GREATER = '>',
TK_OR = '|',
TK_AGAIN = 256,
TK_ERROR,
TK_UNDEFINED,
TK_WORD,
TK_LESS_LESS,
TK_GREATER_GREATER,
TK_AND_AND,
TK_OR_OR,
TK_NT_ACCEPT = 512,
TK_NT_SIMPLE_COMMAND_ELEMENT,
TK_NT_REDIRECTION,
TK_NT_SIMPLE_COMMAND,
TK_NT_REDIRECTION_LIST,
TK_NT_COMMAND,
TK_NT_SUBSHELL,
TK_NT_LIST,
TK_NT_PIPELINE,
} t_token_kind;
enum e_word_flag_index
{
WF_HAS_DOLLAR,
WF_SPLIT,
WF_PARAM,
WF_IFS,
};
typedef enum e_word_flags
{
WFV_HAS_DOLLAR = 1 << WF_HAS_DOLLAR,
WFV_SPLIT = 1 << WF_SPLIT,
WFV_PARAM = 1 << WF_PARAM,
WFV_IFS = 1 << WF_IFS,
WFV_NOQUOTE = WFV_HAS_DOLLAR | WFV_SPLIT,
WFV_DBLQUOTE = WFV_HAS_DOLLAR,
} t_word_flags;
typedef struct s_word
{
char *str;
t_word_flags flags;
} t_word;
typedef struct s_list_word
{
struct s_list_word *next;
t_word word;
} t_list_word;
typedef enum e_redirection
{
R_NONE,
R_OUTPUT_DIRECTION,
R_INPUT_DIRECTION,
R_APPENDING_TO,
R_READING_UNTIL,
} t_redirection;
typedef struct s_redirect
{
int redirectee;
t_redirection instruction;
t_word word;
} t_redirect;
typedef struct s_list_redirect
{
struct s_list_redirect *next;
t_redirect redirect;
} t_list_redirect;
/**
* BEGIN Command
*/
typedef enum e_command_type
{
CMD_NOOP,
CMD_CONNECTION,
CMD_SIMPLE,
CMD_SUBSHELL,
} t_command_type;
enum e_command_flag_index
{
CMDF_ASYNC,
};
typedef int t_command_flags;
typedef struct s_command_connection t_command_connection;
typedef struct s_simple_command t_simple_command;
typedef struct s_subshell_command t_subshell_command;
union u_command_variant
{
void *ptr;
t_command_connection *connection;
t_simple_command *simple;
t_subshell_command *subshell;
};
typedef struct s_command
{
t_command_type type;
union u_command_variant value;
} t_command;
struct s_command_connection
{
t_command_flags flags;
t_token_kind connector;
t_command first;
t_command second;
};
struct s_simple_command
{
t_command_flags flags;
t_list_word *word_list;
t_list_redirect *redirect_list;
};
struct s_subshell_command
{
t_command_flags flags;
t_command container;
t_list_redirect *redirect_list;
};
/**
* END Command
*/
enum e_parser_flag_index
{
PF_HERE_DOCUMENT,
};
# define PARSER_ACCEPT -1000
# define PARSER_ERROR -1001
typedef int t_parser_state;
typedef int t_parser_flags;
typedef enum e_parser_error
{
PE_SUCCESS,
PE_AGAIN,
PE_INCOMPLETED_PAIR,
PE_UNSUPPORTED_TOKEN,
PE_SYNTAX_ERROR,
} t_parser_error;
typedef struct s_parser_stack
{
t_parser_state state;
t_token_kind kind;
t_word word;
t_redirect redirect;
t_command command;
} t_parser_stack;
typedef struct s_parser
{
char *begin;
char *str;
t_word backup_word;
t_parser_flags flags;
t_parser_error error;
size_t stack_capacity;
t_parser_stack *stack_base;
t_parser_stack *now;
t_list_redirect *here_document[HERE_DOCUMENT_MAX];
size_t here_document_index;
} t_parser;
typedef struct s_state_info
{
t_token_kind token;
t_parser_state state;
} t_state_info;
typedef t_token_kind t_parse_func(t_parser *);
typedef struct s_list_process
{
struct s_list_process *next;
pid_t pid;
} t_list_process;
enum e_var_flag_index
{
VF_EXPORTED,
};
typedef enum e_var_flag
{
VFV_EXPORTED = 1 << VF_EXPORTED,
} t_var_flags;
enum e_file_flag_index
{
FF_DIRECTORY,
FF_HIDDEN,
};
typedef int t_file_flags;
typedef enum e_file_status
{
FS_NOT_FOUND,
FS_PROGRAM,
FS_PATHNAME,
} t_file_status;
typedef struct s_list_var
{
struct s_list_var *next;
char *name;
char *value;
t_var_flags attr;
} t_list_var;
typedef struct s_shell
{
int next_pipe;
int redir_undo[3];
t_list_process *pid_list;
t_list_var *var_list;
} t_shell;
typedef struct s_str_buf t_str_buf;
typedef struct s_str_vec t_str_vec;
void print_err(const char *format, ...);
void exit_fail(const char *s);
t_char_flags char_flags(int c);
size_t next_syntax(char *s, t_char_flags flag);
int legal_condition(const uint32_t table[8], int c);
t_token_kind read_token(t_parser *pst);
int parse(t_parser *pst);
void parser_stack_reserve(t_parser *pst, size_t n);
void parser_stack_remove_all(t_parser *pst);
t_parser_state parser_state(t_parser_state state, t_token_kind token);
t_simple_command *make_simple_command(void);
t_subshell_command *make_subshell(t_command *container);
t_command_connection *connect_command(t_command *lhs, t_command *rhs,
t_token_kind connector);
void append_word(t_list_word **list, t_word *item);
void combine_simple_command(t_simple_command *lhs,
t_simple_command *rhs);
void set_redirect(t_redirect *item, int src,
t_redirection ins, t_word *dest);
t_list_redirect *append_redirect(t_list_redirect **list,
t_redirect *item);
void subshell_apply_redirect(t_subshell_command *subshell,
t_list_redirect *r_list);
void dispose_word(t_word *item);
void dispose_redirect(t_redirect *item);
void dispose_command(t_command *item);
void push_here_document(t_parser *pst, t_list_redirect *r);
int gather_here_document(t_parser *pst, t_shell *sh);
char *read_document(char *eof, t_shell *sh);
char *read_document_pipe(char *eof, t_shell *sh);
char *get_token_str(t_token_kind token);
void swap_word(t_word *a, t_word *b);
void swap_redirect(t_redirect *a, t_redirect *b);
void swap_command(t_command *a, t_command *b);
void clear_parser_stack_item(t_parser_stack *item);
t_token_kind parser_reduce_0(t_parser *pst);
t_token_kind parser_reduce_1(t_parser *pst);
t_token_kind parser_reduce_2(t_parser *pst);
t_token_kind parser_reduce_3(t_parser *pst);
t_token_kind parser_reduce_4(t_parser *pst);
t_token_kind parser_reduce_5(t_parser *pst);
t_token_kind parser_reduce_6(t_parser *pst);
t_token_kind parser_reduce_7(t_parser *pst);
t_token_kind parser_reduce_8(t_parser *pst);
t_token_kind parser_reduce_9(t_parser *pst);
t_token_kind parser_reduce_10(t_parser *pst);
t_token_kind parser_reduce_11(t_parser *pst);
t_token_kind parser_reduce_12(t_parser *pst);
t_token_kind parser_reduce_13(t_parser *pst);
t_token_kind parser_reduce_14(t_parser *pst);
t_token_kind parser_reduce_15(t_parser *pst);
t_token_kind parser_reduce_16(t_parser *pst);
t_token_kind parser_reduce_17(t_parser *pst);
t_token_kind parser_reduce_18(t_parser *pst);
t_token_kind parser_reduce_19(t_parser *pst);
char *get_ifs(t_list_var *v_list);
int get_exit_status(int status);
int execute_command(t_shell *sh, t_command *cmd,
int pipe_in, int pipe_out);
int execute_simple_command(t_shell *sh, t_command *cmd,
int pipe_in, int pipe_out);
int execute_pipeline(t_shell *sh, t_command *cmd,
int pipe_in, int pipe_out);
void do_piping(int pipe_in, int pipe_out, int pipe_next);
pid_t make_child(t_shell *sh);
int wait_for(t_shell *sh, pid_t pid);
int do_redirections(t_list_redirect *r_list, t_shell *sh);
void add_undo_redirects(t_shell *sh);
void cleanup_redirects(t_shell *sh);
char *get_var(t_list_var *list, char *name);
void put_var(t_list_var **list_ptr, char *name, char *value,
t_var_flags attr);
void unset_var(t_list_var **list_ptr, char *name);
int is_legal_variable(const char *s, size_t *index_ptr);
char *alloc_str_pair(const char *s, char **val_ptr,
char delim);
void strvec_to_var_list(t_list_var **list_ptr, char **arr,
t_var_flags attr);
char **var_list_to_strvec(t_list_var *list,
t_var_flags attr);
void dispose_var_list(t_list_var *list);
t_list_var *clone_var_list(t_list_var *list);
t_list_var *sort_var_list(t_list_var *list);
void append_word_list(t_list_word **list_ptr, char *str,
t_word_flags flags);
void delete_word_list(t_list_word *list);
void singleton_word_list(t_list_word *ptr, t_word *word);
char *resolve_path(char *path, char *name);
t_file_status file_status(char *path);
int is_absolute_path(char *name, t_file_status type);
char *find_path(char *var, char *name, t_file_status type,
int empty);
t_list_word *expand_map(t_list_word *w_list, t_list_var *v_list,
int mode);
char **expand_collect(t_list_word *w_list, char *path);
char *expand_collect_standalone(t_list_word *w_list);
char **glob_to_strvec(const char *path, const char *pattern);
char **word_expand(t_shell *sh, t_list_word *w_list);
char *redir_expand(t_shell *sh, t_word *word);
void heredoc_eof_expand(t_word *word);
char *heredoc_expand(t_shell *sh, t_word *word,
size_t *len_ptr);
void set_signal_handler(int state);
void on_signal(void);
#endif