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