chiark / gitweb /
acdfec0a07ebb2236cb431d883b094bf3aa9d2e2
[elogind.git] / src / basic / proc-cmdline.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <string.h>
23
24 #include "alloc-util.h"
25 #include "extract-word.h"
26 #include "fileio.h"
27 #include "macro.h"
28 #include "parse-util.h"
29 #include "proc-cmdline.h"
30 #include "process-util.h"
31 //#include "special.h"
32 #include "string-util.h"
33 #include "util.h"
34 #include "virt.h"
35
36 int proc_cmdline(char **ret) {
37         const char *e;
38         assert(ret);
39
40         /* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */
41         e = secure_getenv("SYSTEMD_PROC_CMDLINE");
42         if (e) {
43                 char *m;
44
45                 m = strdup(e);
46                 if (!m)
47                         return -ENOMEM;
48
49                 *ret = m;
50                 return 0;
51         }
52
53         if (detect_container() > 0)
54                 return get_process_cmdline(1, 0, false, ret);
55         else
56                 return read_one_line_file("/proc/cmdline", ret);
57 }
58
59 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data),
60                        void *data,
61                        bool strip_prefix) {
62         _cleanup_free_ char *line = NULL;
63         const char *p;
64         int r;
65
66         assert(parse_item);
67
68         r = proc_cmdline(&line);
69         if (r < 0)
70                 return r;
71
72         p = line;
73         for (;;) {
74                 _cleanup_free_ char *word = NULL;
75                 char *value = NULL, *unprefixed;
76
77                 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
78                 if (r < 0)
79                         return r;
80                 if (r == 0)
81                         break;
82
83                 /* Filter out arguments that are intended only for the
84                  * initrd */
85                 unprefixed = startswith(word, "rd.");
86                 if (unprefixed && !in_initrd())
87                         continue;
88
89                 value = strchr(word, '=');
90                 if (value)
91                         *(value++) = 0;
92
93                 r = parse_item(strip_prefix && unprefixed ? unprefixed : word, value, data);
94                 if (r < 0)
95                         return r;
96         }
97
98         return 0;
99 }
100
101 int get_proc_cmdline_key(const char *key, char **value) {
102         _cleanup_free_ char *line = NULL, *ret = NULL;
103         bool found = false;
104         const char *p;
105         int r;
106
107         assert(key);
108
109         r = proc_cmdline(&line);
110         if (r < 0)
111                 return r;
112
113         p = line;
114         for (;;) {
115                 _cleanup_free_ char *word = NULL;
116                 const char *e;
117
118                 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
119                 if (r < 0)
120                         return r;
121                 if (r == 0)
122                         break;
123
124                 /* Filter out arguments that are intended only for the
125                  * initrd */
126                 if (!in_initrd() && startswith(word, "rd."))
127                         continue;
128
129                 if (value) {
130                         e = startswith(word, key);
131                         if (!e)
132                                 continue;
133
134                         r = free_and_strdup(&ret, e);
135                         if (r < 0)
136                                 return r;
137
138                         found = true;
139                 } else {
140                         if (streq(word, key))
141                                 found = true;
142                 }
143         }
144
145         if (value) {
146                 *value = ret;
147                 ret = NULL;
148         }
149
150         return found;
151
152 }
153
154 #if 0 /// UNNEEDED by elogind
155 int shall_restore_state(void) {
156         _cleanup_free_ char *value = NULL;
157         int r;
158
159         r = get_proc_cmdline_key("systemd.restore_state=", &value);
160         if (r < 0)
161                 return r;
162         if (r == 0)
163                 return true;
164
165         return parse_boolean(value);
166 }
167
168 static const char * const rlmap[] = {
169         "emergency", SPECIAL_EMERGENCY_TARGET,
170         "-b",        SPECIAL_EMERGENCY_TARGET,
171         "rescue",    SPECIAL_RESCUE_TARGET,
172         "single",    SPECIAL_RESCUE_TARGET,
173         "-s",        SPECIAL_RESCUE_TARGET,
174         "s",         SPECIAL_RESCUE_TARGET,
175         "S",         SPECIAL_RESCUE_TARGET,
176         "1",         SPECIAL_RESCUE_TARGET,
177         "2",         SPECIAL_MULTI_USER_TARGET,
178         "3",         SPECIAL_MULTI_USER_TARGET,
179         "4",         SPECIAL_MULTI_USER_TARGET,
180         "5",         SPECIAL_GRAPHICAL_TARGET,
181         NULL
182 };
183
184 static const char * const rlmap_initrd[] = {
185         "emergency", SPECIAL_EMERGENCY_TARGET,
186         "rescue",    SPECIAL_RESCUE_TARGET,
187         NULL
188 };
189
190 const char* runlevel_to_target(const char *word) {
191         size_t i;
192         const char * const *rlmap_ptr = in_initrd() ? rlmap_initrd
193                                                     : rlmap;
194
195         if (!word)
196                 return NULL;
197
198         if (in_initrd() && (word = startswith(word, "rd.")) == NULL)
199                 return NULL;
200
201         for (i = 0; rlmap_ptr[i] != NULL; i += 2)
202                 if (streq(word, rlmap_ptr[i]))
203                         return rlmap_ptr[i+1];
204
205         return NULL;
206 }
207 #endif // 0