1 /* GKrellM
2 |  Copyright (C) 1999-2019 Bill Wilson
3 |
4 |  Author:  Bill Wilson    billw@gkrellm.net
5 |  Latest versions might be found at:  http://gkrellm.net
6 |
7 |
8 |  GKrellM is free software: you can redistribute it and/or modify it
9 |  under the terms of the GNU General Public License as published by
10 |  the Free Software Foundation, either version 3 of the License, or
11 |  (at your option) any later version.
12 |
13 |  GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 |  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 |  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 |  License for more details.
17 |
18 |  You should have received a copy of the GNU General Public License
19 |  along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 |  Additional permission under GNU GPL version 3 section 7
23 |
24 |  If you modify this program, or any covered work, by linking or
25 |  combining it with the OpenSSL project's OpenSSL library (or a
26 |  modified version of that library), containing parts covered by
27 |  the terms of the OpenSSL or SSLeay licenses, you are granted
28 |  additional permission to convey the resulting work.
29 |  Corresponding Source for a non-source form of such a combination
30 |  shall include the source code for the parts of OpenSSL used as well
31 |  as that of the covered work.
32 */
33 
34 #include "gkrellm.h"
35 #include "gkrellm-sysdeps.h"
36 #include "gkrellm-private.h"
37 
38 #define	PPP_LOCK_FILE	"LCK..modem"
39 
40 #define TIMER_TYPE_NONE		0
41 #define TIMER_TYPE_PPP		1
42 #define TIMER_TYPE_IPPP		2
43 #define TIMER_TYPE_SERVER	3
44 
45 
46 #define		N_DAY_STATS		31
47 #define		N_WEEK_STATS	26
48 #define		N_MONTH_STATS	12
49 
50 typedef struct
51 	{
52 	gchar		*date;
53 	gdouble		rx,
54 				tx;
55 	gint		connect_time;
56 	}
57 	NetStat;
58 
59 enum StatType
60 	{
61 	DAY_STAT,
62 	WEEK_STAT,
63 	MONTH_STAT
64 	};
65 
66 
67 typedef struct
68 	{
69 	gchar			*name;
70 	GtkWidget		*vbox,
71 					*parent_vbox;
72 	GtkWidget		*enable_button,
73 					*force_button,
74 					*alert_button,
75 					*label_entry;
76 	GkrellmChart	*chart;
77 	GkrellmChartdata *rx_cd,
78 					*tx_cd;
79 	GkrellmDecal	*rxled,
80 					*txled;
81 
82 	/* All known net interfaces are in the net_mon_list.  Only interfaces
83 	|  which are up or forced up and are config enabled will actually have
84 	|  a chart created, unless the interface is linked to the timer button.
85 	|  A linked interface always has a chart created for it regardless
86 	|  of the up state but it will have a chart that may not be
87 	|  visible if the interface is down (ppp) or the connect state is
88 	|  hangup (ippp).
89 	*/
90 	gboolean	locked;		/* True if linked to timer button or forced up */
91 
92 	GkrellmChartconfig	*chart_config;
93 	gboolean			enabled,
94 						ignore,
95 						chart_labels,
96 						force_up,
97 						real;
98 
99 	gchar				*label;
100 
101 	GkrellmAlert		*alert;
102 	GtkWidget			*alert_config_rx_button,
103 						*alert_config_tx_button;
104 	gboolean			alert_uses_rx,
105 						alert_uses_tx;
106 
107 	gulong				rx_old,
108 						tx_old;
109 	gint				rx_current,
110 						tx_current;
111 	gdouble				rx_totalA,
112 						rx_totalB,
113 						tx_totalA,
114 						tx_totalB;
115 
116 	NetStat				day_stats[N_DAY_STATS],
117 						week_stats[N_WEEK_STATS],
118 						month_stats[N_MONTH_STATS];
119 
120 	gboolean			show_totalB,
121 						totals_shown,
122 						reset_button_in,
123 						stats_button_in,
124 						mouse_in_chart,
125 						new_text_format;
126 	GkrellmLauncher		launch;
127 	GtkWidget			*launch_entry,
128 						*tooltip_entry;
129 
130 	gboolean			up,
131 						up_prev,
132 						up_event,
133 						down_event;
134 
135 	gulong				rx,
136 						tx;
137 	}
138 	NetMon;
139 
140 
141 static void cb_alert_config(GkrellmAlert *ap, NetMon *net);
142 static void	cb_alert_config_create(GkrellmAlert *ap, GtkWidget *vbox,
143 					NetMon *net);
144 static void	net_stat_init(NetMon *net);
145 
146 typedef struct
147 	{
148 	gchar	*name;
149 	gint	type;
150 	}
151 	TimerType;
152 
153 
154 static GList	*net_mon_list;
155 static GList	*net_mon_sys_list;
156 static GList	*timer_defaults_list;
157 static gchar	*lock_directory;
158 static gchar	*net_data_dir;
159 static gchar	*net_ignore_patterns;
160 
161 static void		(*read_net_data)();
162 static void		(*check_net_routes)();
163 static gboolean	(*isdn_is_online)();
164 
165 static gboolean	net_use_routed;
166 static gboolean	net_config_use_routed;
167 
168 static gint		reset_mday;
169 
170 static gboolean		net_enabled_as_default;
171 static GtkWidget	*net_enabled_as_default_button;
172 
173 
174 static gint
strcmp_net_name(NetMon * net1,NetMon * net2)175 strcmp_net_name(NetMon *net1, NetMon *net2)
176 	{
177 	gchar	*s;
178 	gint	n, n1, n2, len;
179 
180 	for (s = net1->name; *s; ++s)
181 		if (isdigit((unsigned char)*s))
182 			break;
183 	if (!*s)
184 		return strcmp(net1->name, net2->name);
185 	n1 = atoi(s);
186 	len = s - net1->name;
187 	n = strncmp(net1->name, net2->name, len);
188 	if (n == 0)
189 		{
190 		n2 = atoi(net2->name + len);
191 		if (n1 < n2)
192 			n = -1;
193 		else if (n1 > n2)
194 			n = 1;
195 		}
196 	return n;
197 	}
198 
199 static gboolean
net_ignore_match(gchar * name)200 net_ignore_match(gchar *name)
201 	{
202 	GMatchInfo	*match_info;
203 	GRegex		*regex;
204 	gchar		*s, buf[128];
205 
206 	for (s = net_ignore_patterns; *s; )
207 		{
208 		while (*s == ' ')
209 			++s;
210 		if (sscanf(s, "%s", buf) == 1)
211 			{
212 			regex = g_regex_new(buf, G_REGEX_ANCHORED, 0, NULL);
213 			if (regex)
214 				{
215 				g_regex_match(regex, name, 0, &match_info);
216 				if (g_match_info_matches(match_info))
217 					{
218 					g_match_info_free(match_info);
219 					g_regex_unref(regex);
220 					return TRUE;
221 					}
222 				g_match_info_free(match_info);
223 				g_regex_unref(regex);
224 				}
225 			}
226 		while (*s != ' ' && *s != '\0')
227 			++s;
228 		}
229 	return FALSE;
230 	}
231 
232 static NetMon *
new_net(gchar * name)233 new_net(gchar *name)
234 	{
235 	NetMon	*net;
236 
237 	net = g_new0(NetMon, 1);
238 	net->name = g_strdup(name);
239 	if (strcmp(name, "lo"))		/* lo is disabled by default */
240 		net->enabled = net_enabled_as_default;		/* All others are enabled unless unset in configuration */
241 	if (net_ignore_match(name))
242 		{
243 		net->ignore = TRUE;
244 		net->enabled = FALSE;
245 		}
246 	net->chart_labels = TRUE;
247 	net->label = g_strdup("");
248 	net->launch.command = g_strdup("");
249 	net->launch.tooltip_comment = g_strdup("");
250 	net->alert_uses_rx = net->alert_uses_tx = TRUE;
251 	net_mon_list = g_list_insert_sorted(net_mon_list, net,
252 				(GCompareFunc) strcmp_net_name);
253 
254 	net_stat_init(net);
255 
256 	return net;
257 	}
258 
259 static NetMon	*
lookup_net(gchar * name)260 lookup_net(gchar *name)
261 	{
262 	NetMon	*net;
263 	GList	*list;
264 
265 	if (!name)
266 		return NULL;
267 	for (list = net_mon_list; list; list = list->next)
268 		{
269 		net = (NetMon *) list->data;
270 		if (!strcmp(net->name, name))
271 			return net;
272 		}
273 	return NULL;
274 	}
275 
276 /* ------------- Net monitor to system dependent interface ------------- */
277 
278 void
gkrellm_net_client_divert(void (* read_func)(),void (* check_routes)(),gboolean (* isdn_online_func)())279 gkrellm_net_client_divert(void (*read_func)(), void (*check_routes)(),
280 			gboolean (*isdn_online_func)())
281 	{
282 	read_net_data = read_func;
283 	check_net_routes = check_routes;
284 	isdn_is_online = isdn_online_func;
285 	}
286 
287 static gboolean
setup_net_interface(void)288 setup_net_interface(void)
289     {
290 	if (!read_net_data && !_GK.client_mode && gkrellm_sys_net_init())
291 		{
292 		read_net_data = gkrellm_sys_net_read_data;
293 		check_net_routes = gkrellm_sys_net_check_routes;
294 		isdn_is_online = gkrellm_sys_net_isdn_online;
295 		}
296 	return read_net_data ? TRUE : FALSE;
297 	}
298 
299 gchar *
gkrellm_net_mon_first(void)300 gkrellm_net_mon_first(void)
301 	{
302 	gchar	*name = NULL;
303 
304 	net_mon_sys_list = net_mon_list;
305 	if (net_mon_sys_list)
306 		{
307 		name = ((NetMon *) (net_mon_sys_list->data))->name;
308 		net_mon_sys_list = net_mon_sys_list->next;
309 		}
310 	return name;
311 	}
312 
313 gchar
gkrellm_net_mon_next(void)314 *gkrellm_net_mon_next(void)
315 	{
316 	gchar	*name = NULL;
317 
318 	if (net_mon_sys_list)
319 		{
320 		name = ((NetMon *) (net_mon_sys_list->data))->name;
321 		net_mon_sys_list = net_mon_sys_list->next;
322 		}
323 	return name;
324 	}
325 
326 void
gkrellm_net_use_routed(gboolean real_routed)327 gkrellm_net_use_routed(gboolean real_routed)
328 	{
329 	/* real_routed should only ever be FALSE when called from client.c to
330 	|  handle the server sysdep net code not using routed mode while the
331 	|  client <-> server interface will always use routed mode.
332 	*/
333 	net_use_routed = TRUE;
334 	net_config_use_routed = real_routed;
335 	}
336 
337 void
gkrellm_net_routed_event(gchar * name,gboolean routed)338 gkrellm_net_routed_event(gchar *name, gboolean routed)
339 	{
340 	NetMon	*net;
341 
342 	if (!net_use_routed)
343 		return;
344 	if ((net = lookup_net(name)) == NULL)
345 		net = new_net(name);
346 	if (!net)
347 		return;
348 
349 	if (routed)
350 		net->up_event = TRUE;
351 	else
352 		net->down_event = TRUE;
353 	net->up = routed;
354 	net->real = TRUE;
355 	}
356 
357 void
gkrellm_net_assign_data(gchar * name,gulong rx,gulong tx)358 gkrellm_net_assign_data(gchar *name, gulong rx, gulong tx)
359 	{
360 	NetMon	*net;
361 
362 	if ((net = lookup_net(name)) == NULL)
363 		net = new_net(name);
364 	if (!net || net->ignore)
365 		return;
366 
367 	if (GK.second_tick && !net_use_routed)
368 		net->up = TRUE;
369 	net->rx = rx;
370 	net->tx = tx;
371 	net->real = TRUE;
372 	}
373 
374 void
gkrellm_net_add_timer_type_ppp(gchar * name)375 gkrellm_net_add_timer_type_ppp(gchar *name)
376 	{
377 	TimerType	*t;
378 
379 	if (!name || !*name || _GK.client_mode)
380 		return;
381 	t = g_new0(TimerType, 1);
382 	t->name = g_strdup(name);
383 	t->type = TIMER_TYPE_PPP;
384 	timer_defaults_list = g_list_append(timer_defaults_list, t);
385 	}
386 
387 void
gkrellm_net_add_timer_type_ippp(gchar * name)388 gkrellm_net_add_timer_type_ippp(gchar *name)
389 	{
390 	TimerType	*t;
391 
392 	if (!name || !*name || _GK.client_mode)
393 		return;
394 	t = g_new0(TimerType, 1);
395 	t->name = g_strdup(name);
396 	t->type = TIMER_TYPE_IPPP;
397 	timer_defaults_list = g_list_append(timer_defaults_list, t);
398 	}
399 
400 void
gkrellm_net_set_lock_directory(gchar * dir)401 gkrellm_net_set_lock_directory(gchar *dir)
402 	{
403 	lock_directory = g_strdup(dir);
404 	}
405 
406 
407 /* ======================================================================== */
408 /* Exporting net data for plugins */
409 
410 gint
gkrellm_net_routes(void)411 gkrellm_net_routes(void)
412 	{
413 	return g_list_length(net_mon_list);
414 	}
415 
416 gboolean
gkrellm_net_stats(gint n,gchar * name,gulong * rx,gulong * tx)417 gkrellm_net_stats(gint n, gchar *name, gulong *rx, gulong *tx)
418 	{
419 	GList	*list;
420 	NetMon	*net;
421 
422 	list = g_list_nth(net_mon_list, n);
423 	if (!list)
424 		return FALSE;
425 	net = (NetMon *) list->data;
426 	if (name)
427 		strcpy(name, net->name);
428 	if (rx)
429 		*rx = net->rx;
430 	if (tx)
431 		*tx = net->tx;
432 	return TRUE;
433 	}
434 
435 void
gkrellm_net_led_positions(gint * x_rx_led,gint * y_rx_led,gint * x_tx_led,gint * y_tx_led)436 gkrellm_net_led_positions(gint *x_rx_led, gint *y_rx_led,
437 			gint *x_tx_led, gint *y_tx_led)
438 	{
439 	if (x_rx_led)
440 		*x_rx_led = _GK.rx_led_x;
441 	if (y_rx_led)
442 		*y_rx_led = _GK.rx_led_y;
443 	if (x_tx_led)
444 		*x_tx_led = _GK.tx_led_x;
445 	if (y_tx_led)
446 		*y_tx_led = _GK.tx_led_y;
447 	}
448 
449 /* ======================================================================== */
450 #include    "pixmaps/net/decal_net_leds.xpm"
451 #include    "pixmaps/timer/bg_timer.xpm"
452 #include    "pixmaps/timer/decal_timer_button.xpm"
453 
454 /* ISO 8601 date and month format strings for network stats gui*/
455 #ifdef WIN32
456 #define GK_NET_ISO_DATE "%Y-%m-%d"
457 #define GK_NET_MONTH_STAT_DATE "%b %d"
458 #else
459 #define GK_NET_ISO_DATE "%F"
460 #define GK_NET_MONTH_STAT_DATE "%b %e"
461 #endif
462 
463 #define	MIN_GRID_RES		5
464 #define	MAX_GRID_RES		500000000
465 #define	DEFAULT_GRID_RES 	20000
466 
467   /* States for the timer button are indexes to the corresponding
468   |  timer button decal frame shown.
469   */
470 #define	TB_NORMAL		0
471 #define	TB_PRESSED		1
472 #define	TB_STANDBY		2
473 #define	TB_ON			3
474 #define	N_TB_DECALS		4
475 
476 #define	RX_LED	0
477 #define	TX_LED	1
478 
479 #define	RX_OFF	0
480 #define	RX_ON	1
481 #define	TX_OFF	2
482 #define	TX_ON	3
483 #define	N_LEDS	4
484 
485 static GkrellmMonitor	*mon_net;
486 static GkrellmMonitor	*mon_timer;
487 
488 
489 static NetMon		*net_timed;		/* Monitor linked to timer button  */
490 
491 GkrellmPanel		*timer_panel;		/* For the timer and button	*/
492 
493 static GtkWidget	*net_vbox;		/* Where all net monitors live */
494 static GtkWidget	*dynamic_net_vbox;
495 static GtkWidget	*timer_vbox;
496 
497 static GkrellmPiximage *bg_timer_piximage,
498 					*decal_net_led_piximage,
499 					*decal_timer_button_piximage;
500 
501 static GkrellmStyle	*bg_timer_style;
502 
503 static GdkPixmap	*decal_net_led_pixmap;
504 static GdkBitmap	*decal_net_led_mask;
505 
506 static GdkPixmap	*decal_timer_button_pixmap;
507 static GdkBitmap	*decal_timer_button_mask;
508 
509 static GkrellmDecal	*time_decal,
510 					*seconds_decal,
511 					*button_decal;
512 
513   /* These 3 decals will be drawn on net charts when mouse is in a chart and
514   |  the chart has a rx and/or tx total drawn.  They won't live in a panel
515   |  so must be managed differently from decals on a panel.
516   */
517 static GkrellmDecal	*decal_totalA,
518 					*decal_totalB,
519 					*decal_reset;
520 static GkrellmDecal	*decal_stats;
521 
522 static gchar		*timer_on_command;
523 static gchar		*timer_off_command;
524 static gchar		*timer_button_iface;
525 static gint			timer_button_enabled;
526 static gint			last_time = -1;
527 
528 
529 static gint			timer_button_type = TIMER_TYPE_NONE,
530 					timer_button_state,
531 					timer_button_old_state,
532 					last_timer_command;
533 
534 static gboolean		timer_seconds;
535 
536 static gint			check_connect_state,
537 					net_stats_window_height;
538 
539 static gint			ascent,
540 					ascent_alt,
541 					sec_pad;
542 
543 static time_t		net_timer0;
544 
545 static gint			net_style_id,
546 					timer_style_id;
547 
548 static GkrellmSizeAbbrev    stats_bytes_abbrev[]    =
549 	{
550 	{ KB_SIZE(1),       1,              "%.0f" },
551 	{ KB_SIZE(10),      KB_SIZE(1),     "%.1fKB" },
552 	{ MB_SIZE(1),       KB_SIZE(1),     "%.2fKB" },
553 	{ MB_SIZE(10),      MB_SIZE(1),     "%.3fMB" },
554 	{ MB_SIZE(100),     MB_SIZE(1),     "%.2fMB" },
555 	{ GB_SIZE(1),       MB_SIZE(1),     "%.2fMB" },
556 	{ GB_SIZE(10),      GB_SIZE(1),     "%.3fGB" },
557 	{ GB_SIZE(100),     GB_SIZE(1),     "%.2fGB" },
558 	{ TB_SIZE(1),       GB_SIZE(1),     "%.2fGB" },
559 	{ TB_SIZE(10),      TB_SIZE(1),     "%.3fTB" },
560 	{ TB_SIZE(100),     TB_SIZE(1),     "%.3fTB" },
561 	{ TB_SIZE(1000),    TB_SIZE(1),     "%.2fTB" }
562 	};
563 
564 #define	NET_DATA_VERSION	2
565 
566 #define	SATURDAY	6
567 #define	SUNDAY		0
568 
569 static gchar	days_in_month[12] =
570 		{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  };
571 
572 
573   /* Called from client.c
574   */
575 void
gkrellm_net_server_has_timer(void)576 gkrellm_net_server_has_timer(void)
577 	{
578 	timer_button_type = TIMER_TYPE_SERVER;
579 	}
580 
581 static void
draw_led(NetMon * net,int rxtx,int led_index)582 draw_led(NetMon *net, int rxtx, int led_index)
583 	{
584 	GkrellmPanel	*p;
585 	GkrellmDecal	*led;
586 
587 	if (!net->chart)
588 		return;
589 	p = net->chart->panel;
590 	if (rxtx == RX_LED)
591 		led = net->rxled;
592 	else
593 		led = net->txled;
594 
595 	gkrellm_draw_decal_pixmap(p, led, led_index);
596 	}
597 
598 static void
draw_timer(GkrellmPanel * p,gint seconds,gint force)599 draw_timer(GkrellmPanel *p, gint seconds, gint force)
600 	{
601 	static gint	prev_minute = -1,
602 				prev_hour   = -1;
603 	gint		minutes, hours, w;
604 	gchar		buf[32], buf_sec[16];
605 
606 	last_time = seconds;
607 	hours = seconds / 60 / 60;
608 	minutes = (seconds / 60) % 60;
609 	seconds = seconds % 60;
610 	snprintf(buf, sizeof(buf), "%2d:%02d", hours, minutes);
611 	snprintf(buf_sec, sizeof(buf_sec), "%02d", seconds);
612 
613 	if (prev_minute != minutes || prev_hour != hours || force)
614 		{
615 		w = gkrellm_gdk_string_width(time_decal->text_style.font, buf);
616 		if (timer_seconds && w + seconds_decal->w + sec_pad <= time_decal->w)
617 			{
618 			time_decal->x_off = time_decal->w - w - seconds_decal->w - sec_pad
619 						- time_decal->text_style.effect;
620 			gkrellm_make_decal_visible(p, seconds_decal);
621 			}
622 		else
623 			{
624 			time_decal->x_off = time_decal->w - w
625 						- time_decal->text_style.effect;
626 			if (time_decal->x_off < 0)
627 				time_decal->x_off = 0;
628 			gkrellm_make_decal_invisible(p, seconds_decal);
629 			}
630 		}
631 	prev_minute = minutes;
632 	prev_hour = hours;
633 
634 	gkrellm_draw_decal_text(p, time_decal, buf,
635 				force ?  -1 : (hours * 60 + minutes));
636 
637 	if (gkrellm_is_decal_visible(seconds_decal))
638 		gkrellm_draw_decal_text(p, seconds_decal, buf_sec,
639 					force ? -1 : seconds);
640 
641 	gkrellm_draw_panel_layers(timer_panel);
642 	}
643 
644   /* --------- net stats window -----------
645   */
646 enum
647 	{
648 	DATE_COLUMN,
649 	RX_COLUMN,
650 	TX_COLUMN,
651 	TOTAL_COLUMN,
652 	TIME_COLUMN,
653 	N_STATS_COLUMNS
654 	};
655 
656 static GtkTreeModel *
stats_model_create(NetMon * net,NetStat * ns,gint n_stats)657 stats_model_create(NetMon *net, NetStat *ns, gint n_stats)
658 	{
659 	GtkListStore	*store;
660 	GtkTreeIter		iter;
661 	gchar			rx[64], tx[64], total[64], time[64];
662 	gint			i, hours, minutes;
663 
664 	store = gtk_list_store_new(N_STATS_COLUMNS,
665 				G_TYPE_STRING,
666 				G_TYPE_STRING,
667 				G_TYPE_STRING,
668 				G_TYPE_STRING,
669 				G_TYPE_STRING);
670 
671 	for (i = 0; i < n_stats; ++i, ++ns)
672 		{
673 		if (i > 0 && !strncmp(ns->date, "---", 3))
674 			continue;
675 		gkrellm_format_size_abbrev(rx, sizeof(rx), (gfloat) ns->rx,
676 					&stats_bytes_abbrev[0],
677 					sizeof(stats_bytes_abbrev) / sizeof(GkrellmSizeAbbrev));
678 		gkrellm_format_size_abbrev(tx, sizeof(tx), (gfloat) ns->tx,
679 					&stats_bytes_abbrev[0],
680 					sizeof(stats_bytes_abbrev) / sizeof(GkrellmSizeAbbrev));
681 		gkrellm_format_size_abbrev(total, sizeof(total),
682 					(gfloat) (ns->rx + ns->tx),
683 					&stats_bytes_abbrev[0],
684 					sizeof(stats_bytes_abbrev) / sizeof(GkrellmSizeAbbrev));
685 		minutes = ns->connect_time / 60;
686 		hours = minutes / 60;
687 		minutes %= 60;
688 		snprintf(time, sizeof(time), "%4d:%02d", hours, minutes);
689 
690 		gtk_list_store_append(store, &iter);
691 		gtk_list_store_set(store, &iter,
692 				DATE_COLUMN, ns->date,
693 				RX_COLUMN, rx,
694 				TX_COLUMN, tx,
695 				TOTAL_COLUMN, total,
696 				TIME_COLUMN, time,
697 				-1);
698 		}
699 	return GTK_TREE_MODEL(store);
700 	}
701 
702 static gint
net_stats_window_configure_cb(GtkWidget * widget,GdkEventConfigure * ev,gpointer data)703 net_stats_window_configure_cb(GtkWidget *widget, GdkEventConfigure *ev,
704 			gpointer data)
705 	{
706 	net_stats_window_height = widget->allocation.height;
707 	gkrellm_config_modified();
708 	return FALSE;
709 	}
710 
711 static void
net_stats_close_cb(GtkWidget * widget,GtkWidget * stats_window)712 net_stats_close_cb(GtkWidget *widget, GtkWidget *stats_window)
713 	{
714 	gtk_widget_destroy(stats_window);
715 	}
716 
717 static void
net_stats_page(GtkWidget * vbox,NetMon * net,NetStat * ns,gint n_stats,gchar * period)718 net_stats_page(GtkWidget *vbox, NetMon *net,
719 			NetStat *ns, gint n_stats, gchar *period)
720 	{
721 	GtkTreeView			*treeview;
722 	GtkTreeModel		*model;
723 	GtkCellRenderer		*renderer;
724 	gint				i;
725 
726 	model = stats_model_create(net, ns, n_stats);
727 	treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
728 	g_object_unref(model);
729 	gtk_tree_view_set_rules_hint(treeview, TRUE);
730 
731 	renderer = gtk_cell_renderer_text_new();
732 	gtk_tree_view_insert_column_with_attributes(treeview, -1, period,
733 			renderer, "text", DATE_COLUMN, NULL);
734 
735 	renderer = gtk_cell_renderer_text_new();
736 	gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Received"),
737 			renderer, "text", RX_COLUMN, NULL);
738 
739 	renderer = gtk_cell_renderer_text_new();
740 	gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Transmitted"),
741 			renderer, "text", TX_COLUMN, NULL);
742 
743 	renderer = gtk_cell_renderer_text_new();
744 	gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Total"),
745 			renderer, "text", TOTAL_COLUMN, NULL);
746 
747 	for (i = 0; i < n_stats; ++i)
748 		if (ns[i].connect_time > 0)
749 			{
750 			renderer = gtk_cell_renderer_text_new();
751 			gtk_tree_view_insert_column_with_attributes(treeview, -1,
752 					_("Connect Time"),
753 					renderer, "text", TIME_COLUMN, NULL);
754 			break;
755 			}
756 	gkrellm_gtk_scrolled_selection(treeview, vbox,
757 			GTK_SELECTION_NONE,
758 			GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC,
759 			NULL, NULL);
760 	}
761 
762 static void
net_stats_window_show(NetMon * net)763 net_stats_window_show(NetMon *net)
764 	{
765 	GtkWidget			*stats_window, *tabs, *main_vbox;
766 	GtkWidget			*vbox, *hbox, *button, *sep;
767 	gchar				buf[64];
768 
769 	snprintf(buf, sizeof(buf), _("%s Statistics"), net->name);
770 
771 	stats_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
772 	gtk_window_set_title(GTK_WINDOW(stats_window), buf);
773 	gtk_window_set_wmclass(GTK_WINDOW(stats_window),
774 				"Gkrellm_netstats", "Gkrellm");
775 
776 	g_signal_connect(G_OBJECT(stats_window), "configure_event",
777 				G_CALLBACK(net_stats_window_configure_cb), NULL);
778 	gtk_window_set_default_size(GTK_WINDOW(stats_window),
779 				-1, net_stats_window_height);
780 
781 	main_vbox = gtk_vbox_new(FALSE, 0);
782 	gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 4);
783 	gtk_container_add(GTK_CONTAINER(stats_window), main_vbox);
784 
785 	tabs = gtk_notebook_new();
786 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
787 	gtk_box_pack_start(GTK_BOX(main_vbox), tabs, TRUE, TRUE, 0);
788 
789 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Daily"));
790 	net_stats_page(vbox, net, &net->day_stats[0], N_DAY_STATS, _("Date"));
791 
792 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Weekly"));
793 	net_stats_page(vbox, net, &net->week_stats[0], N_WEEK_STATS,
794 				_("Week Ending"));
795 
796 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Monthly"));
797 	net_stats_page(vbox, net, &net->month_stats[0], N_MONTH_STATS,
798 				_("Month"));
799 
800 	sep = gtk_hseparator_new();
801 	gtk_box_pack_start(GTK_BOX(main_vbox), sep, FALSE, FALSE, 3);
802 
803 	hbox = gtk_hbutton_box_new();
804 	gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
805 	gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 4);
806 	button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
807 	g_signal_connect(G_OBJECT(button), "clicked",
808 			G_CALLBACK(net_stats_close_cb), stats_window);
809 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
810 
811 	gtk_widget_show_all(stats_window);
812 	}
813 
814 
815 static gint
get_connect_state(void)816 get_connect_state(void)
817 	{
818 	struct stat	st;
819 	gchar		buf[256];
820 	gint		state	= TB_NORMAL;
821 	static gint	old_state;
822 
823 	switch (timer_button_type)
824 		{
825 		case TIMER_TYPE_NONE:
826 		case TIMER_TYPE_SERVER:
827 			break;
828 		case TIMER_TYPE_PPP:
829 			if (net_timed->up)
830 				state = TB_ON;
831 			else if (lock_directory && *lock_directory)
832 				{
833 				snprintf(buf, sizeof(buf),
834 					 "%s/%s", lock_directory, PPP_LOCK_FILE);
835 				if (g_stat(buf, &st) == 0)
836 					state = TB_STANDBY;
837 				else
838 					{
839 					/* If lock file is ttySx, then user can make a link:
840 					|  ln -s ~/.gkrellm2/LCK..modem lock_directory/LCK..ttySx
841 					*/
842 					snprintf(buf, sizeof(buf), "%s/%s/%s",
843 								gkrellm_homedir(), GKRELLM_DIR, PPP_LOCK_FILE);
844 					if (g_stat(buf, &st) == 0)
845 						state = TB_STANDBY;
846 					}
847 				}
848 			break;
849 		case TIMER_TYPE_IPPP:
850 			if (isdn_is_online && (*isdn_is_online)())
851 				state = net_timed->up ? TB_ON : TB_STANDBY;
852 			break;
853 		}
854 	if ((_GK.debug_level & DEBUG_TIMER) && state != old_state)
855 		g_print(_("get_connect_state changed from %d to %d  (check=%d)\n"),
856 				old_state, state, check_connect_state);
857 	old_state = state;
858 	return state;
859 	}
860 
861 static void
get_connect_time(void)862 get_connect_time(void)
863 	{
864 	struct stat	st;
865 	gchar		buf[256];
866 	time_t		t	= 0;
867 
868 	switch (timer_button_type)
869 		{
870 		case TIMER_TYPE_NONE:
871 		case TIMER_TYPE_SERVER:
872 			break;
873 		case TIMER_TYPE_PPP:
874 			snprintf(buf, sizeof(buf), "/var/run/%s.pid", timer_button_iface);
875 			if (g_stat(buf, &st) == 0)
876 				t = st.st_mtime;
877 			break;
878 		case TIMER_TYPE_IPPP:
879 			break;
880 		}
881 	if (t > 0)
882 		net_timer0 = t;
883 	else
884 		time(&net_timer0);
885 	}
886 
887 static void
set_timer_button_state(gint decal_state)888 set_timer_button_state(gint decal_state)
889 	{
890 	timer_button_old_state = timer_button_state;
891 	timer_button_state = decal_state;
892 	gkrellm_draw_decal_pixmap(timer_panel, button_decal, decal_state);
893 	gkrellm_draw_panel_layers(timer_panel);
894 
895 	if (   (_GK.debug_level & DEBUG_TIMER)
896 		&& timer_button_state != timer_button_old_state
897 	   )
898 		g_print(_("set_timer_button_state from %d to %d (check=%d)\n"),
899 			timer_button_old_state, timer_button_state, check_connect_state);
900 	}
901 
902 static void
update_timer_button_monitor(void)903 update_timer_button_monitor(void)
904 	{
905 	if (timer_button_state == TB_PRESSED)
906 		return;
907 	if (   (_GK.debug_level & DEBUG_TIMER) && net_timed
908 		&& timer_button_type != TIMER_TYPE_NONE
909 		&& (net_timed->up_event || net_timed->down_event)
910 	   )
911 		g_print(_("update_timer_button net_timed old_state=%d new_state=%d\n"),
912 			   net_timed->up_event, net_timed->down_event);
913 	switch (timer_button_type)
914 		{
915 		case TIMER_TYPE_NONE:
916 			if (timer_button_state == TB_ON)
917 				draw_timer(timer_panel, (int) (time(0) - net_timer0), 0);
918 			break;
919 
920 		case TIMER_TYPE_PPP:
921 			if (net_timed->up)
922 				{
923 				set_timer_button_state(TB_ON);
924 				check_connect_state = FALSE;
925 				if (net_timed->up_event)
926 					get_connect_time();
927 				}
928 			else if (net_timed->down_event)
929 				set_timer_button_state(TB_NORMAL);
930 			if (check_connect_state)
931 				set_timer_button_state(get_connect_state());
932 
933 			if (net_timed->up)
934 				draw_timer(timer_panel, (int) (time(0) - net_timer0), 0);
935 			break;
936 
937 		case TIMER_TYPE_IPPP:
938 			/* get all isdn status from get_connect_state because the
939 			|  net_timed->up can be UP even with isdn line not connected.
940 			*/
941 			set_timer_button_state(get_connect_state());
942 			if (   timer_button_state != TB_NORMAL
943 				&& timer_button_old_state == TB_NORMAL
944 			   )
945 				time(&net_timer0);  /* New session just started */
946 			if (timer_button_state != TB_NORMAL)
947 				draw_timer(timer_panel, (int) (time(0) - net_timer0), 0);
948 			break;
949 
950 		case TIMER_TYPE_SERVER:
951 			/* Button state is independent of displayed timer
952 			*/
953 			draw_timer(timer_panel, gkrellm_client_server_get_net_timer(), 0);
954 			break;
955 		}
956 	if (net_timed && net_timed->up)
957 		{
958 		net_timed->day_stats[0].connect_time += 1;
959 		net_timed->week_stats[0].connect_time += 1;
960 		net_timed->month_stats[0].connect_time += 1;
961 		}
962 	}
963 
964 static void
stale_pppd_files_debug(void)965 stale_pppd_files_debug(void)
966 	{
967 	struct stat st;
968 	gchar	buf[256];
969 
970 	snprintf(buf, sizeof(buf), "/var/run/%s.pid", timer_button_iface);
971 	if (g_stat(buf, &st) == 0 && !net_timed->up)
972 		g_print(_("  **** Stale pppd pppX.pid file detected!\n"));
973 	}
974 
975 static gint
in_button(GkrellmDecal * d,GdkEventButton * ev)976 in_button(GkrellmDecal *d, GdkEventButton *ev)
977 	{
978 	if (ev->x > d->x && ev->x <= d->x + d->w)
979 		return TRUE;
980 	return FALSE;
981 	}
982 
983 static gint	save_tb_state;
984 
985 static gint
cb_timer_button_press(GtkWidget * widget,GdkEventButton * ev)986 cb_timer_button_press(GtkWidget *widget, GdkEventButton *ev)
987 	{
988 	if (ev->button != 1 || !in_button(DECAL(timer_panel), ev))
989 		return FALSE;
990 	if (timer_button_state != TB_PRESSED)		/* button bounce? */
991 		save_tb_state = timer_button_state;
992 	set_timer_button_state(TB_PRESSED);
993 	return FALSE;
994 	}
995 
996 static gint
cb_timer_button_release(GtkWidget * widget,GdkEventButton * ev)997 cb_timer_button_release(GtkWidget *widget, GdkEventButton *ev)
998 	{
999 	gint	tstate, timer_command;
1000 
1001 	if (timer_button_state != TB_PRESSED)
1002 		return FALSE;
1003 	set_timer_button_state(save_tb_state);
1004 	if (! in_button(DECAL(timer_panel), ev))
1005 		return FALSE;
1006 
1007 	switch (timer_button_type)
1008 		{
1009 		case TIMER_TYPE_NONE:
1010 		case TIMER_TYPE_SERVER:
1011 			if (timer_button_state == TB_NORMAL)
1012 				{
1013 				if (*timer_on_command != '\0')
1014 					g_spawn_command_line_async(timer_on_command, NULL);
1015 				set_timer_button_state(TB_ON);
1016 				time(&net_timer0);
1017 				}
1018 			else
1019 				{
1020 				if (*timer_off_command != '\0')
1021 					g_spawn_command_line_async(timer_off_command, NULL);
1022 				set_timer_button_state(TB_NORMAL);
1023 				}
1024 			break;
1025 
1026 		case TIMER_TYPE_PPP:
1027 		case TIMER_TYPE_IPPP:
1028 			check_connect_state = TRUE;
1029 			tstate = get_connect_state();
1030 			if (_GK.debug_level & DEBUG_TIMER)
1031 				stale_pppd_files_debug();
1032 			if (tstate == TB_NORMAL)
1033 				timer_command = ON;
1034 			else if (tstate == TB_ON)
1035 				timer_command = OFF;
1036 			else /* tstate == TB_STANDBY */
1037 				{
1038 				/* For some, pppd is leaving stale LCK..modem (and ppp0.pid)
1039 				|  files which can fool gkrellm.  So the question is, do I
1040 				|  launch off or on command here?  Since I can't trust
1041 				|  TB_STANDBY to mean pppd is running, I'll just base it on
1042 				|  state info.
1043 				*/
1044 				if (last_timer_command == ON)
1045 					{
1046 					timer_command = OFF;
1047 					if (timer_button_type == TIMER_TYPE_PPP)
1048 						set_timer_button_state(TB_NORMAL);
1049 					check_connect_state = FALSE;
1050 					draw_led(net_timed, RX_LED, RX_OFF);	/* Noise */
1051 					draw_led(net_timed, TX_LED, TX_OFF);
1052 					}
1053 				else
1054 					timer_command = ON;
1055 				}
1056 			if (timer_command == ON && *timer_on_command != '\0')
1057 					g_spawn_command_line_async(timer_on_command, NULL);
1058 			if (timer_command == OFF && *timer_off_command != '\0')
1059 					g_spawn_command_line_async(timer_off_command, NULL);
1060 			last_timer_command = timer_command;
1061 			break;
1062 		}
1063 	return FALSE;
1064 	}
1065 
1066 
1067   /* A timed_net (linked to the timer button) always has a panel
1068   |  visible, and the Chart visibility is toggled based on net up state.
1069   */
1070 static void
timed_net_visibility(void)1071 timed_net_visibility(void)
1072 	{
1073 	NetMon		*net = net_timed;
1074 	gboolean	net_is_up,
1075 				chart_is_visible;
1076 
1077 	if (!net || !net->chart)
1078 		return;
1079 	chart_is_visible = gkrellm_is_chart_visible(net->chart);
1080 
1081 	/* For ippp, the route may always be up, so base a up state on the
1082 	|  route being alive and the line status being connected (timer button
1083 	|  state)
1084 	*/
1085 	if (timer_button_type == TIMER_TYPE_IPPP)
1086 		net_is_up = (net->up && timer_button_state != TB_NORMAL);
1087 	else
1088 		net_is_up = net->up;
1089 
1090 	if ((net->force_up || net_is_up) && !chart_is_visible)
1091 		gkrellm_chart_show(net->chart, TRUE);	/* Make sure panel is shown */
1092 	else if (!net->force_up && !net_is_up && chart_is_visible)
1093 		{
1094 		gkrellm_chart_hide(net->chart, FALSE);  /* Don't hide the panel */
1095 
1096 		/* Save data whenever net has transitioned to a "not up" state.
1097 		|  Don't have the info to do this when there's a force_up and in
1098 		|  this case just rely on the every six hour tick data save.
1099 		*/
1100 		gkrellm_net_save_data();
1101 		}
1102 	}
1103 
1104 
1105 static gint
net_expose_event(GtkWidget * widget,GdkEventExpose * ev)1106 net_expose_event(GtkWidget *widget, GdkEventExpose *ev)
1107 	{
1108 	GList		*list;
1109 	NetMon		*net;
1110 	GdkPixmap	*pixmap	= NULL;
1111 
1112 	if (timer_panel->drawing_area == widget)
1113 		pixmap = timer_panel->pixmap;
1114 	else
1115 		for (list = net_mon_list; list; list = list->next)
1116 			{
1117 			net = (NetMon *) list->data;
1118 			if (!net->chart || !net->chart->panel)	/* A disabled iface */
1119 				continue;
1120 			if (net->chart->drawing_area == widget)
1121 				pixmap = net->chart->pixmap;
1122 			else if (net->chart->panel->drawing_area == widget)
1123 				pixmap = net->chart->panel->pixmap;
1124 			if (pixmap)
1125 				break;
1126 			}
1127 	if (pixmap)
1128 		gdk_draw_drawable(widget->window, gkrellm_draw_GC(1), pixmap,
1129 			ev->area.x, ev->area.y, ev->area.x, ev->area.y,
1130 			ev->area.width, ev->area.height);
1131 	return FALSE;
1132 	}
1133 
1134 static gint
map_x(gint x,gint width)1135 map_x(gint x, gint width)
1136 	{
1137 	gint	xnew, chart_width;
1138 
1139 	xnew = x;
1140 	chart_width = gkrellm_chart_width();
1141 	if (x < 0)
1142 		xnew += chart_width - width;
1143 	return xnew;
1144 	}
1145 
1146 static gint
grid_resolution_default(NetMon * net)1147 grid_resolution_default(NetMon *net)
1148 	{
1149 	gchar	*s 	= net->name;
1150 	gint	res;
1151 
1152 	if (! strncmp(s, "ppp", 3))
1153 		res = 2000;
1154 #if defined(__FreeBSD__)
1155 	else if (! strncmp(s, "tun", 3))
1156 		res = 2000;
1157 #endif
1158 	else if (! strncmp(s, "plip", 3) || ! strncmp(s, "ippp", 4))
1159 		res = 5000;
1160 	else if (! strncmp(s, "eth", 3))
1161 		res = 20000;
1162 	else
1163 		res = 10000;
1164 	return res;
1165 	}
1166 
1167 static void
setup_net_scaling(GkrellmChartconfig * cf,NetMon * net)1168 setup_net_scaling(GkrellmChartconfig *cf, NetMon *net)
1169 	{
1170 	GkrellmChart	*cp  = net->chart;
1171 	gint	grids, res;
1172 
1173 	grids = gkrellm_get_chartconfig_fixed_grids(cf);
1174 	if (!grids)
1175 		grids = FULL_SCALE_GRIDS;
1176 
1177 	res = gkrellm_get_chartconfig_grid_resolution(cf);
1178 	KRELL(cp->panel)->full_scale = res * grids / gkrellm_update_HZ();
1179 	}
1180 
1181 static void
destroy_chart(NetMon * net)1182 destroy_chart(NetMon *net)
1183 	{
1184 	GkrellmChart	*cp;
1185 
1186 	if (!net)
1187 		return;
1188 	cp = net->chart;
1189 	if (cp)
1190 		{
1191 		net->launch.button = NULL;
1192 		g_free(cp->panel->textstyle);
1193 		cp->panel->textstyle = NULL;
1194 		gkrellm_chart_destroy(cp);
1195 		gtk_widget_destroy(net->vbox);
1196 		net->chart = NULL;
1197 		net->vbox = NULL;
1198 		net->parent_vbox = NULL;
1199 		}
1200 	net->locked = FALSE;
1201 	}
1202 
1203 
1204 static GkrellmSizeAbbrev	current_bytes_abbrev[]	=
1205 	{
1206 	{ KB_SIZE(1),		1,				"%.0f" },
1207 	{ KB_SIZE(20),		KB_SIZE(1),		"%.1fK" },
1208 	{ MB_SIZE(1),		KB_SIZE(1),		"%.0fK" },
1209 	{ MB_SIZE(20),		MB_SIZE(1),		"%.1fM" },
1210 	{ GB_SIZE(1),		MB_SIZE(1),		"%.0fM" },
1211 	{ GB_SIZE(20),		GB_SIZE(1),		"%.1fG" },
1212 	{ TB_SIZE(1),		GB_SIZE(1),		"%.0fG" },
1213 	{ TB_SIZE(20),		TB_SIZE(1),		"%.1fT" },
1214 	{ TB_SIZE(1000),	TB_SIZE(1),		"%.0fT" }
1215 	};
1216 
1217 static GkrellmSizeAbbrev	total_bytes_abbrev[]	=
1218 	{
1219 	{ KB_SIZE(100),		1,				"%.0f" },
1220 	{ MB_SIZE(1),		KB_SIZE(1),		"%.1fK" },
1221 	{ MB_SIZE(10),		MB_SIZE(1),		"%.3fM" },
1222 	{ MB_SIZE(100),		MB_SIZE(1),		"%.2fM" },
1223 	{ GB_SIZE(1),		MB_SIZE(1),		"%.1fM" },
1224 	{ GB_SIZE(10),		GB_SIZE(1),		"%.3fG" },
1225 	{ GB_SIZE(100),		GB_SIZE(1),		"%.2fG" },
1226 	{ TB_SIZE(1),		GB_SIZE(1),		"%.1fG" },
1227 	{ TB_SIZE(10),		TB_SIZE(1),		"%.3fT" },
1228 	{ TB_SIZE(100),		TB_SIZE(1),		"%.2fT" },
1229 	{ TB_SIZE(1000),	TB_SIZE(1),		"%.1fT" }
1230 	};
1231 
1232 #define	DEFAULT_TEXT_FORMAT	"$T\\b\\c\\f$L"
1233 
1234 static gchar    *text_format,
1235 				*text_format_locale;
1236 
1237 static void
format_net_data(NetMon * net,gchar * src_string,gchar * buf,gint size)1238 format_net_data(NetMon *net, gchar *src_string, gchar *buf, gint size)
1239 	{
1240 	GkrellmChart	*cp;
1241 	gchar			c, *s, *s1, *result;
1242 	gint			len, bytes;
1243 	gdouble			fbytes;
1244 	gboolean		month, day, week;
1245 
1246 	if (!buf || size < 1)
1247 		return;
1248 	--size;
1249 	*buf = '\0';
1250 	result = buf;
1251 
1252 	if (!src_string)
1253 		return;
1254 	cp = net->chart;
1255 	net->totals_shown = FALSE;
1256 
1257 	gkrellm_debug(DEBUG_CHART_TEXT, "net chart text: %s\n", src_string);
1258 
1259 	for (s = src_string; *s != '\0' && size > 0; ++s)
1260 		{
1261 		len = 1;
1262 		month = week = day = FALSE;
1263 		if (*s == '$' && *(s + 1) != '\0')
1264 			{
1265 			bytes = -1;
1266 			fbytes = -1.0;
1267 			if ((c = *(s + 2)) == 'm')	/* cumulative modifiers */
1268 				month = TRUE;
1269 			else if (c == 'w')
1270 				week = TRUE;
1271 			else if (c == 'd')
1272 				day = TRUE;
1273 
1274 			if ((c = *(s + 1)) == 'T')
1275 				bytes = net->rx_current + net->tx_current;
1276 			else if (c == 'M')
1277 				bytes = gkrellm_get_chart_scalemax(cp);
1278 			else if (c == 't')
1279 				bytes = net->tx_current;
1280 			else if (c == 'r')
1281 				bytes = net->rx_current;
1282 			else if (c == 'o')
1283 				{
1284 				if (month)
1285 					fbytes = net->month_stats[0].tx;
1286 				else if (week)
1287 					fbytes = net->week_stats[0].tx;
1288 				else if (day)
1289 					fbytes = net->day_stats[0].tx;
1290 				else
1291 					fbytes = net->show_totalB
1292 								? net->tx_totalB : net->tx_totalA;
1293 				}
1294 			else if (c == 'i')
1295 				{
1296 				if (month)
1297 					fbytes = net->month_stats[0].rx;
1298 				else if (week)
1299 					fbytes = net->week_stats[0].rx;
1300 				else if (day)
1301 					fbytes = net->day_stats[0].rx;
1302 				else
1303 					fbytes = net->show_totalB
1304 								? net->rx_totalB : net->rx_totalA;
1305 				}
1306 			else if (c == 'O')
1307 				{
1308 				if (month)
1309 					fbytes = net->month_stats[0].rx + net->month_stats[0].tx;
1310 				else if (week)
1311 					fbytes = net->week_stats[0].rx + net->week_stats[0].tx;
1312 				else if (day)
1313 					fbytes = net->day_stats[0].rx + net->day_stats[0].tx;
1314 				else
1315 					fbytes = net->show_totalB
1316 							? (net->rx_totalB + net->tx_totalB)
1317 							: (net->rx_totalA + net->tx_totalA);
1318 				}
1319 			else if (c == 'L')
1320 				{
1321 				if (!*(net->label))
1322 					s1 = " ";
1323 				else
1324 					s1 = net->label;
1325 				len = snprintf(buf, size, "%s", s1);
1326 				}
1327 			else if (c == 'I')
1328 				len = snprintf(buf, size, "%s", net->name);
1329 			else if (c == 'H')
1330 				len = snprintf(buf, size, "%s", gkrellm_sys_get_host_name());
1331 			else if ((s1 = gkrellm_plugin_get_exported_label(mon_net, c,
1332 						net->name)) != NULL)
1333 				len = snprintf(buf, size, "%s", s1);
1334 			else
1335 				{
1336 				*buf = *s;
1337 				if (size > 1)
1338 					{
1339 					*(buf + 1) = *(s + 1);
1340 					++len;
1341 					}
1342 				}
1343 			if (bytes >= 0)
1344 				len = gkrellm_format_size_abbrev(buf, size, (gfloat) bytes,
1345 					&current_bytes_abbrev[0],
1346 					sizeof(current_bytes_abbrev) / sizeof(GkrellmSizeAbbrev));
1347 			else if (fbytes >= 0)
1348 				{
1349 				len = gkrellm_format_size_abbrev(buf, size, (gfloat) fbytes,
1350 					&total_bytes_abbrev[0],
1351 					sizeof(total_bytes_abbrev) /sizeof(GkrellmSizeAbbrev));
1352 				if (!day && !week && !month)
1353 					net->totals_shown = TRUE;
1354 				}
1355 			++s;
1356 			if (day || week || month)
1357 				++s;
1358 			}
1359 		else
1360 			*buf = *s;
1361 		size -= len;
1362 		buf += len;
1363 		}
1364 	*buf = '\0';
1365 
1366 	gkrellm_debug(DEBUG_CHART_TEXT, "              : %s\n", result);
1367 	}
1368 
1369 static void
draw_net_chart_labels(NetMon * net)1370 draw_net_chart_labels(NetMon *net)
1371 	{
1372 	GkrellmChart		*cp = net->chart;
1373 	gchar		buf[128];
1374 
1375 	if (!net->chart_labels)
1376 		return;
1377 	format_net_data(net, text_format_locale, buf, sizeof(buf));
1378 	if (!net->new_text_format)
1379 		gkrellm_chart_reuse_text_format(cp);
1380 	net->new_text_format = FALSE;
1381 	gkrellm_draw_chart_text(cp, net_style_id, buf);
1382 	}
1383 
1384 static void
cb_command_process(GkrellmAlert * alert,gchar * src,gchar * dst,gint len,NetMon * net)1385 cb_command_process(GkrellmAlert *alert, gchar *src, gchar *dst, gint len,
1386 			NetMon *net)
1387 	{
1388 	format_net_data(net, src, dst, len);
1389 	}
1390 
1391 static void
draw_chart_buttons(NetMon * net)1392 draw_chart_buttons(NetMon *net)
1393 	{
1394 	gint	frame, x, y;
1395 
1396 	if (   net->totals_shown && net->chart_labels
1397 		&& decal_totalA && decal_totalB && decal_reset
1398 	   )
1399 		{
1400 		x = gkrellm_chart_width() - 2 * decal_totalA->w;
1401 		y = 2;
1402 
1403 		frame = net->show_totalB ? D_MISC_BUTTON_OUT : D_MISC_BUTTON_IN;
1404 		gkrellm_draw_decal_pixmap(NULL, decal_totalA, frame);
1405 		gkrellm_draw_decal_on_chart(net->chart, decal_totalA, x, y);
1406 
1407 		frame = net->show_totalB ? D_MISC_BUTTON_IN : D_MISC_BUTTON_OUT;
1408 		gkrellm_draw_decal_pixmap(NULL, decal_totalB, frame);
1409 		gkrellm_draw_decal_on_chart(net->chart, decal_totalB,
1410 					x + decal_totalA->w, y);
1411 
1412 		frame = net->reset_button_in ? D_MISC_BUTTON_IN : D_MISC_BUTTON_OUT;
1413 		gkrellm_draw_decal_pixmap(NULL, decal_reset, frame);
1414 		gkrellm_draw_decal_on_chart(net->chart, decal_reset,
1415 					x + decal_totalA->w, y + decal_totalA->h + 4);
1416 		}
1417 	if (decal_stats)
1418 		{
1419 		x = gkrellm_chart_width() - decal_stats->w;
1420 		y = net->chart->h - decal_stats->h;
1421 		frame = net->stats_button_in ? D_MISC_BUTTON_IN : D_MISC_BUTTON_OUT;
1422 		gkrellm_draw_decal_pixmap(NULL, decal_stats, frame);
1423 		gkrellm_draw_decal_on_chart(net->chart, decal_stats, x, y);
1424 		}
1425 	}
1426 
1427 static void
refresh_net_chart(NetMon * net)1428 refresh_net_chart(NetMon *net)
1429 	{
1430 	if (!net->chart)
1431 		return;
1432 	gkrellm_draw_chartdata(net->chart);
1433 	draw_net_chart_labels(net);
1434 	if (net->mouse_in_chart)
1435 		draw_chart_buttons(net);
1436 	gkrellm_draw_chart_to_screen(net->chart);
1437 	}
1438 
1439 
1440 static gint
cb_chart_press(GtkWidget * widget,GdkEventButton * ev,NetMon * net)1441 cb_chart_press(GtkWidget *widget, GdkEventButton *ev, NetMon *net)
1442 	{
1443 	gboolean	check_button;
1444 
1445 	check_button = net->chart_labels && net->totals_shown;
1446 	if (check_button && gkrellm_in_decal(decal_totalA, ev))
1447 		{
1448 		net->show_totalB = FALSE;
1449 		refresh_net_chart(net);
1450 		}
1451 	else if (check_button && gkrellm_in_decal(decal_totalB, ev))
1452 		{
1453 		net->show_totalB = TRUE;
1454 		refresh_net_chart(net);
1455 		}
1456 	else if (check_button && gkrellm_in_decal(decal_reset, ev))
1457 		{
1458 		net->reset_button_in = TRUE;
1459 		refresh_net_chart(net);
1460 		}
1461 	else if (gkrellm_in_decal(decal_stats, ev))
1462 		{
1463 		net->stats_button_in = TRUE;
1464 		refresh_net_chart(net);
1465 		}
1466 	else if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS)
1467 		{
1468 		net->chart_labels = !net->chart_labels;
1469 		gkrellm_config_modified();
1470 		refresh_net_chart(net);
1471 		}
1472 	else if (   ev->button == 3
1473 			 || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)
1474 			)
1475 			gkrellm_chartconfig_window_create(net->chart);
1476 
1477 	return FALSE;
1478 	}
1479 
1480 static gint
cb_chart_release(GtkWidget * widget,GdkEventButton * ev,NetMon * net)1481 cb_chart_release(GtkWidget *widget, GdkEventButton *ev, NetMon *net)
1482 	{
1483 	if (!net->reset_button_in && !net->stats_button_in)
1484 		return FALSE;
1485 	if (net->stats_button_in && gkrellm_in_decal(decal_stats, ev))
1486 		net_stats_window_show(net);
1487 	if (net->reset_button_in && gkrellm_in_decal(decal_reset, ev))
1488 		{
1489 		if (net->show_totalB)
1490 			net->rx_totalB = net->tx_totalB = 0;
1491 		else
1492 			net->rx_totalA = net->tx_totalA = 0;
1493 		}
1494 	net->reset_button_in = FALSE;
1495 	net->stats_button_in = FALSE;
1496 	refresh_net_chart(net);
1497 	return FALSE;
1498 	}
1499 
1500 static gint
cb_chart_enter(GtkWidget * w,GdkEventButton * ev,NetMon * net)1501 cb_chart_enter(GtkWidget *w, GdkEventButton *ev, NetMon *net)
1502 	{
1503 	net->mouse_in_chart = TRUE;
1504 	draw_chart_buttons(net);
1505 	gkrellm_draw_chart_to_screen(net->chart);
1506 	return FALSE;
1507 	}
1508 
1509 static gint
cb_chart_leave(GtkWidget * w,GdkEventButton * ev,NetMon * net)1510 cb_chart_leave(GtkWidget *w, GdkEventButton *ev, NetMon *net)
1511 	{
1512 	net->mouse_in_chart = FALSE;
1513 	net->reset_button_in = FALSE;
1514 	net->stats_button_in = FALSE;
1515 	refresh_net_chart(net);
1516 	return FALSE;
1517 	}
1518 
1519 static gint
cb_panel_press(GtkWidget * widget,GdkEventButton * ev)1520 cb_panel_press(GtkWidget *widget, GdkEventButton *ev)
1521 	{
1522 	if (ev->button == 3)
1523 		gkrellm_open_config_window(mon_net);
1524 	return FALSE;
1525 	}
1526 
1527   /* Make sure net charts appear in same order as the sorted net_mon_list
1528   */
1529 static void
net_chart_reorder(NetMon * new_net)1530 net_chart_reorder(NetMon *new_net)
1531 	{
1532 	NetMon		*net;
1533 	GList		*list;
1534 	gint		i;
1535 
1536 	for (i = 0, list = net_mon_list; list; list = list->next)
1537 		{
1538 		net = (NetMon *) list->data;
1539 		if (net->parent_vbox != new_net->parent_vbox)
1540 			continue;
1541 		if (net == new_net)
1542 			break;
1543 		++i;
1544 		}
1545 	if (!list || !list->next)
1546 		return;
1547 	gtk_box_reorder_child(GTK_BOX(new_net->parent_vbox), new_net->vbox, i);
1548 	}
1549 
1550 static void
create_net_monitor(GtkWidget * vbox,NetMon * net,gint first_create)1551 create_net_monitor(GtkWidget *vbox, NetMon *net, gint first_create)
1552 	{
1553 	GkrellmStyle	*style;
1554 	GkrellmChart	*cp;
1555 	GkrellmPanel	*p;
1556 
1557 	if (first_create)
1558 		{
1559 		net->parent_vbox = vbox;
1560 		net->vbox = gtk_vbox_new(FALSE, 0);
1561 		gtk_box_pack_start(GTK_BOX(vbox), net->vbox, FALSE, FALSE, 0);
1562 
1563 		net->chart = gkrellm_chart_new0();
1564 		net->chart->panel = gkrellm_panel_new0();
1565 		net->chart->panel->textstyle = gkrellm_textstyle_new0();
1566 		net_chart_reorder(net);
1567 		}
1568 	cp = net->chart;
1569 	p = cp->panel;
1570 
1571 	gkrellm_chart_create(net->vbox, mon_net, cp, &net->chart_config);
1572 	net->tx_cd = gkrellm_add_default_chartdata(cp, _("tx bytes"));
1573 	net->rx_cd = gkrellm_add_default_chartdata(cp, _("rx bytes"));
1574 	gkrellm_set_draw_chart_function(cp, refresh_net_chart, net);
1575 
1576     gkrellm_chartconfig_fixed_grids_connect(cp->config,
1577                 setup_net_scaling, net);
1578     gkrellm_chartconfig_grid_resolution_connect(cp->config,
1579                 setup_net_scaling, net);
1580     gkrellm_chartconfig_grid_resolution_adjustment(cp->config, TRUE,
1581                 0, (gfloat) MIN_GRID_RES, (gfloat) MAX_GRID_RES, 0, 0, 0, 0);
1582 
1583     gkrellm_chartconfig_grid_resolution_label(cp->config,
1584                 _("rx/tx bytes per sec"));
1585     if (gkrellm_get_chartconfig_grid_resolution(cp->config) < MIN_GRID_RES)
1586         gkrellm_set_chartconfig_grid_resolution(cp->config,
1587 				grid_resolution_default(net));
1588     gkrellm_alloc_chartdata(cp);
1589 
1590 	style = gkrellm_panel_style(net_style_id);
1591 	gkrellm_create_krell(p, gkrellm_krell_panel_piximage(net_style_id), style);
1592 
1593 	net->rxled = gkrellm_create_decal_pixmap(p, decal_net_led_pixmap,
1594 				decal_net_led_mask, N_LEDS, style, 0, _GK.rx_led_y);
1595 	net->rxled->x = map_x(_GK.rx_led_x, net->rxled->w);
1596 
1597 	net->txled = gkrellm_create_decal_pixmap(p, decal_net_led_pixmap,
1598 				decal_net_led_mask, N_LEDS, style, 0, _GK.tx_led_y);
1599 	net->txled->x = map_x(_GK.tx_led_x, net->txled->w);
1600 
1601 	*(p->textstyle) = *gkrellm_panel_textstyle(net_style_id);
1602 	if (strlen(net->name) > 5)
1603 		p->textstyle->font = gkrellm_panel_alt_textstyle(net_style_id)->font;
1604 
1605 	gkrellm_panel_configure(p, net->name, style);
1606 	gkrellm_panel_create(net->vbox, mon_net, p);
1607 
1608 	setup_net_scaling(cp->config, net);
1609 
1610 	net->new_text_format = TRUE;
1611 	if (first_create)
1612 		{
1613 		g_signal_connect(G_OBJECT (cp->drawing_area), "expose_event",
1614 					G_CALLBACK(net_expose_event), NULL);
1615 		g_signal_connect(G_OBJECT(cp->drawing_area), "button_press_event",
1616 					G_CALLBACK(cb_chart_press), net);
1617 		g_signal_connect(G_OBJECT(cp->drawing_area), "button_release_event",
1618 					G_CALLBACK(cb_chart_release), net);
1619 		g_signal_connect(G_OBJECT(cp->drawing_area), "enter_notify_event",
1620 					G_CALLBACK(cb_chart_enter), net);
1621 		g_signal_connect(G_OBJECT(cp->drawing_area), "leave_notify_event",
1622 					G_CALLBACK(cb_chart_leave), net);
1623 
1624 		g_signal_connect(G_OBJECT (p->drawing_area), "expose_event",
1625 					G_CALLBACK(net_expose_event), NULL);
1626 		g_signal_connect(G_OBJECT(p->drawing_area), "button_press_event",
1627 					G_CALLBACK(cb_panel_press), NULL);
1628 
1629 		gtk_widget_show_all(net->vbox);
1630 		}
1631 	else
1632 		refresh_net_chart(net);
1633 
1634 	gkrellm_setup_launcher(p, &net->launch, CHART_PANEL_TYPE, 0);
1635 
1636 	draw_led(net, RX_LED, RX_OFF);
1637 	draw_led(net, TX_LED, TX_OFF);
1638 
1639 	if (net->force_up)
1640 		net->locked = TRUE;
1641 	}
1642 
1643 static void
net_timer_visibility(void)1644 net_timer_visibility(void)
1645 	{
1646 	if (timer_button_enabled)
1647 		{
1648 		gkrellm_panel_show(timer_panel);
1649 		gkrellm_spacers_show(mon_timer);
1650 		}
1651 	else
1652 		{
1653 		gkrellm_panel_hide(timer_panel);
1654 		gkrellm_spacers_hide(mon_timer);
1655 		}
1656 	}
1657 
1658 
1659 static gint
days_in_year(gint y)1660 days_in_year(gint y)
1661 	{
1662 	if((y % 4) == 0)
1663 		return 366;
1664 	return 365;
1665 	}
1666 
1667   /* Adjust a tm date structure to reference its next day.
1668   */
1669 static void
next_day(struct tm * t)1670 next_day(struct tm *t)
1671 	{
1672 	if ((t->tm_wday += 1) > SATURDAY)
1673 		t->tm_wday = SUNDAY;
1674 	if ((t->tm_yday += 1) >= days_in_year(t->tm_year) )
1675 		{
1676 		t->tm_year += 1;
1677 		t->tm_yday = 0;
1678 		}
1679 	if ((t->tm_mday += 1) > days_in_month[t->tm_mon])
1680 		{
1681 		if (   t->tm_mon == 1
1682 		    && (((gint)t->tm_year - 80) % 4) == 0
1683 		    && t->tm_mday == 29)
1684 			;
1685 		else
1686 			{
1687 			if ((t->tm_mon += 1) > 11)
1688 				t->tm_mon = 0;
1689 			t->tm_mday = 1;
1690 			}
1691 		}
1692 	}
1693 
1694 static gboolean
net_accounting_month_new(struct tm * tm)1695 net_accounting_month_new(struct tm *tm)
1696 	{
1697 	if (   tm->tm_mday == reset_mday
1698 		|| (   reset_mday > days_in_month[tm->tm_mon]
1699 			&& tm->tm_mday == 1
1700 		   )
1701 	   )
1702 		return TRUE;
1703 	return FALSE;
1704 	}
1705 
1706 void
gkrellm_net_save_data(void)1707 gkrellm_net_save_data(void)
1708 	{
1709 	FILE		*f;
1710 	GList		*list;
1711 	struct tm	*tm  = gkrellm_get_current_time();
1712 	NetMon		*net;
1713 	gchar		fname[256];
1714 	gint		i;
1715 
1716 	for (list = net_mon_list; list; list = list->next)
1717 		{
1718 		net = (NetMon *) list->data;
1719 		if (!net->enabled)
1720 			continue;
1721 		snprintf(fname, sizeof(fname), "%s%c%s", net_data_dir,
1722 					G_DIR_SEPARATOR, net->name);
1723 		if ((f = g_fopen(fname, "w")) == NULL)
1724 			continue;
1725 		fprintf(f, "%d\n", NET_DATA_VERSION);
1726 		fputs("wday mday month yday year\n", f);
1727 		fprintf(f, "%d %d %d %d %d\n", tm->tm_wday,
1728 					tm->tm_mday, tm->tm_mon, tm->tm_yday, tm->tm_year);
1729 
1730 		fputs("[daily]\n", f);
1731 		for (i = 0; i < N_DAY_STATS; ++i)
1732 			fprintf(f, "\"%s\" %.0f %.0f %d\n", net->day_stats[i].date,
1733 					net->day_stats[i].rx, net->day_stats[i].tx,
1734 					net->day_stats[i].connect_time);
1735 		fputs("[weekly]\n", f);
1736 		for (i = 0; i < N_WEEK_STATS; ++i)
1737 			fprintf(f, "\"%s\" %.0f %.0f %d\n", net->week_stats[i].date,
1738 					net->week_stats[i].rx, net->week_stats[i].tx,
1739 					net->week_stats[i].connect_time);
1740 		fputs("[monthly]\n", f);
1741 			for (i = 0; i < N_MONTH_STATS; ++i)
1742 		fprintf(f, "\"%s\" %.0f %.0f %d\n", net->month_stats[i].date,
1743 					net->month_stats[i].rx, net->month_stats[i].tx,
1744 					net->month_stats[i].connect_time);
1745 		fclose(f);
1746 		}
1747 	}
1748 
1749 static gchar *
utf8_string(gchar * string)1750 utf8_string(gchar *string)
1751 	{
1752 	gchar	*utf8 = NULL;
1753 
1754 	if (   g_utf8_validate(string, -1, NULL)
1755 	    || (utf8 = g_locale_to_utf8(string, -1, NULL, NULL, NULL)) == NULL
1756 	   )
1757 		utf8 = g_strdup(string);
1758 
1759 	return utf8;
1760 	}
1761 
1762 static void
net_stat_set_date_string(NetStat * ns,enum StatType stat_type,struct tm * t)1763 net_stat_set_date_string(NetStat *ns, enum StatType stat_type, struct tm *t)
1764 	{
1765 	struct tm	tm  = *t,
1766 				tmx;
1767 	gchar		*utf8, buf[128], bufa[32], bufb[32];
1768 
1769 	if (stat_type == DAY_STAT)
1770 		{
1771 		strftime(buf, sizeof(buf), GK_NET_ISO_DATE, &tm);
1772 		}
1773 	else if (stat_type == WEEK_STAT)
1774 		{
1775 		while (tm.tm_wday != SATURDAY)
1776 			next_day(&tm);
1777 		strftime(buf, sizeof(buf), GK_NET_ISO_DATE, &tm);
1778 		}
1779 	else if (stat_type == MONTH_STAT)
1780 		{
1781 		if (reset_mday == 1)
1782 			strftime(buf, sizeof(buf), "%B", &tm);	/* full month name */
1783 		else
1784 			{
1785 			tmx = tm;
1786 			if (tm.tm_mday < reset_mday)
1787 				{
1788 				tmx.tm_mon -= 1;
1789 				if (tmx.tm_mon < 0)
1790 					{
1791 					tmx.tm_mon = 11;
1792 					tmx.tm_year -= 1;
1793 					}
1794 				}
1795 			else
1796 				{
1797 				tm.tm_mon += 1;
1798 				if (tm.tm_mon > 11)
1799 					{
1800 					tm.tm_mon = 0;
1801 					tm.tm_year += 1;
1802 					}
1803 				}
1804 			tmx.tm_mday = reset_mday;
1805 			tm.tm_mday = reset_mday - 1;
1806 			if (tmx.tm_mday > days_in_month[tmx.tm_mon])
1807 				tmx.tm_mday = days_in_month[tmx.tm_mon];
1808 			if (tm.tm_mday > days_in_month[tm.tm_mon])
1809 				tm.tm_mday = days_in_month[tm.tm_mon];
1810 			strftime(bufa, sizeof(bufa), GK_NET_MONTH_STAT_DATE, &tmx);
1811 			strftime(bufb, sizeof(bufb), GK_NET_MONTH_STAT_DATE, &tm);
1812 			snprintf(buf, sizeof(buf), "%s - %s", bufa, bufb);
1813 			}
1814 		}
1815 	else
1816 		return;
1817 
1818 	g_free(ns->date);
1819 	utf8 = utf8_string(buf);
1820 	ns->date = utf8 ? utf8 : g_strdup("??");
1821 	}
1822 
1823 static void
net_stat_init(NetMon * net)1824 net_stat_init(NetMon *net)
1825 	{
1826 	struct tm	*tm = gkrellm_get_current_time();
1827 	gint		i;
1828 
1829 	for (i = 0; i < N_DAY_STATS; ++i)
1830 		net->day_stats[i].date = g_strdup("---");
1831 	for (i = 0; i < N_WEEK_STATS; ++i)
1832 		net->week_stats[i].date = g_strdup("---");
1833 	for (i = 0; i < N_MONTH_STATS; ++i)
1834 		net->month_stats[i].date = g_strdup("---");
1835 
1836 	net_stat_set_date_string(&net->day_stats[0], DAY_STAT, tm);
1837 	net_stat_set_date_string(&net->week_stats[0], WEEK_STAT, tm);
1838 	net_stat_set_date_string(&net->month_stats[0], MONTH_STAT, tm);
1839 	}
1840 
1841 static void
net_stats_shift_down(NetStat * ns,gint n_stats,enum StatType stat_type)1842 net_stats_shift_down(NetStat *ns, gint n_stats, enum StatType stat_type)
1843 	{
1844 	gint	d;
1845 
1846 	g_free(ns[n_stats - 1].date);
1847 
1848 	for (d = n_stats - 1; d > 0; --d)
1849 		ns[d] = ns[d - 1];
1850 	ns->rx = ns->tx = 0.0;
1851 	ns->connect_time = 0;
1852 	ns->date = NULL;
1853 	net_stat_set_date_string(ns, stat_type, gkrellm_get_current_time());
1854 	}
1855 
1856 static void
load_net_data(void)1857 load_net_data(void)
1858 	{
1859 	FILE		*f;
1860 	GList		*list;
1861 	struct tm	*tm  = gkrellm_get_current_time();
1862 	NetMon		*net;
1863 	NetStat		*ns = NULL;
1864 	gchar		buf[128], fname[256], date[32];
1865 	gint		wday, mday, month, yday, year, version;
1866 	gint		day_delta, month_delta, n_stats = 0;
1867 
1868 	for (list = net_mon_list; list; list = list->next)
1869 		{
1870 		net = (NetMon *) list->data;
1871 		snprintf(fname, sizeof(fname), "%s%c%s", net_data_dir,
1872 					G_DIR_SEPARATOR, net->name);
1873 		if ((f = g_fopen(fname, "r")) == NULL)
1874 			continue;
1875 		fgets(buf, sizeof(buf), f);
1876 		if (sscanf(buf, "%d\n", &version) != 1)
1877 			{
1878 			fclose(f);
1879 			continue;
1880 			}
1881 
1882 		fgets(buf, sizeof(buf), f);		/* Comment line */
1883 		fgets(buf, sizeof(buf), f);
1884 		sscanf(buf, "%d %d %d %d %d", &wday, &mday, &month, &yday, &year);
1885 
1886 		if (version == 1)
1887 			{
1888 			struct tm	tmx = *gkrellm_get_current_time();
1889 
1890 			tmx.tm_wday = wday;
1891 			tmx.tm_mday = mday;
1892 			tmx.tm_mon = month;
1893 			tmx.tm_yday = yday;
1894 			tmx.tm_year = year;
1895 
1896 			fgets(buf, sizeof(buf), f);		/* day */
1897 			fgets(buf, sizeof(buf), f);
1898 			sscanf(buf, "%lf %lf",
1899 						&net->day_stats[0].rx, &net->day_stats[0].tx);
1900 			fgets(buf, sizeof(buf), f);		/* week */
1901 			fgets(buf, sizeof(buf), f);
1902 			sscanf(buf, "%lf %lf",
1903 						&net->week_stats[0].rx, &net->week_stats[0].tx);
1904 			fgets(buf, sizeof(buf), f);		/* month */
1905 			fgets(buf, sizeof(buf), f);
1906 			sscanf(buf, "%lf %lf",
1907 						&net->month_stats[0].rx, &net->month_stats[0].tx);
1908 
1909 			net_stat_set_date_string(&net->day_stats[0], DAY_STAT, &tmx);
1910 			net_stat_set_date_string(&net->week_stats[0], WEEK_STAT, &tmx);
1911 			net_stat_set_date_string(&net->month_stats[0], MONTH_STAT, &tmx);
1912 
1913 			if (   net == net_timed
1914 				&& fgets(buf, sizeof(buf), f)	/* connect day*/
1915 			   )
1916 				{
1917 				fgets(buf, sizeof(buf), f);
1918 				sscanf(buf, "%d %d %d",
1919 						&net->day_stats[0].connect_time,
1920 						&net->week_stats[0].connect_time,
1921 						&net->month_stats[0].connect_time);
1922 				}
1923 
1924 			}
1925 		else if (version == NET_DATA_VERSION)
1926 			{
1927 			while (fgets(buf, sizeof(buf), f) != NULL)
1928 				{
1929 				if (!strncmp(buf, "[daily]", 7))
1930 					{
1931 					ns = &net->day_stats[0];
1932 					n_stats = N_DAY_STATS;
1933 					}
1934 				else if (!strncmp(buf, "[weekly]", 8))
1935 					{
1936 					ns = &net->week_stats[0];
1937 					n_stats = N_WEEK_STATS;
1938 					}
1939 				else if (!strncmp(buf, "[monthly]", 9))
1940 					{
1941 					ns = &net->month_stats[0];
1942 					n_stats = N_MONTH_STATS;
1943 					}
1944 				else if (   ns && n_stats > 0
1945 				         && sscanf(buf, "\"%31[^\"]\" %lf %lf %d",
1946 				               date, &ns->rx, &ns->tx, &ns->connect_time) == 4
1947 				        )
1948 					{
1949 					gkrellm_dup_string(&ns->date, date);
1950 					++ns;
1951 					--n_stats;
1952 					}
1953 				}
1954 			}
1955 		else
1956 			{
1957 			fclose(f);
1958 			continue;
1959 			}
1960 
1961 		fclose(f);
1962 
1963 		month_delta = (tm->tm_year * 12 + tm->tm_mon) - (year * 12 + month);
1964 		if (month_delta == 0)
1965 			day_delta = tm->tm_mday - mday;
1966 		else if (month_delta == 1)
1967 			day_delta = days_in_month[month] - mday + tm->tm_mday;
1968 		else
1969 			day_delta = 7;		/* max compared to is 6 */
1970 
1971 		if (day_delta > 0)
1972 			net_stats_shift_down(&net->day_stats[0], N_DAY_STATS, DAY_STAT);
1973 
1974 		if (wday + day_delta != tm->tm_wday)
1975 			net_stats_shift_down(&net->week_stats[0], N_WEEK_STATS, WEEK_STAT);
1976 
1977 		if (   (   tm->tm_mday < reset_mday
1978 				&& (   (month_delta > 1)
1979 					|| (month_delta == 1 && mday < reset_mday)
1980 				   )
1981 			   )
1982 			|| (   tm->tm_mday >= reset_mday
1983 				&& (   (month_delta > 0)
1984 					|| (month_delta == 0 && mday < reset_mday)
1985 				   )
1986 			   )
1987 		   )
1988 			net_stats_shift_down(&net->month_stats[0], N_MONTH_STATS,
1989 						MONTH_STAT);
1990 		}
1991 	}
1992 
1993 
1994 #define SEC_PAD	0
1995 
1996 static void
create_net_timer(GtkWidget * vbox,gint first_create)1997 create_net_timer(GtkWidget *vbox, gint first_create)
1998 	{
1999 	GkrellmPanel		*p;
2000 	GkrellmStyle		*style;
2001 	GkrellmTextstyle	*ts, *ts_alt;
2002 	GkrellmMargin		*m;
2003 	GkrellmBorder		*tb;
2004 	gint				top_margin, bot_margin;
2005 	gint				x, y, w, h, w_avail;
2006 
2007 	if (first_create)
2008 		timer_panel = gkrellm_panel_new0();
2009 	p = timer_panel;
2010 
2011 	style = gkrellm_meter_style(timer_style_id);
2012 	ts = gkrellm_meter_textstyle(timer_style_id);
2013 	ts_alt = gkrellm_meter_alt_textstyle(timer_style_id);
2014 	m = gkrellm_get_style_margins(style);
2015 	tb = &bg_timer_style->border;
2016 
2017 	button_decal = gkrellm_create_decal_pixmap(p, decal_timer_button_pixmap,
2018 			decal_timer_button_mask, N_TB_DECALS, style, -1, -1);
2019 	button_decal->x = gkrellm_chart_width() - m->right - button_decal->w;
2020 
2021 	w_avail = button_decal->x - m->left - 3;
2022 	if (bg_timer_piximage)
2023 		w_avail -= tb->left + tb->right;
2024 	w = gkrellm_gdk_string_width(ts->font, "0000:0000");
2025 	sec_pad = gkrellm_gdk_string_width(ts->font, "0") * 2 / 3;
2026 	if (w > w_avail)
2027 		w = w_avail;
2028 
2029 	time_decal = gkrellm_create_decal_text(p, "0:", ts, style, -1, -1, w);
2030 	seconds_decal = gkrellm_create_decal_text(p, "00",
2031 				ts_alt, style, -1, -1, 0);
2032 
2033 	gkrellm_panel_configure(p, NULL, style);
2034 
2035 	/* Some special work needed here if there is a bg_timer.  I have so
2036 	|  far the time_decal and button_decal fitting inside top/bottom margins.
2037 	|  If I add bg_timer borders to time_decal height and that ends up higher
2038 	|  than button_decal, I will need to grow the panel height.
2039 	*/
2040 	h = time_decal->h;
2041 	if (bg_timer_piximage)
2042 		{
2043 		gkrellm_get_top_bottom_margins(style, &top_margin, &bot_margin);
2044 		h += tb->top + tb->bottom;
2045 		time_decal->y += tb->top;
2046 		time_decal->x += tb->left;
2047 		if (h > button_decal->h)	/* Need to grow the height ? */
2048 			{
2049 			gkrellm_panel_configure_set_height(p, h + top_margin + bot_margin);
2050 			button_decal->y += (h - button_decal->h) / 2;
2051 			}
2052 		else	/* button_decal->y is OK */
2053 			time_decal->y += (button_decal->h - h) / 2;
2054 		}
2055 	else
2056 		{
2057 		/* time_decal and button_decal are initially at same y = top_margin
2058 		*/
2059 		if (time_decal->h > button_decal->h)
2060 			button_decal->y += (time_decal->h - button_decal->h) / 2;
2061 		else
2062 			time_decal->y += (button_decal->h - time_decal->h) / 2;
2063 		}
2064 
2065 	seconds_decal->y = time_decal->y + time_decal->h - seconds_decal->h;
2066 	gkrellm_panel_create(vbox, mon_timer, p);
2067 
2068 	gkrellm_move_decal(p, seconds_decal,
2069 				time_decal->x + time_decal->w - seconds_decal->w,
2070 				seconds_decal->y);
2071 
2072 	if (first_create)
2073 		{
2074 		g_signal_connect(G_OBJECT (p->drawing_area), "expose_event",
2075 					G_CALLBACK(net_expose_event), NULL);
2076 		g_signal_connect(G_OBJECT(p->drawing_area), "button_release_event",
2077 					G_CALLBACK(cb_timer_button_release), NULL);
2078 		g_signal_connect(G_OBJECT(p->drawing_area), "leave_notify_event",
2079 					G_CALLBACK(cb_timer_button_release), NULL);
2080 		g_signal_connect(G_OBJECT(p->drawing_area), "button_press_event",
2081 					G_CALLBACK(cb_timer_button_press), NULL);
2082 		}
2083 
2084 	if (bg_timer_piximage)
2085 		{
2086 		w += tb->left + tb->right;
2087 		x = time_decal->x - tb->left;
2088 		y = time_decal->y - tb->top;
2089 		gkrellm_paste_piximage(bg_timer_piximage, p->pixmap, x, y, w, h);
2090 		gkrellm_paste_piximage(bg_timer_piximage, p->bg_pixmap, x, y, w, h);
2091 		gdk_draw_drawable(p->bg_text_layer_pixmap, _GK.draw1_GC, p->bg_pixmap,
2092                 0, 0,  0, 0,  p->w, p->h);
2093 
2094 		}
2095 
2096 	set_timer_button_state(timer_button_state);
2097 	}
2098 
2099 static void
update_net(void)2100 update_net(void)
2101 	{
2102 	GList			*list;
2103 	NetMon			*net;
2104 	struct tm		*tm;
2105 	GkrellmPanel	*p;
2106 	gint			bytes;
2107 	gdouble			rxd, txd;
2108 
2109 	/* If sysdep code is not reporting route up/down events, then
2110 	|  gkrellm_net_assign_data() sets a net as up if data is assigned for it.
2111 	|  So, once a second, compare a net up state before a data read to the
2112 	|  state after a read and use that to internally generate up/down events.
2113 	|  If sysdep code assigns data even if a net is not routed, then there
2114 	|  will be no automatic chart toggling and charts will always be visible
2115 	|  if enabled.
2116 	*/
2117 	if (GK.second_tick)
2118 		{
2119 		if (!net_use_routed)
2120 			{
2121 			for (list = net_mon_list; list; list = list->next)
2122 				{
2123 				net = (NetMon *) list->data;
2124 				if (net->ignore)
2125 					continue;
2126 				net->up_prev = net->up;
2127 				net->up = FALSE;
2128 				}
2129 			}
2130 		else
2131 			(*check_net_routes)();
2132 		}
2133 	(*read_net_data)();
2134 	if (GK.second_tick && !net_use_routed)
2135 		{
2136 		for (list = net_mon_list; list; list = list->next)
2137 			{
2138 			net = (NetMon *) list->data;
2139 			if (net->ignore)
2140 				continue;
2141 			if (net->up && !net->up_prev)
2142 				net->up_event = TRUE;
2143 			else if (!net->up && net->up_prev)
2144 				net->down_event = TRUE;
2145 			}
2146 		}
2147 	for (list = net_mon_list; list; list = list->next)
2148 		{
2149 		net = (NetMon *) list->data;
2150 		if (!net->chart || net->ignore)
2151 			continue;
2152 		p = net->chart->panel;
2153 		if (net->up || net->force_up)
2154 			{
2155 			if (net->rx > net->rx_old)
2156 				draw_led(net, RX_LED, RX_ON);
2157 			else
2158 				draw_led(net, RX_LED, RX_OFF);
2159 			if (net->tx > net->tx_old)
2160 				draw_led(net, TX_LED, TX_ON);
2161 			else
2162 				draw_led(net, TX_LED, TX_OFF);
2163 			}
2164 		net->rx_old = net->rx;
2165 		net->tx_old = net->tx;
2166 		if (GK.second_tick)
2167 			{
2168 			gkrellm_store_chartdata(net->chart, 0, net->tx, net->rx);
2169 			net->rx_current = gkrellm_get_current_chartdata(net->rx_cd);
2170 			net->tx_current = gkrellm_get_current_chartdata(net->tx_cd);
2171 			rxd = (gdouble) net->rx_current;
2172 			txd = (gdouble) net->tx_current;
2173 			net->rx_totalA += rxd;
2174 			net->tx_totalA += txd;
2175 			net->rx_totalB += rxd;
2176 			net->tx_totalB += txd;
2177 
2178 			if (GK.day_tick)
2179 				{
2180 				tm = gkrellm_get_current_time();
2181 				net_stats_shift_down(&net->day_stats[0], N_DAY_STATS,
2182 							DAY_STAT);
2183 
2184 				if (tm->tm_wday == 0)
2185 					net_stats_shift_down(&net->week_stats[0], N_WEEK_STATS,
2186 								WEEK_STAT);
2187 
2188 				if (net_accounting_month_new(tm))
2189 					net_stats_shift_down(&net->month_stats[0], N_MONTH_STATS,
2190 								MONTH_STAT);
2191 				}
2192 			net->day_stats[0].rx   += rxd;
2193 			net->week_stats[0].rx  += rxd;
2194 			net->month_stats[0].rx += rxd;
2195 
2196 			net->day_stats[0].tx   += txd;
2197 			net->week_stats[0].tx  += txd;
2198 			net->month_stats[0].tx += txd;
2199 
2200 			if (net->alert)
2201 				{
2202 				bytes = 0;
2203 				if (net->alert_uses_rx)
2204 					bytes += net->rx_current;
2205 				if (net->alert_uses_tx)
2206 					bytes += net->tx_current;
2207 				gkrellm_check_alert(net->alert, bytes);
2208 				}
2209 			gkrellm_panel_label_on_top_of_decals(p,
2210 						gkrellm_alert_decal_visible(net->alert));
2211 			refresh_net_chart(net);
2212 			}
2213 		gkrellm_update_krell(p, KRELL(p), net->tx + net->rx);
2214 		gkrellm_draw_panel_layers(p);
2215 		}
2216 	if (GK.second_tick)
2217 		{
2218 		update_timer_button_monitor();
2219 		timed_net_visibility();
2220 		if (net_timed && !net_timed->up && !net_timed->force_up)
2221 			{
2222 			draw_led(net_timed, RX_LED, RX_OFF);
2223 			draw_led(net_timed, TX_LED, TX_OFF);
2224 			}
2225 		for (list = net_mon_list; list; list = list->next)
2226 			{
2227 			net = (NetMon *) list->data;
2228 			if (net->ignore)
2229 				continue;
2230 			if (!net->locked)
2231 				{
2232 				if (net->up_event && !net->chart && net->enabled)
2233 					{
2234 					create_net_monitor(dynamic_net_vbox, net, TRUE);
2235 					gkrellm_pack_side_frames();
2236 					}
2237 				else if (net->down_event && net->chart)
2238 					{
2239 					destroy_chart(net);
2240 					gkrellm_pack_side_frames();
2241 					}
2242 				}
2243 			net->up_event = net->down_event = FALSE;
2244 			}
2245 		}
2246 	if (GK.hour_tick)
2247 		{
2248 		tm = gkrellm_get_current_time();
2249 		if ((tm->tm_hour % 6) == 0)
2250 			gkrellm_net_save_data();
2251 		}
2252 	}
2253 
2254   /* A timed interface has its chart locked and is forced enabled.
2255   */
2256 static void
create_timed_monitor(void)2257 create_timed_monitor(void)
2258 	{
2259 	GList		*list;
2260 	NetMon		*net;
2261 	TimerType	*tt;
2262 
2263 	if (_GK.client_mode)
2264 		return;
2265 
2266 	net_timed = NULL;
2267 	timer_button_type = TIMER_TYPE_NONE;
2268 	time(&net_timer0);
2269 
2270 	if (!*timer_button_iface || !strcmp(timer_button_iface, "none"))
2271 		return;
2272 
2273 	/* Making a timed mon out of one that is already up?  It needs to be
2274 	|  moved to a different vbox, so destroy and create dance.
2275 	*/
2276 	for (list = net_mon_list; list; list = list->next)
2277 		{
2278 		net = (NetMon *) list->data;
2279 		if (!strcmp(net->name, timer_button_iface))
2280 			{
2281 			destroy_chart(net);
2282 			break;
2283 			}
2284 		}
2285 	if ((net = lookup_net(timer_button_iface)) == NULL)
2286 		net = new_net(timer_button_iface);
2287 
2288 	net->enabled = TRUE;
2289 	net->locked = TRUE;
2290 	create_net_monitor(net_vbox, net, TRUE);
2291 	if (!net->up)
2292 		gkrellm_chart_hide(net->chart, FALSE);	/* Don't hide its panel */
2293 
2294 	net_timed = net;
2295 	for (list = timer_defaults_list; list; list = list->next)
2296 		{
2297 		tt = (TimerType *) list->data;
2298 		if (!strncmp(timer_button_iface, tt->name, strlen(tt->name) - 1))
2299 			{
2300 			timer_button_type = tt->type;
2301 			break;
2302 			}
2303 		}
2304 	get_connect_time();
2305 	}
2306 
2307 
2308 static void
load_net_extra_piximages(void)2309 load_net_extra_piximages(void)
2310 	{
2311 	gchar			**xpm;
2312 	gint			w, h;
2313 
2314 	/* Check for theme_dir/net/decal_net_leds.png.
2315 	*/
2316 	gkrellm_load_piximage("decal_net_leds", decal_net_leds_xpm,
2317 			&decal_net_led_piximage, NET_STYLE_NAME);
2318 
2319 	w = gdk_pixbuf_get_width(decal_net_led_piximage->pixbuf);
2320 	w *= gkrellm_get_theme_scale();
2321 
2322 	h = gdk_pixbuf_get_height(decal_net_led_piximage->pixbuf) / N_LEDS;
2323 	h *= gkrellm_get_theme_scale();
2324 
2325 	gkrellm_scale_piximage_to_pixmap(decal_net_led_piximage,
2326 				&decal_net_led_pixmap, &decal_net_led_mask, w, h * N_LEDS);
2327 
2328 	/* Check for theme_dir/net/decal_timer_button.png
2329 	*/
2330 	gkrellm_load_piximage("decal_timer_button", decal_timer_button_xpm,
2331 			&decal_timer_button_piximage, TIMER_STYLE_NAME);
2332 	h = gdk_pixbuf_get_height(decal_timer_button_piximage->pixbuf)
2333 				/ N_TB_DECALS;
2334 	h *= gkrellm_get_theme_scale();
2335 	gkrellm_scale_piximage_to_pixmap(decal_timer_button_piximage,
2336 			&decal_timer_button_pixmap, &decal_timer_button_mask,
2337 			-1, h * N_TB_DECALS);
2338 
2339 	/* Here is where I define the net timer panel theme extensions.  I ask
2340 	|  for a theme extension image:
2341 	|      THEME_DIR/timer/bg_timer.png
2342 	|  and for a border for it from the gkrellmrc in the format:
2343 	|      set_piximage_border timer_bg_timer l,r,t,b
2344 	| There is no default for bg_timer, ie it may end up being NULL.
2345 	*/
2346 	if (!bg_timer_style)		/* Used just for the bg_timer border */
2347 		bg_timer_style = gkrellm_style_new0();
2348 	if (bg_timer_piximage)
2349 		gkrellm_destroy_piximage(bg_timer_piximage);
2350 	bg_timer_piximage = NULL;
2351 	xpm = (gkrellm_using_default_theme()) ? bg_timer_xpm : NULL;
2352 	gkrellm_load_piximage("bg_timer", xpm,
2353 				&bg_timer_piximage, TIMER_STYLE_NAME);
2354 	gkrellm_set_gkrellmrc_piximage_border("timer_bg_timer",
2355 				bg_timer_piximage, bg_timer_style);
2356 	}
2357 
2358 static void
net_spacer_visibility(void)2359 net_spacer_visibility(void)
2360 	{
2361 	GList		*list;
2362 	gboolean	enabled = FALSE;
2363 
2364 	for (list = net_mon_list; list; list = list->next)
2365 		if (((NetMon *) list->data)->enabled)
2366 			enabled = TRUE;
2367 	if (timer_button_enabled || enabled)
2368 		gkrellm_spacers_show(mon_net);
2369 	else
2370 		gkrellm_spacers_hide(mon_net);
2371 	}
2372 
2373 static void
create_net(GtkWidget * vbox,gint first_create)2374 create_net(GtkWidget *vbox, gint first_create)
2375 	{
2376 	GList	*list;
2377 	NetMon	*net;
2378 
2379 	load_net_extra_piximages();
2380 
2381 	/* Make a couple of vboxes here so I can control the net layout.
2382 	|  I want interface linked to the timer button  to go last.
2383 	*/
2384 	if (first_create)
2385 		{
2386 		dynamic_net_vbox = gtk_vbox_new(FALSE, 0);
2387 		gtk_box_pack_start(GTK_BOX(vbox), dynamic_net_vbox, FALSE, FALSE, 0);
2388 		gtk_widget_show(dynamic_net_vbox);
2389 
2390 		net_vbox = gtk_vbox_new(FALSE, 0);
2391 		gtk_box_pack_start(GTK_BOX(vbox), net_vbox, FALSE, FALSE, 0);
2392 		gtk_widget_show(net_vbox);
2393 
2394 		(*(read_net_data))();		/* need net up states */
2395 
2396 		create_timed_monitor();
2397 		for (list = net_mon_list; list; list = list->next)
2398 			{
2399 			net = (NetMon *) list->data;
2400 			if (net == net_timed)
2401 				continue;
2402 			if ((net->up || net->force_up) && net->enabled)
2403 				create_net_monitor(dynamic_net_vbox, net, first_create);
2404 			}
2405 		load_net_data();
2406 		}
2407 	else
2408 		{
2409 		/* Some decals don't live in a panel, they will be drawn onto
2410 		|  charts when needed.  So, must destroy them at create events (not
2411 		|  done automatically in panel lists) and then recreate them with NULL
2412 		|  panel and style pointers.
2413 		*/
2414 		gkrellm_destroy_decal(decal_totalA);
2415 		gkrellm_destroy_decal(decal_totalB);
2416 		gkrellm_destroy_decal(decal_reset);
2417 		gkrellm_destroy_decal(decal_stats);
2418 		decal_totalA = decal_totalB = decal_reset = decal_stats = NULL;
2419 		for (list = net_mon_list; list; list = list->next)
2420 			{
2421 			net = (NetMon *) list->data;
2422 			if (net->chart)
2423 				create_net_monitor(NULL, net, 0);
2424 			}
2425 		}
2426 	decal_totalA = gkrellm_create_decal_pixmap(NULL,
2427 			gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
2428 			N_MISC_DECALS, NULL, 0, 0);
2429 	decal_totalB = gkrellm_create_decal_pixmap(NULL,
2430 			gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
2431 			N_MISC_DECALS, NULL, 0, 0);
2432 
2433 	decal_reset = gkrellm_create_decal_pixmap(NULL,
2434 			gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
2435 			N_MISC_DECALS, NULL, 0, 0);
2436 
2437 	decal_stats = gkrellm_create_decal_pixmap(NULL,
2438 			gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
2439 			N_MISC_DECALS, NULL, 0, 0);
2440 
2441 	net_spacer_visibility();
2442 	}
2443 
2444 static void
create_timer(GtkWidget * vbox,gint first_create)2445 create_timer(GtkWidget *vbox, gint first_create)
2446 	{
2447 	timer_vbox = vbox;
2448 	create_net_timer(timer_vbox, first_create);
2449 	ascent = 0;
2450 	ascent_alt = 0;
2451 	if (first_create)
2452 		draw_timer(timer_panel, (int) (time(0) - net_timer0), 1);
2453 	else
2454 		draw_timer(timer_panel, last_time , 1);
2455 	gkrellm_draw_panel_layers(timer_panel);
2456 	net_timer_visibility();
2457 	}
2458 
2459 #define	NET_CONFIG_KEYWORD	"net"
2460 
2461 static void
cb_alert_trigger(GkrellmAlert * alert,NetMon * net)2462 cb_alert_trigger(GkrellmAlert *alert, NetMon *net)
2463 	{
2464 	/* Full panel alert, default decal.
2465 	*/
2466 	alert->panel = net->chart->panel;
2467 	}
2468 
2469 static void
create_alert(NetMon * net)2470 create_alert(NetMon *net)
2471 	{
2472 	net->alert = gkrellm_alert_create(NULL, net->name,
2473 				_("Bytes per second"),
2474 				TRUE, FALSE, TRUE,
2475 				1e10, 1000, 1000, 10000, 0);
2476 	gkrellm_alert_delay_config(net->alert, 1, 60 * 60, 0);
2477 
2478 	gkrellm_alert_trigger_connect(net->alert, cb_alert_trigger, net);
2479 	gkrellm_alert_config_connect(net->alert, cb_alert_config, net);
2480 	gkrellm_alert_config_create_connect(net->alert,
2481 							cb_alert_config_create, net);
2482 	gkrellm_alert_command_process_connect(net->alert, cb_command_process, net);
2483 	}
2484 
2485 
2486 static void
save_net_config(FILE * f)2487 save_net_config(FILE *f)
2488 	{
2489 	GList	*list;
2490 	NetMon	*net;
2491 
2492 	for (list = net_mon_list; list; list = list->next)
2493 		{
2494 		net = (NetMon *) list->data;
2495 		if ((!net->enabled  && !net->real) || net->ignore)
2496 			continue;
2497 		fprintf(f, "%s enables %s %d %d %d\n", NET_CONFIG_KEYWORD, net->name,
2498 				net->enabled, net->chart_labels, net->force_up);
2499 		gkrellm_save_chartconfig(f, net->chart_config,
2500 				NET_CONFIG_KEYWORD, net->name);
2501 		if (*net->label)
2502 			fprintf(f, "%s label %s %s\n", NET_CONFIG_KEYWORD,
2503 					net->name, net->label);
2504 		if (*(net->launch.command))
2505 			fprintf(f, "%s launch %s %s\n", NET_CONFIG_KEYWORD,
2506 					net->name, net->launch.command);
2507 		if (*(net->launch.tooltip_comment))
2508 			fprintf(f, "%s tooltip %s %s\n", NET_CONFIG_KEYWORD,
2509 					net->name, net->launch.tooltip_comment);
2510 		if (net->alert)
2511 			{
2512 			gkrellm_save_alertconfig(f, net->alert,
2513 						NET_CONFIG_KEYWORD, net->name);
2514 			fprintf(f, "%s extra_alert_config %s %d %d\n", NET_CONFIG_KEYWORD,
2515 						net->name,
2516 						net->alert_uses_rx, net->alert_uses_tx);
2517 			}
2518 		}
2519 
2520 	if (*net_ignore_patterns)
2521 		fprintf(f, "%s ignore_patterns %s\n", NET_CONFIG_KEYWORD, net_ignore_patterns);
2522 
2523 	if (!_GK.client_mode || timer_button_type != TIMER_TYPE_SERVER)
2524 		fprintf(f, "%s timer_enabled %d\n", NET_CONFIG_KEYWORD,
2525 						timer_button_enabled);
2526 	fprintf(f, "%s timer_seconds %d\n", NET_CONFIG_KEYWORD, timer_seconds);
2527 	if (!_GK.client_mode)
2528 		fprintf(f, "%s timer_iface %s\n", NET_CONFIG_KEYWORD,
2529 				timer_button_iface);
2530 	fprintf(f, "%s timer_on %s\n", NET_CONFIG_KEYWORD, timer_on_command);
2531 	fprintf(f, "%s timer_off %s\n", NET_CONFIG_KEYWORD, timer_off_command);
2532 	if (*text_format)
2533 		fprintf(f, "%s text_format %s\n", NET_CONFIG_KEYWORD, text_format);
2534 	fprintf(f, "%s reset_mday %d\n", NET_CONFIG_KEYWORD, reset_mday);
2535 	fprintf(f, "%s net_enabled_as_default %d\n", NET_CONFIG_KEYWORD, net_enabled_as_default);
2536 	fprintf(f, "%s net_stats_window_height %d\n", NET_CONFIG_KEYWORD,
2537 				net_stats_window_height);
2538 	}
2539 
2540 static void
load_net_config(gchar * arg)2541 load_net_config(gchar *arg)
2542 	{
2543 	NetMon		*net;
2544 	gchar		config[32], name[32];
2545 	gchar		item[CFG_BUFSIZE], item1[CFG_BUFSIZE];
2546 	gboolean	enable = TRUE, ch_labels = TRUE, force = FALSE;
2547 	gint		n;
2548 
2549 	n = sscanf(arg, "%31s %[^\n]", config, item);
2550 	if (n != 2)
2551 		return;
2552 
2553 	if (!_GK.client_mode || timer_button_type != TIMER_TYPE_SERVER)
2554 		if (!strcmp(config, "timer_enabled") && ! _GK.demo)
2555 			sscanf(item, "%d", &timer_button_enabled);
2556 
2557 	if (!strcmp(config, "timer_seconds"))
2558 		sscanf(item, "%d", &timer_seconds);
2559 	else if (!strcmp(config, "reset_mday"))
2560 		sscanf(item, "%d", &reset_mday);
2561 	else if (!strcmp(config, "net_enabled_as_default"))
2562 		sscanf(item, "%d", &net_enabled_as_default);
2563 	else if (!strcmp(config, "net_stats_window_height"))
2564 		sscanf(item, "%d", &net_stats_window_height);
2565 	else if (!strcmp(config, "timer_iface") && !_GK.client_mode)
2566 		{
2567 		if (_GK.demo && !strcmp(item, "none"))
2568 			gkrellm_dup_string(&timer_button_iface, "ppp0");
2569 		else
2570 			gkrellm_dup_string(&timer_button_iface, item);
2571 		}
2572 	else if (!strcmp(config, "timer_on"))
2573 		gkrellm_dup_string(&timer_on_command, item);
2574 	else if (!strcmp(config, "timer_off"))
2575 		gkrellm_dup_string(&timer_off_command, item);
2576 	else if (!strcmp(config, "text_format"))
2577 		gkrellm_locale_dup_string(&text_format, item, &text_format_locale);
2578 	else if (!strcmp(config, "ignore_patterns"))
2579 		gkrellm_dup_string(&net_ignore_patterns, item);
2580 	else if (sscanf(item, "%31s %[^\n]", name, item1) == 2)
2581 		{
2582 		if (!strcmp(config, "iface"))	/* Hack to get some of 1.0 config */
2583 			{	/* Can't get resolution, label, launch or tooltip */
2584 			sscanf(item1, "%*d %d %*s %d %d", &enable, &ch_labels, &force);
2585 			strcpy(config, "enables");
2586 			snprintf(item1, sizeof(item1), "%d %d %d", enable, ch_labels, force);
2587 			}
2588 		/* Remaining configs will have a net name
2589 		*/
2590 		if (!strcmp(config, "enables"))
2591 			{
2592 			if ((net = lookup_net(name)) == NULL)
2593 				net = new_net(name);
2594 			if (net && !net->ignore)
2595 				{
2596 				sscanf(item1, "%d %d %d", &net->enabled, &net->chart_labels,
2597 							&net->force_up);
2598 				if (!net_use_routed)
2599 					net->force_up = FALSE;
2600 				}
2601 			return;
2602 			}
2603 		if ((net = lookup_net(name)) == NULL || net->ignore)
2604 			return;
2605 		if (!strcmp(config, GKRELLM_CHARTCONFIG_KEYWORD))
2606 			gkrellm_load_chartconfig(&net->chart_config, item1, 2);
2607 		else if (!strcmp(config, GKRELLM_ALERTCONFIG_KEYWORD))
2608 			{
2609 			if (!net->alert)
2610 				create_alert(net);
2611 			gkrellm_load_alertconfig(&net->alert, item1);
2612 			}
2613 		else if (!strcmp(config, "extra_alert_config"))
2614 			sscanf(item1, "%d %d", &net->alert_uses_rx, &net->alert_uses_tx);
2615 		else if (!strcmp(config, "label"))
2616 			gkrellm_dup_string(&net->label, item1);
2617 		else if (!strcmp(config, "launch"))
2618 			gkrellm_dup_string(&net->launch.command, item1);
2619 		else if (!strcmp(config, "tooltip"))
2620 			gkrellm_dup_string(&net->launch.tooltip_comment, item1);
2621 		}
2622 	}
2623 
2624 
2625 /* -------------- User config interface --------------------- */
2626 
2627 #define STEP	1
2628 
2629 static GtkWidget	*pon_entry,
2630 					*poff_entry,
2631 					*net_ignore_entry,
2632 					*timer_iface_combo_box,
2633 					*text_format_combo_box;
2634 
2635 static GtkWidget	*enable_net_timer_button;
2636 static GtkWidget	*net_timer_seconds_button;
2637 
2638 static gboolean		enable_in_progress;
2639 
2640 
2641 static void
sync_chart(NetMon * net)2642 sync_chart(NetMon *net)
2643 	{
2644 	/* If enabling, fake an up_event so update_net() will create the chart.
2645 	*/
2646 	if (net->enabled && !net->chart && (net->up || net->force_up))
2647 		net->up_event = TRUE;
2648 	else if (   net->chart
2649 			 && (!net->enabled || (!net->locked && !net->force_up && !net->up))
2650 			)
2651 		destroy_chart(net);
2652 	}
2653 
2654 static void
cb_force(GtkWidget * button,NetMon * net)2655 cb_force(GtkWidget *button, NetMon *net)
2656 	{
2657 	if (enable_in_progress)
2658 		return;
2659 	net->force_up = GTK_TOGGLE_BUTTON(button)->active;
2660 	if (net != net_timed)
2661 		net->locked = FALSE;
2662 	sync_chart(net);
2663 	}
2664 
2665 static void
cb_enable(GtkWidget * button,NetMon * net)2666 cb_enable(GtkWidget *button, NetMon *net)
2667 	{
2668 	enable_in_progress = TRUE;
2669 	net->enabled = GTK_TOGGLE_BUTTON(button)->active;
2670 	if (net->force_button)
2671 		{
2672 		if (net->enabled)
2673 			gtk_widget_set_sensitive(net->force_button, TRUE);
2674 		else
2675 			{
2676 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net->force_button),
2677 						FALSE);
2678 			gtk_widget_set_sensitive(net->force_button, FALSE);
2679 			net->force_up = FALSE;
2680 			}
2681 		}
2682 	gtk_widget_set_sensitive(net->alert_button, net->enabled);
2683 	if (net == net_timed && !net->enabled && timer_iface_combo_box)
2684 		gtk_combo_box_set_active(GTK_COMBO_BOX(timer_iface_combo_box), 0);
2685 	else
2686 		sync_chart(net);
2687 	enable_in_progress = FALSE;
2688 	net_spacer_visibility();
2689 	}
2690 
2691 static void
cb_launch_entry(GtkWidget * widget,NetMon * net)2692 cb_launch_entry(GtkWidget *widget, NetMon *net)
2693 	{
2694 	if (net->chart)
2695 		gkrellm_apply_launcher(&net->launch_entry, &net->tooltip_entry,
2696 				net->chart->panel, &net->launch, gkrellm_launch_button_cb);
2697 	}
2698 
2699 static void
cb_text_format(GtkWidget * widget,gpointer data)2700 cb_text_format(GtkWidget *widget, gpointer data)
2701 	{
2702 	GList   *list;
2703 	NetMon	*net;
2704 	gchar   *s;
2705 	GtkWidget *entry;
2706 
2707 	entry = gtk_bin_get_child(GTK_BIN(text_format_combo_box));
2708 	s = gkrellm_gtk_entry_get_text(&entry);
2709 	gkrellm_locale_dup_string(&text_format, s, &text_format_locale);
2710 	for (list = net_mon_list; list; list = list->next)
2711 		{
2712 		net = (NetMon *) list->data;
2713 		net->new_text_format = TRUE;
2714 		refresh_net_chart(net);
2715 		}
2716 	}
2717 
2718 static void
cb_label_entry(GtkWidget * widget,NetMon * net)2719 cb_label_entry(GtkWidget *widget, NetMon *net)
2720 	{
2721 	gkrellm_dup_string(&net->label,
2722 						gkrellm_gtk_entry_get_text(&net->label_entry));
2723 	refresh_net_chart(net);
2724 	}
2725 
2726 static void
cb_set_alert(GtkWidget * button,NetMon * net)2727 cb_set_alert(GtkWidget *button, NetMon *net)
2728 	{
2729 
2730 #if 0
2731 	GtkTreeModel	*model;
2732 	GtkTreePath		*path;
2733 	GtkTreeIter		iter;
2734 	NetMon			*net;
2735 
2736 	if (!row_reference)
2737 		return;
2738 	model = gtk_tree_view_get_model(treeview);
2739 	path = gtk_tree_row_reference_get_path(row_reference);
2740 	gtk_tree_model_get_iter(model, &iter, path);
2741 	gtk_tree_model_get(model, &iter, NETMON_COLUMN, &net, -1);
2742 #endif
2743 
2744 	if (!net->alert)
2745 		create_alert(net);
2746 	gkrellm_alert_config_window(&net->alert);
2747 
2748 #if 0
2749 	gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2750 				ALERT_COLUMN, net->alert, -1);
2751 #endif
2752 	}
2753 
2754   /* Callback for a created or destroyed alert.  Find the sensor in the model
2755   |  and set the IMAGE_COLUMN.
2756   */
2757 static void
cb_alert_config(GkrellmAlert * ap,NetMon * net)2758 cb_alert_config(GkrellmAlert *ap, NetMon *net)
2759     {
2760 #if 0
2761 	GtkTreeModel	*model;
2762 	GtkTreeIter		iter;
2763 	NetMon			*net_test;
2764 	GdkPixbuf		*pixbuf;
2765 	gchar			node[2];
2766 	gint			i;
2767 
2768 	if (!gkrellm_config_window_shown())
2769 		return;
2770 	model = gtk_tree_view_get_model(treeview);
2771 	pixbuf = ap->activated ? gkrellm_alert_pixbuf() : NULL;
2772 	for (i = 0; i < 2; ++i)
2773 		{
2774 		node[0] = '0' + i;      /* toplevel Primary or Secondary node */
2775 		node[1] = '\0';
2776 		if (get_child_iter(model, node, &iter))
2777 			do
2778 				{
2779 				gtk_tree_model_get(model, &iter, NETMON_COLUMN, &net_test, -1);
2780 				if (net != net_test)
2781 					continue;
2782 				gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2783 							IMAGE_COLUMN, pixbuf, -1);
2784 				return;
2785 				}
2786 			while (gtk_tree_model_iter_next(model, &iter));
2787 		}
2788 #endif
2789 	net->alert_uses_rx =
2790 			GTK_TOGGLE_BUTTON(net->alert_config_rx_button)->active;
2791 	net->alert_uses_tx =
2792 			GTK_TOGGLE_BUTTON(net->alert_config_tx_button)->active;
2793 	}
2794 
2795 static void
cb_alert_config_button(GtkWidget * button,NetMon * net)2796 cb_alert_config_button(GtkWidget *button, NetMon *net)
2797 	{
2798 	gboolean	read, write;
2799 
2800 	read = GTK_TOGGLE_BUTTON(net->alert_config_rx_button)->active;
2801 	write = GTK_TOGGLE_BUTTON(net->alert_config_tx_button)->active;
2802 	if (!read && !write)
2803 		{
2804 		gtk_toggle_button_set_active(
2805 				GTK_TOGGLE_BUTTON(net->alert_config_rx_button), TRUE);
2806 		gtk_toggle_button_set_active(
2807 				GTK_TOGGLE_BUTTON(net->alert_config_tx_button), TRUE);
2808 		}
2809 	}
2810 
2811 static void
cb_alert_config_create(GkrellmAlert * ap,GtkWidget * vbox,NetMon * net)2812 cb_alert_config_create(GkrellmAlert *ap, GtkWidget *vbox, NetMon *net)
2813     {
2814     gkrellm_gtk_check_button_connected(vbox, &net->alert_config_rx_button,
2815                 net->alert_uses_rx, FALSE, FALSE, 2,
2816                 cb_alert_config_button, net, _("rx bytes"));
2817     gkrellm_gtk_check_button_connected(vbox, &net->alert_config_tx_button,
2818                 net->alert_uses_tx, FALSE, FALSE, 2,
2819                 cb_alert_config_button, net, _("tx bytes"));
2820     }
2821 
2822 
2823 static void
cb_timer_enable(GtkWidget * button,gpointer data)2824 cb_timer_enable(GtkWidget *button, gpointer data)
2825 	{
2826 	gkrellm_panel_enable_visibility(timer_panel,
2827 				GTK_TOGGLE_BUTTON(enable_net_timer_button)->active,
2828 				&timer_button_enabled);
2829 	gtk_widget_set_sensitive(net_timer_seconds_button, timer_button_enabled);
2830 	if (timer_iface_combo_box)
2831 		{
2832 		/* Reset to "none" combo box entry */
2833 		if (!timer_button_enabled)
2834 			gtk_combo_box_set_active(GTK_COMBO_BOX(timer_iface_combo_box), 0);
2835 		gtk_widget_set_sensitive(timer_iface_combo_box, timer_button_enabled);
2836 		}
2837 	net_timer_visibility();
2838 	}
2839 
2840 static void
cb_timer_seconds(GtkWidget * button,gpointer data)2841 cb_timer_seconds(GtkWidget *button, gpointer data)
2842 	{
2843 	timer_seconds = GTK_TOGGLE_BUTTON(button)->active;
2844 	gkrellm_panel_destroy(timer_panel);
2845 	create_net_timer(timer_vbox, TRUE);
2846 	draw_timer(timer_panel, last_time , 1);
2847 	}
2848 
2849 static void
cb_timer_iface(GtkWidget * widget,gpointer data)2850 cb_timer_iface(GtkWidget *widget, gpointer data)
2851 	{
2852 	gchar	*s;
2853 	GtkWidget *entry;
2854 
2855 	entry = gtk_bin_get_child(GTK_BIN(timer_iface_combo_box));
2856 	s = gkrellm_gtk_entry_get_text(&entry);
2857 	if (*s == '\0' || strcmp(s, _("none")) == 0 || net_ignore_match(s))
2858 		s = "none";
2859 	if (gkrellm_dup_string(&timer_button_iface, s))
2860 		{
2861 		/* A new timer_button_iface, so destroy old one.  If the old one
2862 		|  is up or forced up, a new chart for it needs to be created in
2863 		|  another vbox, so fake an up_event.
2864 		*/
2865 		if (net_timed)
2866 			{
2867 			destroy_chart(net_timed);
2868 			if (   net_timed->enabled
2869 				&& (net_timed->up || net_timed->force_up)
2870 			   )
2871 				net_timed->up_event = TRUE;
2872 			}
2873 		create_timed_monitor();
2874 		if (net_timed)
2875 			gtk_toggle_button_set_active(
2876 						GTK_TOGGLE_BUTTON(net_timed->enable_button), TRUE);
2877 		draw_timer(timer_panel, (int) (time(0) - net_timer0), 1);
2878 		gkrellm_draw_panel_layers(timer_panel);
2879 		}
2880 	}
2881 
2882 static void
cb_pon_entry(GtkWidget * widget,gpointer data)2883 cb_pon_entry(GtkWidget *widget, gpointer data)
2884 	{
2885 	gchar	*s;
2886 
2887 	s = gkrellm_gtk_entry_get_text(&pon_entry);
2888 	gkrellm_dup_string(&timer_on_command, s);
2889 	}
2890 
2891 static void
cb_poff_entry(GtkWidget * widget,gpointer data)2892 cb_poff_entry(GtkWidget *widget, gpointer data)
2893 	{
2894 	gchar	*s;
2895 
2896 	s = gkrellm_gtk_entry_get_text(&poff_entry);
2897 	gkrellm_dup_string(&timer_off_command, s);
2898 	}
2899 
2900 static void
cb_reset_mday(GtkWidget * widget,GtkSpinButton * spin)2901 cb_reset_mday(GtkWidget *widget, GtkSpinButton *spin)
2902 	{
2903 	GList		*list;
2904 	NetMon		*net;
2905 	NetStat		*ns;
2906 	struct tm	*tm;
2907 	gint		year, month, mday, month_delta;
2908 
2909 	reset_mday = gtk_spin_button_get_value_as_int(spin);
2910 
2911 	for (list = net_mon_list; list; list = list->next)
2912 		{
2913 		net = (NetMon *) list->data;
2914 		net->month_stats[0].rx = net->month_stats[0].tx = 0.0;
2915 		net->month_stats[0].connect_time = 0;
2916 		tm = gkrellm_get_current_time();
2917 		net_stat_set_date_string(&net->month_stats[0], MONTH_STAT, tm);
2918 
2919 		for (ns = &net->day_stats[0]; ns < &net->day_stats[N_DAY_STATS]; ++ns)
2920 			{
2921 			if (sscanf(ns->date, "%d-%d-%d", &year, &month, &mday) != 3)
2922 				continue;
2923 			year -= 1900;	/* Adjust to struct tm ranges */
2924 			month -= 1;
2925 			month_delta = (tm->tm_year * 12 + tm->tm_mon)
2926 								- (year * 12 + month);
2927 			if (   (   tm->tm_mday < reset_mday
2928 			        && (   (month_delta > 1)
2929 			            || (month_delta == 1 && mday < reset_mday)
2930 			           )
2931 			       )
2932 			    || (   tm->tm_mday >= reset_mday
2933 			        && (   (month_delta > 0)
2934 			            || (month_delta == 0 && mday < reset_mday)
2935 			           )
2936 			       )
2937 			   )
2938 				continue;
2939 
2940 			net->month_stats[0].rx += ns->rx;
2941 			net->month_stats[0].tx += ns->tx;
2942 			net->month_stats[0].connect_time += ns->connect_time;
2943 			}
2944 		}
2945 	}
2946 
2947 static void
cb_net_enabled_as_default(GtkWidget * button,gpointer data)2948 cb_net_enabled_as_default(GtkWidget *button, gpointer data)
2949 	{
2950 	net_enabled_as_default = GTK_TOGGLE_BUTTON(button)->active;
2951 	}
2952 
2953 static void
net_ignore_entry_cb(GtkWidget * widget,gpointer data)2954 net_ignore_entry_cb(GtkWidget *widget, gpointer data)
2955 	{
2956 	NetMon	*net;
2957 	GList	*list;
2958 	gchar	*str = gkrellm_gtk_entry_get_text(&net_ignore_entry);
2959 	gboolean prev_ignore;
2960 
2961 	gkrellm_dup_string(&net_ignore_patterns, str);
2962 	for (list = net_mon_list; list; list = list->next)
2963 		{
2964 		net = (NetMon *) list->data;
2965 		prev_ignore = net->ignore;
2966 		net->ignore = net_ignore_match(net->name);
2967 		if (net->ignore && !prev_ignore)
2968 			{
2969 			net->enabled = FALSE;
2970 			sync_chart(net);
2971 			net_spacer_visibility();
2972 			}
2973 		else if (!net->ignore && prev_ignore)
2974 			{
2975 			net->enabled = net_enabled_as_default;
2976 			sync_chart(net);
2977 			net_spacer_visibility();
2978 			}
2979 		if (net->force_button)
2980 			{
2981 			if (net->enabled)
2982 				gtk_widget_set_sensitive(net->force_button, TRUE);
2983 			else
2984 				{
2985 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net->force_button),
2986 							FALSE);
2987 				gtk_widget_set_sensitive(net->force_button, FALSE);
2988 				net->force_up = FALSE;
2989 				}
2990 			}
2991 		if (net->alert_button)
2992 			gtk_widget_set_sensitive(net->alert_button, net->enabled);
2993 		if (net == net_timed && !net->enabled && timer_iface_combo_box)
2994 			gtk_combo_box_set_active(GTK_COMBO_BOX(timer_iface_combo_box), 0);
2995 		}
2996 	}
2997 
2998 #if !defined(WIN32)
2999 static gchar	*net_info_text0[] =
3000 {
3001 N_("<h>Timer Button\n"),
3002 N_("\tThe timer button may be used as a stand alone timer with start and\n"
3003 	"\tstop commands, but it is usually linked to a dial up net interface\n"
3004 	"\twhere the commands can control the interface and different timer\n"
3005 	"\tbutton colors can show connect states:\n"),
3006 "\n",
3007 #if defined(__FreeBSD__)
3008 "<b>\ttun: ",
3009 #else
3010 "<b>\tppp: ",
3011 #endif
3012 N_("Standby state is while the modem phone line is locked while\n"
3013 	"\tppp is connecting, and the on state is the ppp link connected.\n"
3014 	"\tThe phone line lock is determined by the existence of the modem\n"
3015 	"\tlock file /var/lock/LCK..modem.  If your pppd setup does not\n"
3016 	"\tuse /dev/modem, then you can configure an alternative with:\n"),
3017 N_("<i>\t\tln -s /var/lock/LCK..ttySx ~/.gkrellm2/LCK..modem\n"),
3018 N_("\twhere ttySx is the tty device your modem uses.  The ppp on\n"
3019 	"\tstate is detected by the existence of /var/run/pppX.pid and\n"
3020 	"\tthe time stamp of this file is the base for the on line time.\n"),
3021 #if defined(__linux__)
3022 "\n",
3023 "<b>\tippp: ",
3024 N_("The timer button standby state is not applicable to isdn\n"
3025 	"\tinterfaces that are always routed. The on state is isdn on line\n"
3026 	"\twhile the ippp interface is routed.  The on line timer is reset\n"
3027 	"\twhen the isdn interface transitions from a hangup to an on line\n"
3028 	"\tstate\n"),
3029 #endif
3030 "\n"
3031 };
3032 #endif
3033 
3034 static gchar	*net_info_text1[] =
3035 {
3036 N_("<h>Chart Labels\n"),
3037 N_("Substitution variables for the format string for chart labels:\n"),
3038 N_("\t$M    maximum chart value\n"),
3039 N_("\t$T    receive + transmit bytes\n"),
3040 N_("\t$r    receive bytes\n"),
3041 N_("\t$t    transmit bytes\n"),
3042 N_("\t$O    cumulative receive + transmit bytes\n"),
3043 N_("\t$i    cumulative receive bytes\n"),
3044 N_("\t$o    cumulative transmit bytes\n"),
3045 N_("\t$L    the optional chart label\n"),
3046 N_("\t$I    the net interface name\n"),
3047 "\n",
3048 N_("The cumulative variables may have a 'd', 'w', or 'm' qualifier for\n"
3049    "daily, weekly, or monthly totals.  For example:  $Ow for a\n"
3050    "cumulative weekly receive + transmit bytes.\n"),
3051 "\n",
3052 N_("Substitution variables may be used in alert commands.\n")
3053 };
3054 
3055 static void
create_net_tab(GtkWidget * tab_vbox)3056 create_net_tab(GtkWidget *tab_vbox)
3057 	{
3058 	GtkWidget		*tabs;
3059 	GtkWidget		*table;
3060 	GtkWidget		*vbox, *vbox1;
3061 	GtkWidget		*hbox;
3062 	GtkWidget		*label;
3063 	GtkWidget		*text;
3064 	GList			*list, *tlist;
3065 	NetMon			*net;
3066 	TimerType		*tt;
3067 	gchar			buf[256];
3068 	gint			i;
3069 
3070 	tabs = gtk_notebook_new();
3071 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
3072 	gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
3073 
3074 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Timer Button"));
3075 
3076 	if (timer_button_type != TIMER_TYPE_SERVER) /* enabled by gkrellmd.conf? */
3077 		gkrellm_gtk_check_button_connected(vbox, &enable_net_timer_button,
3078 					timer_button_enabled, FALSE, FALSE, 10,
3079 					cb_timer_enable, NULL,
3080 					_("Enable timer button"));
3081 
3082 	gkrellm_gtk_check_button_connected(vbox, &net_timer_seconds_button,
3083 				timer_seconds, FALSE, FALSE, 0,
3084 				cb_timer_seconds, NULL,
3085 				_("Show seconds"));
3086 	gtk_widget_set_sensitive(net_timer_seconds_button, timer_button_enabled);
3087 	hbox = gtk_hbox_new (FALSE, 3);
3088 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 0);
3089 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 50);
3090 
3091 	if (!_GK.client_mode)
3092 		{
3093 		timer_iface_combo_box = gtk_combo_box_entry_new_text();
3094 		gtk_box_pack_start(GTK_BOX(hbox), timer_iface_combo_box, TRUE, TRUE, 0);
3095 		gtk_widget_set_sensitive(timer_iface_combo_box, timer_button_enabled);
3096 		gtk_combo_box_append_text(GTK_COMBO_BOX(timer_iface_combo_box),
3097 			_("none"));
3098 		for (tlist = timer_defaults_list; tlist; tlist = tlist->next)
3099 			{
3100 			tt = (TimerType *) tlist->data;
3101 			gtk_combo_box_append_text(GTK_COMBO_BOX(timer_iface_combo_box),
3102 				tt->name);
3103 			}
3104 		gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(
3105 			GTK_BIN(timer_iface_combo_box))), timer_button_iface);
3106 		g_signal_connect(G_OBJECT(timer_iface_combo_box), "changed",
3107 			G_CALLBACK(cb_timer_iface), NULL);
3108 
3109 		label = gtk_label_new(_("Interface to link to the timer button"));
3110 		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
3111 		}
3112 	vbox = gkrellm_gtk_framed_vbox_end(vbox, NULL, 4, FALSE, 0, 2);
3113 	hbox = gtk_hbox_new (FALSE, 3);
3114 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
3115 	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
3116 
3117 	vbox1 = gtk_vbox_new(FALSE, 3);
3118 	gtk_container_set_border_width(GTK_CONTAINER(vbox1), 3);
3119 	gtk_container_add(GTK_CONTAINER(hbox), vbox1);
3120 	label = gtk_label_new(_("Start Command"));
3121 	gtk_box_pack_start(GTK_BOX (vbox1), label, FALSE, TRUE, 0);
3122 	pon_entry = gtk_entry_new();
3123 	gtk_box_pack_start(GTK_BOX (vbox1), pon_entry, FALSE, TRUE, 0);
3124 	gtk_entry_set_text(GTK_ENTRY(pon_entry), timer_on_command);
3125 	g_signal_connect(G_OBJECT(pon_entry),
3126 				"changed", G_CALLBACK(cb_pon_entry), NULL);
3127 
3128 	vbox1 = gtk_vbox_new(FALSE, 3);
3129 	gtk_container_set_border_width(GTK_CONTAINER(vbox1), 3);
3130 	gtk_container_add(GTK_CONTAINER(hbox), vbox1);
3131 	label = gtk_label_new(_("Stop Command"));
3132 	gtk_box_pack_start(GTK_BOX (vbox1), label, FALSE, TRUE, 0);
3133 	poff_entry = gtk_entry_new();
3134 	gtk_box_pack_start(GTK_BOX (vbox1), poff_entry, FALSE, TRUE, 0);
3135 	gtk_entry_set_text(GTK_ENTRY(poff_entry), timer_off_command);
3136 	g_signal_connect(G_OBJECT(poff_entry),
3137 				"changed", G_CALLBACK(cb_poff_entry), NULL);
3138 
3139 	for (list = net_mon_list; list; list = list->next)
3140 		{
3141 		net = (NetMon *) list->data;
3142 		if (net->ignore)
3143 			{
3144 			net->alert_button = NULL;
3145 			net->force_button = NULL;
3146 			continue;
3147 			}
3148 		vbox = gkrellm_gtk_framed_notebook_page(tabs, net->name);
3149 
3150 		snprintf(buf, sizeof(buf), _("Enable %s"), net->name);
3151 		hbox = gtk_hbox_new (FALSE, 0);
3152 		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 4);
3153 		gkrellm_gtk_check_button_connected(hbox,
3154 						&net->enable_button, net->enabled,
3155 						FALSE, FALSE, 0,
3156 						cb_enable, net, buf);
3157 		gkrellm_gtk_alert_button(hbox, &net->alert_button, FALSE, FALSE, 4,
3158 					FALSE, cb_set_alert, net);
3159 		gtk_widget_set_sensitive(net->alert_button, net->enabled);
3160 
3161 
3162 		if (net_config_use_routed)
3163 			{
3164 			gkrellm_gtk_check_button_connected(vbox, &net->force_button,
3165 						net->enabled ? net->force_up : FALSE, FALSE, FALSE, 0,
3166 						cb_force, net,
3167 		_("Force chart to be always shown even if interface is not routed."));
3168 			if (!net->enabled)
3169 				gtk_widget_set_sensitive(net->force_button, FALSE);
3170 			}
3171 
3172 		hbox = gtk_hbox_new (FALSE, 0);
3173 		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 12);
3174 
3175 		net->label_entry = gtk_entry_new();
3176 		gtk_entry_set_max_length(GTK_ENTRY(net->label_entry), 16);
3177 		gtk_widget_set_size_request(net->label_entry, 70, -1);
3178 		gtk_entry_set_text(GTK_ENTRY(net->label_entry), net->label);
3179 		gtk_box_pack_start (GTK_BOX (hbox), net->label_entry, FALSE, TRUE, 2);
3180 		label = gtk_label_new(_("Optional label for this interface."));
3181 		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 4);
3182 		g_signal_connect(G_OBJECT(net->label_entry), "changed",
3183 					G_CALLBACK(cb_label_entry), net);
3184 
3185 		vbox = gkrellm_gtk_category_vbox(vbox,
3186 					_("Launch Commands"),
3187 					4, 0, TRUE);
3188 		table = gkrellm_gtk_launcher_table_new(vbox, 1);
3189 		gkrellm_gtk_config_launcher(table, 0,  &net->launch_entry,
3190 						&net->tooltip_entry, net->name, &net->launch);
3191 		g_signal_connect(G_OBJECT(net->launch_entry), "changed",
3192 					G_CALLBACK(cb_launch_entry), net);
3193 		g_signal_connect(G_OBJECT(net->tooltip_entry), "changed",
3194 					G_CALLBACK(cb_launch_entry), net);
3195 		}
3196 
3197 /* -- Setup tab */
3198 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Setup"));
3199 
3200 	vbox1 = gkrellm_gtk_category_vbox(vbox,
3201 				_("Format String for Chart Labels"),
3202 				4, 0, TRUE);
3203 	text_format_combo_box = gtk_combo_box_entry_new_text();
3204 	gtk_widget_set_size_request (GTK_WIDGET(text_format_combo_box), 300, -1);
3205 	gtk_box_pack_start(GTK_BOX(vbox1), text_format_combo_box, FALSE, FALSE, 2);
3206 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box), text_format);
3207 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
3208 		DEFAULT_TEXT_FORMAT);
3209 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
3210 		"\\c\\f$M\\n$T\\b\\c\\f$L");
3211 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
3212 		_("\\f\\ww\\c\\f$M\\n\\f\\at\\.$t\\n\\f\\ar\\.$r\\b\\c\\f$L"));
3213 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
3214 		_("\\f\\ww\\c\\f$M\\n\\f\\at\\.$o\\n\\f\\ar\\.$i\\b\\c\\f$L"));
3215 	gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
3216 		_("\\f\\ww\\c\\f$M\\D2\\f\\ar\\.$r\\D1\\f\\at\\.$t\\b\\c\\f$L"));
3217 	gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(text_format_combo_box))),
3218 		text_format);
3219 	g_signal_connect(G_OBJECT(GTK_COMBO_BOX(text_format_combo_box)), "changed",
3220 			G_CALLBACK(cb_text_format), NULL);
3221 
3222 	vbox1 = gkrellm_gtk_category_vbox(vbox,
3223 				_("Ignore Net Interfaces"),
3224 				4, 0, TRUE);
3225 	label = gtk_label_new(_("Space separated list of patterns.\n"));
3226 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
3227 	hbox = gtk_hbox_new(FALSE, 0);
3228 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
3229 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
3230 
3231 	hbox = gtk_hbox_new(FALSE, 0);
3232 	gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
3233 	net_ignore_entry = gtk_entry_new();
3234 	snprintf(buf, sizeof(buf), "%s", net_ignore_patterns);
3235 	gtk_entry_set_text(GTK_ENTRY(net_ignore_entry), buf);
3236 	gtk_box_pack_start(GTK_BOX(hbox), net_ignore_entry, FALSE, FALSE, 0);
3237 	g_signal_connect(G_OBJECT(net_ignore_entry), "changed",
3238 			G_CALLBACK(net_ignore_entry_cb), NULL);
3239 
3240 	gkrellm_gtk_spin_button(vbox, NULL, (gfloat) reset_mday,
3241 			1.0, 31.0, 1.0, 1.0, 0, 55,
3242 			cb_reset_mday, NULL, FALSE,
3243 			_("Start day for cumulative monthly transmit and receive bytes"));
3244 
3245 	gkrellm_gtk_check_button_connected(vbox, &net_enabled_as_default_button,
3246 			net_enabled_as_default, FALSE, FALSE, 10,
3247 			cb_net_enabled_as_default, NULL,
3248 			_("Enable new interfaces"));
3249 
3250 /* --Info tab */
3251 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
3252 	text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
3253 				GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3254 #if !defined(WIN32)
3255 	if (!_GK.client_mode)
3256 		for (i = 0; i < sizeof(net_info_text0)/sizeof(gchar *); ++i)
3257 			gkrellm_gtk_text_view_append(text, _(net_info_text0[i]));
3258 #endif
3259 	for (i = 0; i < sizeof(net_info_text1)/sizeof(gchar *); ++i)
3260 		gkrellm_gtk_text_view_append(text, _(net_info_text1[i]));
3261 	}
3262 
3263 
3264 
3265 static GkrellmMonitor	monitor_net =
3266 	{
3267 	N_("Net"),			/* Name, for config tab.	*/
3268 	MON_NET,			/* Id,  0 if a plugin		*/
3269 	create_net,			/* The create function		*/
3270 	update_net,			/* The update function		*/
3271 	create_net_tab,		/* The config tab create function	*/
3272 	NULL,				/* Instant apply */
3273 
3274 	save_net_config,	/* Save user conifg			*/
3275 	load_net_config,	/* Load user config			*/
3276 	NET_CONFIG_KEYWORD,	/* config keyword			*/
3277 
3278 	NULL,				/* Undef 2	*/
3279 	NULL,				/* Undef 1	*/
3280 	NULL,				/* Undef 0	*/
3281 
3282 	0,					/* insert_before_id - place plugin before this mon */
3283 
3284 	NULL,				/* Handle if a plugin, filled in by GKrellM		*/
3285 	NULL				/* path if a plugin, filled in by GKrellM		*/
3286 	};
3287 
3288 GkrellmMonitor *
gkrellm_init_net_monitor(void)3289 gkrellm_init_net_monitor(void)
3290 	{
3291 	TimerType	*tt;
3292 
3293 	if (!setup_net_interface())
3294 		return NULL;
3295 	time(&net_timer0);
3296 	if (timer_defaults_list)
3297 		{
3298 		tt = (TimerType *) timer_defaults_list->data;
3299 		timer_button_iface = g_strdup(tt->name);
3300 		timer_button_type = tt->type;
3301 		}
3302 	else
3303 		{
3304 		timer_button_iface = g_strdup("none");
3305 		}
3306 	if (!_GK.client_mode)
3307 		timer_button_enabled = TRUE;
3308 	else
3309 		timer_button_enabled = (timer_button_type == TIMER_TYPE_SERVER);
3310 
3311 	timer_seconds = TRUE;
3312 	timer_on_command = g_strdup("");
3313 	timer_off_command = g_strdup("");
3314 
3315 	net_enabled_as_default = TRUE;
3316 
3317 	gkrellm_locale_dup_string(&text_format, DEFAULT_TEXT_FORMAT,
3318 					&text_format_locale);
3319 	gkrellm_dup_string(&net_ignore_patterns, "");
3320 
3321 	net_stats_window_height = 200;
3322 
3323     monitor_net.name = _(monitor_net.name);
3324 	net_style_id = gkrellm_add_chart_style(&monitor_net, NET_STYLE_NAME);
3325 	mon_net = &monitor_net;
3326 	return &monitor_net;
3327 	}
3328 
3329 
3330 static GkrellmMonitor	monitor_timer =
3331 	{
3332 	N_("Net Timer"),	/* Name, for config tab.	*/
3333 	MON_TIMER,			/* Id,  0 if a plugin		*/
3334 	create_timer,		/* The create function		*/
3335 	NULL,				/* The update function		*/
3336 	NULL,				/* The config tab create function	*/
3337 	NULL,				/* Apply the config function		*/
3338 
3339 	NULL,				/* Save user conifg			*/
3340 	NULL,				/* Load user config			*/
3341 	NULL,				/* config keyword			*/
3342 
3343 	NULL,				/* Undef 2	*/
3344 	NULL,				/* Undef 1	*/
3345 	NULL,				/* Undef 0	*/
3346 
3347 	0,					/* insert_before_id - place plugin before this mon */
3348 
3349 	NULL,				/* Handle if a plugin, filled in by GKrellM		*/
3350 	NULL				/* path if a plugin, filled in by GKrellM		*/
3351 	};
3352 
3353 GkrellmMonitor *
gkrellm_init_timer_monitor(void)3354 gkrellm_init_timer_monitor(void)
3355 	{
3356 	if (!mon_net)
3357 		return NULL;
3358     monitor_timer.name = _(monitor_timer.name);
3359 	timer_style_id = gkrellm_add_meter_style(&monitor_timer, TIMER_STYLE_NAME);
3360 	mon_timer = &monitor_timer;
3361 	net_data_dir = gkrellm_make_data_file_name("net", NULL);
3362 	reset_mday = 1;
3363 	return &monitor_timer;
3364 	}
3365 
3366