1#include "internal.h"
2
3static CMDLINE_DECLARE_STRING(
4 root, global.root_partition,
5 .desc = "Root filesystem partition to mount at boot", .arg = "<device>",
6 .default_val = NULL, .flags = CMDLINE_ENTRY_REQUIRED);
7
8static const char *parse_escaped_string(const char *input, char *buf,
9 size_t max_len, bool in_quotes) {
10 if (!buf || max_len == 0)
11 return input;
12 size_t idx = 0;
13
14 while (*input) {
15 if (*input == '\\' && *(input + 1) != '\0') {
16 input++;
17 char escaped = *input;
18 switch (escaped) {
19 case 'n': escaped = '\n'; break;
20 case 't': escaped = '\t'; break;
21 case 'r': escaped = '\r'; break;
22 default: break;
23 }
24 if (idx < max_len - 1)
25 buf[idx++] = escaped;
26 input++;
27 continue;
28 }
29
30 if (in_quotes) {
31 if (*input == '"') {
32 input++; /* consume closing quote */
33 break;
34 }
35 } else {
36 if (*input == ' ' || *input == '\t')
37 break;
38 }
39
40 if (idx < max_len - 1)
41 buf[idx++] = *input;
42 input++;
43 }
44
45 buf[idx] = '\0';
46 return input;
47}
48
49static const char *parse_next_token(const char *input,
50 char var_buf[MAX_VAR_LEN],
51 char val_buf[MAX_VAL_LEN]) {
52 var_buf[0] = '\0';
53 val_buf[0] = '\0';
54
55 while (*input == ' ' || *input == '\t')
56 input++;
57
58 if (*input == '\0')
59 return input;
60
61 const char *var_start = input;
62 while (*input && *input != '=' && *input != ' ' && *input != '\t')
63 input++;
64
65 if (*input != '=')
66 return input;
67
68 const char *var_end = input;
69 input++; /* consume '=' */
70
71 while (*input == ' ' || *input == '\t')
72 input++;
73
74 size_t var_len = (size_t) (var_end - var_start);
75 if (var_len >= MAX_VAR_LEN)
76 var_len = MAX_VAR_LEN - 1;
77 memcpy(var_buf, var_start, var_len);
78 var_buf[var_len] = '\0';
79
80 bool is_quoted = (*input == '"');
81 if (is_quoted)
82 input++; /* consume opening quote */
83
84 return parse_escaped_string(input, buf: val_buf, MAX_VAL_LEN, in_quotes: is_quoted);
85}
86
87void cmdline_parse(const char *input) {
88 char var_buf[MAX_VAR_LEN];
89 char val_buf[MAX_VAL_LEN];
90
91 cmdline_check_for_duplicates();
92 cmdline_assign_all_args();
93 cmdline_validate_defaults();
94
95 while (*input) {
96 input = parse_next_token(input, var_buf, val_buf);
97 if (var_buf[0] != '\0')
98 cmdline_dispatch(var: var_buf, val: val_buf);
99 }
100
101 cmdline_apply_defaults();
102 cmdline_check_for_unfilled();
103 cmdline_print_all();
104}
105