]> git.itanic.dy.fi Git - rrdd/blob - parser.c
Add utils.h
[rrdd] / parser.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "parser.h"
6 #include "process.h"
7 #include "string.h"
8 #include "debug.h"
9 #include "utils.h"
10
11 #define STATFILE "/proc/stat"
12
13 int cpu_parser(char *data, const char **p)
14 {
15         char buf[1024];
16         char *str = buf;
17         FILE *file = fopen(STATFILE, "r");
18         long long user, nice, sys, idle, wait, irq, softirq;
19
20         if (file == NULL) {
21                 pr_err("Failed to open file %s\n", STATFILE);
22                 return -1;
23         }
24
25         if (!fgets(buf, 1024, file)) {
26                 pr_err("Failed to read file %s\n", STATFILE);
27                 fclose(file);
28                 return -1;
29         }
30
31         user    = dec_to_longlong(str, &str);
32         nice    = dec_to_longlong(str, &str);
33         sys     = dec_to_longlong(str, &str);
34         idle    = dec_to_longlong(str, &str);
35         wait    = dec_to_longlong(str, &str);
36         irq     = dec_to_longlong(str, &str);
37         softirq = dec_to_longlong(str, &str);
38
39         snprintf(data, RRD_DATA_MAX_LEN, "%lld:%lld:%lld:%lld:%lld:%lld:%lld",
40                 user, nice, sys, idle, wait, irq, softirq);
41
42         fclose(file);
43         return 0;
44 }
45
46 #define MEMFILE "/proc/meminfo"
47
48 int mem_parser(char *data, const char **p)
49 {
50         char buf[1024], word[1024];
51         int free = 0, buffered = 0, cache = 0, active = 0, inactive = 0,
52                 swapfree = 0, anon = 0, slab = 0, tables = 0, other = 0,
53                 swaptotal = 0, total = 0;
54         FILE *file = fopen(MEMFILE, "r");
55
56         if (file == NULL) {
57                 pr_err("Failed to open file %s\n", MEMFILE);
58                 return -1;
59         }
60
61         while (fgets(buf, 1024, file)) {
62                 get_word(buf, 0, word, 1024);
63                 
64                 if (!strcmp(word, "MemFree:")) {
65                         free = dec_to_int(buf, NULL);
66                 } else if (!strcmp(word, "MemTotal:")) {
67                         total = dec_to_int(buf, NULL);
68                 } else if (!strcmp(word, "Buffers:")) {
69                         buffered = dec_to_int(buf, NULL);
70                 } else if (!strcmp(word, "Cached:")) {
71                         cache = dec_to_int(buf, NULL);
72                 } else if (!strcmp(word, "Active:")) {
73                         active = dec_to_int(buf, NULL);
74                 } else if (!strcmp(word, "Inactive:")) {
75                         inactive = dec_to_int(buf, NULL);
76                 } else if (!strcmp(word, "SwapFree:")) {
77                         swapfree = dec_to_int(buf, NULL);
78                 } else if (!strcmp(word, "AnonPages:")) {
79                         anon = dec_to_int(buf, NULL);
80                 } else if (!strcmp(word, "Slab:")) {
81                         slab = dec_to_int(buf, NULL);
82                 } else if (!strcmp(word, "PageTables:")) {
83                         tables = dec_to_int(buf, NULL);
84                 } else if (!strcmp(word, "SwapTotal:")) {
85                         swaptotal = dec_to_int(buf, NULL);
86                 }
87         }
88         fclose(file);
89
90         other = total - free - buffered - cache - anon - slab - tables;
91
92         snprintf(data, RRD_DATA_MAX_LEN, "%f:%f:%f:%f:%f:%f:%f:%f:%f:%f:%f",
93                 free / 1024.0,
94                 buffered / 1024.0,
95                 cache / 1024.0,
96                 active / 1024.0,
97                 inactive / 1024.0,
98                 swapfree / 1024.0,
99                 anon / 1024.0,
100                 slab / 1024.0,
101                 tables / 1024.0,
102                 other / 1024.0,
103                 (swaptotal - swapfree) / 1024.0);
104
105         return 0;
106 }
107
108 int cpu_mem_parser(char *data, const char **p)
109 {
110         char cpu[1024], mem[1024];
111
112         cpu_parser(cpu, p);
113         mem_parser(mem, p);
114         snprintf(data, RRD_DATA_MAX_LEN, "%s:%s", cpu, mem);
115
116         return 0;
117 }
118
119 int digitemp_parser(char *data, const char **p)
120 {
121         const char digitemp_cmd[] = "/usr/bin/digitemp";
122         char *const digitemp_args[] = { "", "-o2", "-a", "-q", 0 };
123         FILE *readf;
124         int pid, ret;
125         float t1 = 0, t2 = 0, t3 = 0;
126         char buf[1024];
127
128         pid = run_piped_stream(digitemp_cmd, digitemp_args, 0, &readf, 0);
129         if (pid < 0) {
130                 pr_err("Failed to parse digitemp\n");
131                 sprintf(data, "U:U");
132                 return -1;
133         }
134
135         ret = fscanf(readf, "%f %f %f", &t1, &t2, &t3);
136
137         if (ret != 3) {
138                 pr_err("Failed to parse digitemp output: %m\n");
139                 sprintf(data, "U:U");
140                 return 1;
141         }
142
143         t2 += 2.16;
144         t3 += -0.44;
145
146         /* Read whatever the process might be still printing out */
147         while (fgets(buf, 1024, readf));
148
149         harvest_zombies(pid);
150         snprintf(data, RRD_DATA_MAX_LEN, "%.2f:%.2f", t3, t2);
151         return 0;
152 }
153
154 int digitemp_parser_mod(char *data, const char **p)
155 {
156         char buf[1024];
157         int ret;
158
159         ret = digitemp_parser(buf, p);
160         snprintf(data, RRD_DATA_MAX_LEN, "U:%s", buf);
161
162         return ret;
163 }
164
165 /* Run a command and feed the output from stdout directly to rrdtool */
166 int script_parser(char *rrd_data, const char **parser_data)
167 {
168         FILE *readf;
169         int pid, ret;
170         void *tmp = parser_data;
171         char **cmd = tmp;
172
173         pid = run_piped_stream(cmd[0], &cmd[1], NULL, &readf, NULL);
174         ret = fread(rrd_data, 1, RRD_DATA_MAX_LEN, readf);
175
176         pr_info("Read %d bytes :%s\n", ret, rrd_data);
177         fclose(readf);
178
179         harvest_zombies(pid);
180
181         return 0;
182 }
183
184 struct iface_stats {
185         long long rx_bytes;
186         long long rx_packets;
187         long long tx_bytes;
188         long long tx_packets;
189 };
190
191 #define PROC_NETDEV     "/proc/net/dev"
192
193 static int get_iface_stats(const char *iface, struct iface_stats *stat)
194 {
195         FILE *netdev;
196         char buf[1024];
197         char if_name[16];
198         char *str;
199         int error;
200
201         netdev = fopen(PROC_NETDEV, "r");
202
203         if (netdev == NULL) {
204                 error = errno;
205                 pr_err("Failed to open file %s: %d (%m)\n",
206                         PROC_NETDEV, error);
207                 return error;
208         }
209
210         while (fgets(buf, sizeof(buf), netdev)) {
211                 get_word(buf, &str, if_name, sizeof(if_name));
212
213                 /* Remove the ':' at the end of the if_name */
214                 if_name[strlen(if_name) - 1] = 0;
215                 if (strncmp(iface, if_name, sizeof(if_name)))
216                         continue;
217
218                 stat->rx_bytes          = dec_to_longlong(str, &str);
219                 stat->rx_packets        = dec_to_longlong(str, &str);
220                 /* errs */                dec_to_longlong(str, &str);
221                 /* drop */                dec_to_longlong(str, &str);
222                 /* fifo */                dec_to_longlong(str, &str);
223                 /* frame */               dec_to_longlong(str, &str);
224                 /* compressed */          dec_to_longlong(str, &str);
225                 /* multicast */           dec_to_longlong(str, &str);
226                 stat->tx_bytes          = dec_to_longlong(str, &str);
227                 stat->tx_packets        = dec_to_longlong(str, &str);
228
229                 pr_info("rx_b %lld rx_p %lld tx_b %lld tx_p %lld\n",
230                         stat->rx_bytes, stat->rx_packets,
231                         stat->tx_bytes, stat->tx_packets);
232
233                 return 0;
234         }
235
236         pr_err("Interface %s not found\n", iface);
237         return -ENODEV;
238 }
239
240 int netstats_parser(char *rrd_data, const char **parser_data)
241 {
242         struct iface_stats stat;
243         const char **iface_name = parser_data;
244         int max_str = RRD_DATA_MAX_LEN;
245         int ret;
246
247         if (!parser_data) {
248                 pr_err("No device names specified\n");
249                 return -1;
250         }
251
252         while(*iface_name) {
253                 pr_info("getting data for iface %s\n", *iface_name);
254                 ret = get_iface_stats(*iface_name, &stat);
255
256                 if (!ret) {
257                         ret = snprintf(rrd_data, max_str, "%lld:%lld:%lld:%lld",
258                                 stat.rx_bytes, stat.rx_packets,
259                                 stat.tx_bytes, stat.tx_packets);
260                 } else {
261                         ret = snprintf(rrd_data, max_str, "U:U:U:U");
262                 }
263
264                 max_str -= ret;
265                 rrd_data += ret;
266
267                 iface_name++;
268                 if (!*iface_name)
269                         break;
270
271                 ret = snprintf(rrd_data, max_str, ":");
272                 max_str -= ret;
273                 rrd_data += ret;
274         }
275
276         return 0;
277 }