lib/efi: Cleanup read/write routines
[petitboot] / discover / event.c
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #include <string.h>
6
7 #include <log/log.h>
8 #include <talloc/talloc.h>
9
10 #include "event.h"
11
12 #define streq(a, b) (!strcasecmp((a), (b)))
13
14 /**
15  * event_parse_ad_header - Parse an <action>@<device> event header.
16  *
17  * The buffer is modified in place.
18  * Returns zero on success.
19  */
20
21 static int event_parse_ad_header(char *buf, int len, enum event_action *action,
22         char **device)
23 {
24         int headerlen;
25         char *sep;
26
27         *action = 0;
28         *device = NULL;
29         headerlen = strnlen(buf, len);
30
31         if (!headerlen) {
32                 pb_log_fn("bad header, no data\n");
33                 return -1;
34         }
35
36         /* we should see an <action>@<device>\0 at the head of the buffer */
37         sep = strchr(buf, '@');
38         if (!sep) {
39                 pb_log_fn("bad header: %s\n", buf);
40                 return -1;
41         }
42
43         /* terminate the action string */
44         *sep = '\0';
45
46         if (streq(buf, "add"))
47                 *action = EVENT_ACTION_ADD;
48         else if (streq(buf, "remove"))
49                 *action = EVENT_ACTION_REMOVE;
50         else if (streq(buf, "url"))
51                 *action = EVENT_ACTION_URL;
52         else if (streq(buf, "dhcp"))
53                 *action = EVENT_ACTION_DHCP;
54         else if (streq(buf, "boot"))
55                 *action = EVENT_ACTION_BOOT;
56         else if (streq(buf, "sync"))
57                 *action = EVENT_ACTION_SYNC;
58         else if (streq(buf, "plugin"))
59                 *action = EVENT_ACTION_PLUGIN;
60         else {
61                 pb_log_fn("unknown action: %s\n", buf);
62                 return -1;
63         }
64
65         if (!*(sep + 1)) {
66                 pb_log_fn("bad device: %s\n", buf);
67                 return -1;
68         }
69
70         *device = sep + 1;
71         return headerlen;
72 }
73
74 /**
75  * event_parse_params - Parse a <name>=<value> buffer.
76  *
77  * The buffer is not modified.
78  */
79
80 static void event_parse_params(struct event *event, const char *buf, int len)
81 {
82         int param_len, name_len, value_len;
83         struct param *param;
84         char *sep;
85
86         for (; len > 0; len -= param_len + 1, buf += param_len + 1) {
87
88                 /* find the length of the whole parameter */
89                 param_len = strnlen(buf, len);
90                 if (!param_len) {
91                         /* multiple NULs? skip over */
92                         param_len = 1;
93                         continue;
94                 }
95
96                 /* update the params array */
97                 event->params = talloc_realloc(event, event->params,
98                                         struct param, ++event->n_params);
99                 param = &event->params[event->n_params - 1];
100
101                 sep = memchr(buf, '=', param_len);
102                 if (!sep) {
103                         name_len = param_len;
104                         value_len = 0;
105                         param->value = "";
106                 } else {
107                         name_len = sep - buf;
108                         value_len = param_len - name_len - 1;
109                         param->value = talloc_strndup(event, sep + 1,
110                                         value_len);
111                 }
112                 param->name = talloc_strndup(event, buf, name_len);
113         }
114 }
115
116 int event_parse_ad_message(struct event *event, char *buf, int len)
117 {
118         enum event_action action;
119         int headerlen;
120         char *device;
121
122         headerlen = event_parse_ad_header(buf, len, &action, &device);
123
124         if (headerlen <= 0)
125                 return -1;
126
127         /* now we have an action and a device, we can construct the event */
128         event->action = action;
129         event->device = talloc_strdup(event, device);
130         event->n_params = 0;
131         event->params = NULL;
132
133         len -= headerlen + 1;
134         buf += headerlen + 1;
135         event_parse_params(event, buf, len);
136
137         return 0;
138 }
139
140 const char *event_get_param(const struct event *event, const char *name)
141 {
142         int i;
143
144         for (i = 0; i < event->n_params; i++)
145                 if (!strcasecmp(event->params[i].name, name))
146                         return event->params[i].value;
147
148         return NULL;
149 }
150
151 void event_set_param(struct event *event, const char *name, const char *value)
152 {
153         struct param *param;
154         int i;
155
156         /* if it's already present, replace the value of the old param */
157         for (i = 0; i < event->n_params; i++) {
158                 param = &event->params[i];
159                 if (!strcasecmp(param->name, name)) {
160                         talloc_free(param->value);
161                         param->value = talloc_strdup(event, value);
162                         return;
163                 }
164         }
165
166         /* not found - create a new param */
167         event->params = talloc_realloc(event, event->params,
168                                 struct param, ++event->n_params);
169         param = &event->params[event->n_params - 1];
170
171         param->name = talloc_strdup(event, name);
172         param->value = talloc_strdup(event, value);
173 }