qosify: add support for keeping stats
[project/qosify.git] / main.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
4 */
5 #include <sys/wait.h>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <stdint.h>
9
10 #include <libubox/uloop.h>
11
12 #include "qosify.h"
13
14 static int usage(const char *progname)
15 {
16 fprintf(stderr, "Usage: %s [options]\n"
17 "Options:\n"
18 " -l <file> Load defaults from <file>\n"
19 " -o only load program/maps without running as daemon\n"
20 "\n", progname);
21
22 return 1;
23 }
24
25 int qosify_run_cmd(char *cmd, bool ignore_error)
26 {
27 char *argv[] = { "sh", "-c", cmd, NULL };
28 bool first = true;
29 int status = -1;
30 char buf[512];
31 int fds[2];
32 FILE *f;
33 int pid;
34
35 if (pipe(fds))
36 return -1;
37
38 pid = fork();
39 if (!pid) {
40 close(fds[0]);
41 if (fds[1] != STDOUT_FILENO)
42 dup2(fds[1], STDOUT_FILENO);
43 if (fds[1] != STDERR_FILENO)
44 dup2(fds[1], STDERR_FILENO);
45 if (fds[1] > STDERR_FILENO)
46 close(fds[1]);
47 execv("/bin/sh", argv);
48 exit(1);
49 }
50
51 if (pid < 0)
52 return -1;
53
54 close(fds[1]);
55 f = fdopen(fds[0], "r");
56 if (!f) {
57 close(fds[0]);
58 goto out;
59 }
60
61 while (fgets(buf, sizeof(buf), f) != NULL) {
62 if (!strlen(buf))
63 break;
64 if (ignore_error)
65 continue;
66 if (first) {
67 ULOG_WARN("Command: %s\n", cmd);
68 first = false;
69 }
70 ULOG_WARN("%s%s", buf, strchr(buf, '\n') ? "" : "\n");
71 }
72
73 fclose(f);
74
75 out:
76 while (waitpid(pid, &status, 0) < 0)
77 if (errno != EINTR)
78 break;
79
80 return status;
81 }
82
83
84 int main(int argc, char **argv)
85 {
86 const char *load_file = NULL;
87 bool oneshot = false;
88 int ch;
89
90 while ((ch = getopt(argc, argv, "fl:o")) != -1) {
91 switch (ch) {
92 case 'f':
93 break;
94 case 'l':
95 load_file = optarg;
96 break;
97 case 'o':
98 oneshot = true;
99 break;
100 default:
101 return usage(argv[0]);
102 }
103 }
104
105 if (qosify_loader_init())
106 return 2;
107
108 if (qosify_map_init())
109 return 2;
110
111 if (qosify_map_load_file(load_file))
112 return 2;
113
114 if (oneshot)
115 return 0;
116
117 ulog_open(ULOG_SYSLOG, LOG_DAEMON, "qosify");
118 uloop_init();
119
120 if (qosify_ubus_init() ||
121 qosify_iface_init())
122 return 2;
123
124 qosify_dns_init();
125
126 uloop_run();
127
128 qosify_ubus_stop();
129 qosify_iface_stop();
130
131 uloop_done();
132
133 return 0;
134 }