wmclockmon: remove unnecessary `AC_SUBST` of `LIBS`
[dockapps.git] / wmcliphist / rcconfig.c
blob153295cc5022d76e4b580e922837f1476e6ee14b
1 #include "wmcliphist.h"
2 #include <sys/stat.h>
4 #define RC_BUF_SIZE 256
6 /* automat state */
7 typedef enum {
8 STATE_BEGINING,
9 STATE_COMMENT,
10 STATE_DIRECTIVE,
11 STATE_VALUE,
12 STATE_EXPRESSION_START,
13 STATE_EXPRESSION,
14 STATE_EXPRESSION_END,
15 STATE_ACTION,
16 STATE_COMMAND
17 } STATE;
20 GList *action_list = NULL;
23 /* add character to buffer */
24 #define add_to_buff(buf, pos, chr) do { \
25 buf[pos++] = chr; \
26 buf[pos] = '\0'; \
27 if (pos + 1 == RC_BUF_SIZE) \
28 error = 7; \
29 } while (0)
32 #define ismywhite(c) (c == '\t' || c == ' ')
36 * returns config/data file name in user's home
38 char *
39 rcconfig_get_name(char *append)
41 static gchar fname[PATH_MAX];
42 const gchar *home;
44 begin_func("rcconfig_get_name");
46 if (!(home = g_getenv("HOME")))
47 return_val(NULL);
49 memset(fname, 0, PATH_MAX);
50 snprintf(fname, PATH_MAX, "%s/.wmcliphist%s", home, append);
52 return_val(fname);
59 * appends parsed action to action list
61 int
62 action_append(char *expr_buf, char *action_buf, char *cmd_buf)
64 ACTION *action;
66 begin_func("action_append");
68 action = g_new0(ACTION, 1);
70 if (regcomp(&action->expression, expr_buf,
71 REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) {
72 g_free(action);
73 return_val(-101);
76 if (strcmp(action_buf, "exec") == 0)
77 action->action = ACT_EXEC;
78 else if (strcmp(action_buf, "submenu") == 0)
79 action->action = ACT_SUBMENU;
80 else if (strcmp(action_buf, "ignore") == 0)
81 action->action = ACT_IGNORE;
82 else {
83 g_free(action);
84 return_val(-102);
87 action->command = g_strdup(cmd_buf);
89 action_list = g_list_append(action_list, action);
91 return_val(0);
96 * read and parse rcconfig
98 int
99 rcconfig_get(char *fname)
101 int f_rc;
102 char tmp[1024], c;
103 int byte_cnt;
104 STATE state = STATE_BEGINING;
105 char direc_buf[RC_BUF_SIZE],
106 expr_buf[RC_BUF_SIZE],
107 action_buf[RC_BUF_SIZE],
108 cmd_buf[RC_BUF_SIZE];
109 int buf_index = 0;
110 int error = 0, eof = 0;
111 int i;
112 int line = 0;
113 int res;
115 begin_func("rcconfig_get");
117 close(open(fname, O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
119 if ((f_rc = open(fname, O_RDONLY)) < 0) {
120 fprintf(stderr, ".wmcliphistrc not found\n");
121 return_val(1);
124 i = byte_cnt = 0;
125 while (1) {
126 if (i == byte_cnt) {
127 byte_cnt = read(f_rc, tmp, 1024);
128 if (byte_cnt == -1) {
129 fprintf(stderr, "cannot read .wmcliphistrc\n");
130 break;
131 } else if (byte_cnt < 1024) {
132 tmp[byte_cnt++] = 0;
133 eof = 1;
135 i = 0;
138 c = tmp[i++];
139 switch (state) {
140 case STATE_BEGINING:
141 line++;
142 if (isalnum(c)) {
143 state = STATE_DIRECTIVE;
144 buf_index = 0;
145 add_to_buff(direc_buf, buf_index, c);
146 } else if (c == '#')
147 state = STATE_COMMENT;
148 else if (ismywhite(c))
149 line--;
150 else if (c == '\n')
151 state = STATE_BEGINING;
152 else
153 error = 1;
154 break;
156 case STATE_COMMENT:
157 if (c == '\n' || c == '\0')
158 state = STATE_BEGINING;
159 break;
161 case STATE_DIRECTIVE:
162 if (ismywhite(c)) {
163 if (strcmp(direc_buf, "action") == 0) {
164 state = STATE_EXPRESSION_START;
165 buf_index = 0;
166 } else if (strcmp(direc_buf, "menukey") == 0) {
167 state = STATE_VALUE;
168 buf_index = 0;
169 } else if (strcmp(direc_buf, "prev_item_key") == 0) {
170 state = STATE_VALUE;
171 buf_index = 0;
172 } else if (strcmp(direc_buf, "exec_item_key") == 0) {
173 state = STATE_VALUE;
174 buf_index = 0;
175 } else if (strcmp(direc_buf, "keep") == 0) {
176 state = STATE_VALUE;
177 buf_index = 0;
178 } else if (strcmp(direc_buf, "lcolor") == 0) {
179 state = STATE_VALUE;
180 buf_index = 0;
181 } else if (strcmp(direc_buf, "clipboard") == 0) {
182 state = STATE_VALUE;
183 buf_index = 0;
184 } else if (strcmp(direc_buf, "autosave") == 0) {
185 state = STATE_VALUE;
186 buf_index = 0;
187 } else if (strcmp(direc_buf,
188 "confirm_exec") == 0) {
189 state = STATE_VALUE;
190 buf_index = 0;
191 } else if (strcmp(direc_buf, "exec_immediately") == 0) {
192 state = STATE_VALUE;
193 buf_index = 0;
194 } else if (strcmp(direc_buf, "exec_middleclick") == 0) {
195 state = STATE_VALUE;
196 buf_index = 0;
197 } else if (strcmp(direc_buf, "exec_hotkey") == 0) {
198 state = STATE_VALUE;
199 buf_index = 0;
200 } else if (strcmp(direc_buf, "auto_take_up") == 0) {
201 state = STATE_VALUE;
202 buf_index = 0;
203 } else {
204 error = 8;
206 } else if (isalpha(c) || c == '_') {
207 add_to_buff(direc_buf, buf_index, c);
208 } else {
209 error = 1;
211 break;
213 case STATE_VALUE:
214 if (c == '\n' || ismywhite(c)) {
215 if (strcmp(direc_buf, "menukey") == 0) {
216 memset(menukey_str, 0, 32);
217 strncpy(menukey_str,
218 expr_buf, 31);
219 } else if (strcmp(direc_buf, "prev_item_key") == 0) {
220 memset(prev_item_key_str, 0, 32);
221 strncpy(prev_item_key_str,
222 expr_buf, 31);
223 } else if (strcmp(direc_buf, "exec_item_key") == 0) {
224 memset(exec_item_key_str, 0, 32);
225 strncpy(exec_item_key_str,
226 expr_buf, 31);
227 } else if (strcmp(direc_buf, "keep") == 0) {
228 num_items_to_keep =
229 atoi(expr_buf);
230 } else if (strcmp(direc_buf, "lcolor")
231 == 0) {
232 memset(locked_color_str, 0, 32);
233 strncpy(locked_color_str,
234 expr_buf, 31);
235 } else if (strcmp(direc_buf, "clipboard")
236 == 0) {
237 memset(clipboard_str, 0, 32);
238 strncpy(clipboard_str,
239 expr_buf, 31);
240 } else if (strcmp(direc_buf, "autosave") == 0) {
241 autosave_period =
242 atoi(expr_buf);
243 } else if (strcmp(direc_buf,
244 "confirm_exec") == 0) {
245 if (strcasecmp(expr_buf, "yes") == 0) {
246 confirm_exec = 1;
248 } else if (strcmp(direc_buf, "exec_immediately") == 0) {
249 if (strcasecmp(expr_buf, "no") == 0) {
250 exec_immediately= 0;
252 } else if (strcmp(direc_buf, "exec_middleclick") == 0) {
253 if (strcasecmp(expr_buf, "no") == 0) {
254 exec_middleclick = 0;
256 } else if (strcmp(direc_buf, "exec_hotkey") == 0) {
257 if (strcasecmp(expr_buf, "no") == 0) {
258 exec_hotkey = 0;
260 } else if (strcmp(direc_buf, "auto_take_up") == 0) {
261 if (strcasecmp(expr_buf, "no") == 0) {
262 auto_take_up = 0;
264 } else
265 error = 1;
266 } else if (isgraph(c))
267 add_to_buff(expr_buf, buf_index, c);
268 else
269 error = 2;
271 if (error == 0) {
272 if (c == '\n' || c == '\0') {
273 buf_index = 0;
274 state = STATE_BEGINING;
275 } else if (ismywhite(c)) {
276 buf_index = 0;
277 state = STATE_COMMENT;
281 break;
283 case STATE_EXPRESSION_START:
284 if (c == '"')
285 state = STATE_EXPRESSION;
286 else
287 error = 1;
288 break;
290 case STATE_EXPRESSION:
291 if (c == '"')
292 state = STATE_EXPRESSION_END;
293 else if (c == '\n')
294 error = 1;
295 else
296 add_to_buff(expr_buf, buf_index, c);
297 break;
299 case STATE_EXPRESSION_END:
300 if (c != ' ' && c != '\t')
301 error = 1;
302 if (strcmp(direc_buf, "action") == 0) {
303 state = STATE_ACTION;
304 buf_index = 0;
305 } else
306 error = 1;
308 break;
310 case STATE_ACTION:
311 if (c == ' ' || c == '\t') {
312 state = STATE_COMMAND;
313 buf_index = 0;
314 } else if (c == '\0' || c == '\n') {
315 if (strcmp(action_buf, "ignore") == 0) {
316 state = STATE_BEGINING;
317 buf_index = 0;
318 *cmd_buf = '\0';
319 res = action_append(
320 expr_buf,
321 action_buf,
322 cmd_buf);
323 if (res < 0)
324 error = abs(res);
325 } else
326 error = 1;
327 } else if (isalpha(c))
328 add_to_buff(action_buf, buf_index, c);
329 else
330 error = 1;
331 break;
333 case STATE_COMMAND:
334 if (c == '\n' || c == '\0') {
335 state = STATE_BEGINING;
336 buf_index = 0;
337 res = action_append(
338 expr_buf,
339 action_buf,
340 cmd_buf);
341 if (res < 0)
342 error = abs(res);
343 } else
344 add_to_buff(cmd_buf, buf_index, c);
345 break;
348 if (!error && (!eof || i < byte_cnt))
349 continue;
351 switch (state) {
352 case STATE_DIRECTIVE:
353 if (error == 7)
354 fprintf(stderr, "Directive is too long "
355 "(line %d)\n", line);
356 else if (error == 8)
357 fprintf(stderr, "Unknown directive "
358 "(line %d)\n", line);
359 else
360 fprintf(stderr, "Only letters are "
361 "allowed in directive "
362 "name (line %d)\n",
363 line);
364 break;
366 case STATE_EXPRESSION_START:
367 case STATE_EXPRESSION:
368 if (error == 7)
369 fprintf(stderr, "Expression is too long "
370 "(line %d)\n", line);
371 else
372 fprintf(stderr, "Expression must be "
373 "enclosed with quotes "
374 "\" (line %d)\n", line);
375 break;
377 case STATE_EXPRESSION_END:
378 fprintf(stderr, "One space/tab and "
379 "action must follow "
380 "each expression"
381 " (line %d)\n", line);
382 break;
384 case STATE_ACTION:
385 if (error == 1)
386 fprintf(stderr, "Only letters are "
387 "allowed in action "
388 "name (line %d)\n",
389 line);
390 else if (error == 101)
391 fprintf(stderr, "Invalid expression "
392 "(line %d)\n", line);
393 else if (error == 7)
394 fprintf(stderr, "Action is too long "
395 "(line %d)\n", line);
396 else
397 fprintf(stderr, "Invalid action "
398 "(line %d)\n", line);
399 break;
401 case STATE_VALUE:
402 if (error == 1)
403 fprintf(stderr, "Invalid directive "
404 "(line %d)\n", line);
405 else if (error == 7)
406 fprintf(stderr, "Value is too long "
407 "(line %d)\n", line);
408 else
409 fprintf(stderr, "Invalid value "
410 "(line %d)\n", line);
411 break;
413 case STATE_COMMAND:
414 if (error == 101)
415 fprintf(stderr, "Invalid expression "
416 "(line %d)\n", line);
417 else if (error == 7)
418 fprintf(stderr, "Command is too long "
419 "(line %d)\n", line);
420 else
421 fprintf(stderr, "Invalid action "
422 "(line %d)\n", line);
423 break;
425 case STATE_COMMENT:
426 if (!eof)
427 fprintf(stderr, "Unknown error "
428 "(line %d)\n", line);
429 else
430 error = 0;
431 break;
433 case STATE_BEGINING:
434 /* everything is OK */
435 error = 0;
436 break;
439 break;
442 close(f_rc);
444 return_val(error);
449 * free rcconfig data
451 void
452 rcconfig_free()
454 GList *list_node;
456 begin_func("rcconfig_free");
458 list_node = action_list;
459 while (list_node) {
460 ACTION *action = list_node->data;
462 g_free(action->command);
463 regfree(&action->expression);
464 g_free(action);
465 list_node = list_node->next;
467 g_list_free(action_list);
469 return_void();