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