proto-shell: move script handler dump code to handler.c
[project/netifd.git] / handler.c
1 /*
2  * netifd - network interface daemon
3  * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #define _GNU_SOURCE
16 #include <glob.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #include "netifd.h"
22 #include "system.h"
23 #include "handler.h"
24
25 static int
26 netifd_dir_push(int fd)
27 {
28         int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
29         system_fd_set_cloexec(prev_fd);
30         if (fd >= 0)
31                 fchdir(fd);
32         return prev_fd;
33 }
34
35 static void
36 netifd_dir_pop(int prev_fd)
37 {
38         fchdir(prev_fd);
39         close(prev_fd);
40 }
41
42 int netifd_open_subdir(const char *name)
43 {
44         int prev_dir;
45         int ret = -1;
46
47         prev_dir = netifd_dir_push(-1);
48         if (chdir(main_path)) {
49                 perror("chdir(main path)");
50                 goto out;
51         }
52
53         ret = open(name, O_RDONLY | O_DIRECTORY);
54         if (ret >= 0)
55                 system_fd_set_cloexec(ret);
56
57 out:
58         netifd_dir_pop(prev_dir);
59         return ret;
60 }
61
62 static void
63 netifd_init_script_handler(const char *name, script_dump_cb cb)
64 {
65         struct json_tokener *tok = NULL;
66         json_object *obj;
67         static char buf[512];
68         char *start, *cmd;
69         FILE *f;
70         int len;
71
72 #define DUMP_SUFFIX     " '' dump"
73
74         cmd = alloca(strlen(name) + 1 + sizeof(DUMP_SUFFIX));
75         sprintf(cmd, "%s" DUMP_SUFFIX, name);
76
77         f = popen(cmd, "r");
78         if (!f)
79                 return;
80
81         do {
82                 start = fgets(buf, sizeof(buf), f);
83                 if (!start)
84                         continue;
85
86                 len = strlen(start);
87
88                 if (!tok)
89                         tok = json_tokener_new();
90
91                 obj = json_tokener_parse_ex(tok, start, len);
92                 if (!is_error(obj)) {
93                         cb(name, obj);
94                         json_object_put(obj);
95                         json_tokener_free(tok);
96                         tok = NULL;
97                 } else if (start[len - 1] == '\n') {
98                         json_tokener_free(tok);
99                         tok = NULL;
100                 }
101         } while (!feof(f) && !ferror(f));
102
103         if (tok)
104                 json_tokener_free(tok);
105
106         pclose(f);
107 }
108
109 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
110 {
111         glob_t g;
112         int i, prev_fd;
113
114         prev_fd = netifd_dir_push(dir_fd);
115         glob("./*.sh", 0, NULL, &g);
116         for (i = 0; i < g.gl_pathc; i++)
117                 netifd_init_script_handler(g.gl_pathv[i], cb);
118         netifd_dir_pop(prev_fd);
119 }