chiark / gitweb /
cryptsetup: minimal cryptsetup unit generator
[elogind.git] / src / condition.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "util.h"
28 #include "condition.h"
29
30 Condition* condition_new(ConditionType type, const char *parameter, bool negate) {
31         Condition *c;
32
33         c = new0(Condition, 1);
34         c->type = type;
35         c->negate = negate;
36
37         if (!(c->parameter = strdup(parameter))) {
38                 free(c);
39                 return NULL;
40         }
41
42         return c;
43 }
44
45 void condition_free(Condition *c) {
46         assert(c);
47
48         free(c->parameter);
49         free(c);
50 }
51
52 void condition_free_list(Condition *first) {
53         Condition *c, *n;
54
55         LIST_FOREACH_SAFE(conditions, c, n, first)
56                 condition_free(c);
57 }
58
59 static bool test_kernel_command_line(const char *parameter) {
60         char *line, *w, *state, *word = NULL;
61         bool equal;
62         int r;
63         size_t l, pl;
64         bool found = false;
65
66         if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
67                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
68                 return false;
69         }
70
71         equal = !!strchr(parameter, '=');
72         pl = strlen(parameter);
73
74         FOREACH_WORD_QUOTED(w, l, line, state) {
75
76                 free(word);
77                 if (!(word = strndup(w, l)))
78                         break;
79
80                 if (equal) {
81                         if (streq(word, parameter)) {
82                                 found = true;
83                                 break;
84                         }
85                 } else {
86                         if (startswith(word, parameter) && (word[pl] == '=' || word[pl] == 0)) {
87                                 found = true;
88                                 break;
89                         }
90                 }
91
92         }
93
94         free(word);
95         free(line);
96
97         return found;
98 }
99
100 bool condition_test(Condition *c) {
101         assert(c);
102
103         switch(c->type) {
104
105         case CONDITION_PATH_EXISTS:
106                 return (access(c->parameter, F_OK) >= 0) == !c->negate;
107
108         case CONDITION_KERNEL_COMMAND_LINE:
109                 return !!test_kernel_command_line(c->parameter) == !c->negate;
110
111         default:
112                 assert_not_reached("Invalid condition type.");
113         }
114 }
115
116 bool condition_test_list(Condition *first) {
117         Condition *c;
118
119         /* If the condition list is empty, then it is true */
120         if (!first)
121                 return true;
122
123         /* Otherwise, if any of the conditions apply we return true */
124         LIST_FOREACH(conditions, c, first)
125                 if (condition_test(c))
126                         return true;
127
128         return false;
129 }
130
131 void condition_dump(Condition *c, FILE *f, const char *prefix) {
132         assert(c);
133         assert(f);
134
135         if (!prefix)
136                 prefix = "";
137
138         fprintf(f,
139                 "%s%s: %s%s\n",
140                 prefix,
141                 condition_type_to_string(c->type),
142                 c->negate ? "!" : "",
143                 c->parameter);
144 }
145
146 void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
147         Condition *c;
148
149         LIST_FOREACH(conditions, c, first)
150                 condition_dump(c, f, prefix);
151 }
152
153 static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
154         [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
155         [CONDITION_PATH_EXISTS] = "ConditionPathExists"
156 };
157
158 DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);