1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2 * vim: ts=4 sw=4 noet ai cindent syntax=c
4 * Conky, a system monitor, based on torsmo
6 * Any original torsmo code is licensed under the BSD license
8 * All code written since the fork of torsmo is licensed under the GPL
10 * Please see COPYING for details
12 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
13 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
15 * All rights reserved.
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
36 #include "text_object.h"
38 #include <netinet/in.h>
41 #include <sys/ioctl.h>
44 /* network interface stuff */
46 struct net_stat netstats[MAX_NET_INTERFACES];
48 struct net_stat *get_net_stat(const char *dev, void *free_at_crash1, void *free_at_crash2)
56 /* find interface stat */
57 for (i = 0; i < MAX_NET_INTERFACES; i++) {
58 if (netstats[i].dev && strcmp(netstats[i].dev, dev) == 0) {
63 /* wasn't found? add it */
64 for (i = 0; i < MAX_NET_INTERFACES; i++) {
65 if (netstats[i].dev == 0) {
66 netstats[i].dev = strndup(dev, text_buffer_size);
71 CRIT_ERR(free_at_crash1, free_at_crash2, "too many interfaces used (limit is %d)", MAX_NET_INTERFACES);
75 void parse_net_stat_arg(struct text_object *obj, const char *arg, void *free_at_crash)
80 obj->data.opaque = get_net_stat(arg, obj, free_at_crash);
83 void parse_net_stat_bar_arg(struct text_object *obj, const char *arg, void *free_at_crash)
86 arg = scan_bar(obj, arg);
87 obj->data.opaque = get_net_stat(arg, obj, free_at_crash);
89 // default to DEFAULTNETDEV
90 char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
91 obj->data.opaque = get_net_stat(buf, obj, free_at_crash);
96 void print_downspeed(struct text_object *obj, char *p, int p_max_size)
98 struct net_stat *ns = obj->data.opaque;
103 human_readable(ns->recv_speed, p, p_max_size);
106 void print_downspeedf(struct text_object *obj, char *p, int p_max_size)
108 struct net_stat *ns = obj->data.opaque;
113 spaced_print(p, p_max_size, "%.1f", 8, ns->recv_speed / 1024.0);
116 void print_upspeed(struct text_object *obj, char *p, int p_max_size)
118 struct net_stat *ns = obj->data.opaque;
123 human_readable(ns->trans_speed, p, p_max_size);
126 void print_upspeedf(struct text_object *obj, char *p, int p_max_size)
128 struct net_stat *ns = obj->data.opaque;
133 spaced_print(p, p_max_size, "%.1f", 8, ns->trans_speed / 1024.0);
136 void print_totaldown(struct text_object *obj, char *p, int p_max_size)
138 struct net_stat *ns = obj->data.opaque;
143 human_readable(ns->recv, p, p_max_size);
146 void print_totalup(struct text_object *obj, char *p, int p_max_size)
148 struct net_stat *ns = obj->data.opaque;
153 human_readable(ns->trans, p, p_max_size);
156 void print_addr(struct text_object *obj, char *p, int p_max_size)
158 struct net_stat *ns = obj->data.opaque;
163 if ((ns->addr.sa_data[2] & 255) == 0 &&
164 (ns->addr.sa_data[3] & 255) == 0 &&
165 (ns->addr.sa_data[4] & 255) == 0 &&
166 (ns->addr.sa_data[5] & 255) == 0) {
167 snprintf(p, p_max_size, "No Address");
169 snprintf(p, p_max_size, "%u.%u.%u.%u",
170 ns->addr.sa_data[2] & 255,
171 ns->addr.sa_data[3] & 255,
172 ns->addr.sa_data[4] & 255,
173 ns->addr.sa_data[5] & 255);
178 void print_addrs(struct text_object *obj, char *p, int p_max_size)
180 struct net_stat *ns = obj->data.opaque;
185 if (NULL != ns->addrs && strlen(ns->addrs) > 2) {
186 ns->addrs[strlen(ns->addrs) - 2] = 0; /* remove ", " from end of string */
187 strncpy(p, ns->addrs, p_max_size);
189 strncpy(p, "0.0.0.0", p_max_size);
192 #endif /* __linux__ */
195 void parse_net_stat_graph_arg(struct text_object *obj, const char *arg, void *free_at_crash)
198 buf = scan_graph(obj, arg, 0);
200 // default to DEFAULTNETDEV
202 obj->data.opaque = get_net_stat(buf, obj, free_at_crash);
206 obj->data.opaque = get_net_stat(DEFAULTNETDEV, obj, free_at_crash);
209 void print_downspeedgraph(struct text_object *obj, char *p)
211 struct net_stat *ns = obj->data.opaque;
216 new_graph(obj, p, ns->recv_speed / 1024.0);
219 void print_upspeedgraph(struct text_object *obj, char *p)
221 struct net_stat *ns = obj->data.opaque;
226 new_graph(obj, p, ns->trans_speed / 1024.0);
232 void print_wireless_essid(struct text_object *obj, char *p, int p_max_size)
234 struct net_stat *ns = obj->data.opaque;
239 snprintf(p, p_max_size, "%s", ns->essid);
241 void print_wireless_mode(struct text_object *obj, char *p, int p_max_size)
243 struct net_stat *ns = obj->data.opaque;
248 snprintf(p, p_max_size, "%s", ns->mode);
250 void print_wireless_bitrate(struct text_object *obj, char *p, int p_max_size)
252 struct net_stat *ns = obj->data.opaque;
257 snprintf(p, p_max_size, "%s", ns->bitrate);
259 void print_wireless_ap(struct text_object *obj, char *p, int p_max_size)
261 struct net_stat *ns = obj->data.opaque;
266 snprintf(p, p_max_size, "%s", ns->ap);
268 void print_wireless_link_qual(struct text_object *obj, char *p, int p_max_size)
270 struct net_stat *ns = obj->data.opaque;
275 spaced_print(p, p_max_size, "%d", 4, ns->link_qual);
277 void print_wireless_link_qual_max(struct text_object *obj, char *p, int p_max_size)
279 struct net_stat *ns = obj->data.opaque;
284 spaced_print(p, p_max_size, "%d", 4, ns->link_qual_max);
286 void print_wireless_link_qual_perc(struct text_object *obj, char *p, int p_max_size)
288 struct net_stat *ns = obj->data.opaque;
293 if (ns->link_qual_max > 0) {
294 spaced_print(p, p_max_size, "%.0f", 5,
295 (double) ns->link_qual /
296 ns->link_qual_max * 100);
298 spaced_print(p, p_max_size, "unk", 5);
301 void print_wireless_link_bar(struct text_object *obj, char *p, int p_max_size)
303 struct net_stat *ns = obj->data.opaque;
309 if(output_methods & TO_X) {
310 new_bar(obj, p, ((double) ns->link_qual /
311 ns->link_qual_max) * 255.0);
314 new_bar_in_shell(obj, p, p_max_size, ((double) ns->link_qual /
315 ns->link_qual_max) * 100.0);
317 #endif /* HAVE_IWLIB */
318 #endif /* __linux__ */
320 void clear_net_stats(void)
323 for (i = 0; i < MAX_NET_INTERFACES; i++) {
324 if (netstats[i].dev) {
325 free(netstats[i].dev);
328 memset(netstats, 0, sizeof(netstats));
331 void parse_if_up_arg(struct text_object *obj, const char *arg)
333 obj->data.opaque = strndup(arg, text_buffer_size);
336 void free_if_up(struct text_object *obj)
338 if (obj->data.opaque) {
339 free(obj->data.opaque);
340 obj->data.opaque = NULL;
344 /* We should check if this is ok with OpenBSD and NetBSD as well. */
345 int interface_up(struct text_object *obj)
349 char *dev = obj->data.opaque;
354 if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
355 CRIT_ERR(NULL, NULL, "could not create sockfd");
358 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
359 if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
360 /* if device does not exist, treat like not up */
361 if (errno != ENODEV && errno != ENXIO)
362 perror("SIOCGIFFLAGS");
366 if (!(ifr.ifr_flags & IFF_UP)) /* iface is not up */
368 if (ifup_strictness == IFUP_UP)
371 if (!(ifr.ifr_flags & IFF_RUNNING))
373 if (ifup_strictness == IFUP_LINK)
376 if (ioctl(fd, SIOCGIFADDR, &ifr)) {
377 perror("SIOCGIFADDR");
380 if (((struct sockaddr_in *)&(ifr.ifr_ifru.ifru_addr))->sin_addr.s_addr)
399 void free_dns_data(void)
402 for (i = 0; i < dns_data.nscount; i++)
403 free(dns_data.ns_list[i]);
404 if (dns_data.ns_list)
405 free(dns_data.ns_list);
406 memset(&dns_data, 0, sizeof(dns_data));
409 void update_dns_data(void)
413 //static double last_dns_update = 0.0;
415 /* maybe updating too often causes higher load because of /etc lying on a real FS
416 if (current_update_time - last_dns_update < 10.0)
419 last_dns_update = current_update_time;
424 if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
427 if (fgets(line, 255, fp) == NULL) {
430 if (!strncmp(line, "nameserver ", 11)) {
431 line[strlen(line) - 1] = '\0'; // remove trailing newline
433 dns_data.ns_list = realloc(dns_data.ns_list, dns_data.nscount * sizeof(char *));
434 dns_data.ns_list[dns_data.nscount - 1] = strndup(line + 11, text_buffer_size);
440 void parse_nameserver_arg(struct text_object *obj, const char *arg)
442 obj->data.l = arg ? atoi(arg) : 0;
445 void print_nameserver(struct text_object *obj, char *p, int p_max_size)
447 if (dns_data.nscount > obj->data.l)
448 snprintf(p, p_max_size, "%s", dns_data.ns_list[obj->data.l]);