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-private.h"
36 #include "gkrellm-sysdeps.h"
37 #include "inet.h"
38
39 typedef struct
40 {
41 GtkWidget *vbox;
42 gchar *name;
43
44 GkrellmChart *chart;
45 GkrellmChart *chart_minute;
46 GkrellmChart *chart_hour;
47 GkrellmChartconfig *chart_config_minute;
48 GkrellmChartconfig *chart_config_hour;
49 GkrellmPanel *panel;
50 gboolean hour_mode;
51 gint cd_length;
52
53 gboolean extra_info;
54 GkrellmLauncher launch;
55 GtkWidget *launch_entry,
56 *tooltip_entry;
57 GtkWidget *launch_table;
58
59 gshort *mark_data; /* Draw marks if hits for any second */
60 gint mark_position,
61 mark_prev_hits;
62
63 GkrellmDecal *list_decal;
64 GkrellmDecalbutton *list_button;
65 GString *connection_string;
66 GList *tcp_save_list;
67 gboolean busy;
68 gboolean connection_string_event;
69 gboolean config_modified;
70
71 gchar *label0;
72 gint active0;
73 gint prev_active0;
74 gulong hits0_minute,
75 hits0_hour;
76 gboolean data0_is_range;
77 gulong port0_0,
78 port0_1;
79
80 gchar *label1;
81 gint active1;
82 gint prev_active1;
83 gulong hits1_minute,
84 hits1_hour;
85 gboolean data1_is_range;
86 gulong port1_0,
87 port1_1;
88
89 gulong krell_hits;
90 }
91 InetMon;
92
93 static GkrellmMonitor *mon_inet;
94
95 static GList *inet_mon_list;
96 static GList *active_tcp_list,
97 *free_tcp_list;
98
99 void (*read_tcp_data)();
100
101 static GtkWidget *inet_vbox;
102 static GdkImage *grid;
103
104 static gchar *inet_data_dir;
105 static gchar *text_format,
106 *text_format_locale;
107
108 static gint n_inet_monitors,
109 update_interval = 1;
110 static gint style_id;
111
112
113
114 static ActiveTCP *
_tcp_alloc(void)115 _tcp_alloc(void)
116 {
117 ActiveTCP *tcp;
118
119 if (free_tcp_list)
120 {
121 tcp = free_tcp_list->data;
122 free_tcp_list = g_list_remove(free_tcp_list, tcp);
123 }
124 else
125 tcp = g_new0(ActiveTCP, 1);
126 return tcp;
127 }
128
129 static ActiveTCP *
_log_active_port(ActiveTCP * tcp)130 _log_active_port(ActiveTCP *tcp)
131 {
132 GList *list;
133 ActiveTCP *active_tcp, *new_tcp;
134 gchar *ap, *aap;
135 gint slen;
136
137 for (list = active_tcp_list; list; list = list->next)
138 {
139 active_tcp = (ActiveTCP *) (list->data);
140 if (tcp->family == AF_INET)
141 {
142 ap = (char *)&tcp->remote_addr;
143 aap = (char *)&active_tcp->remote_addr;
144 slen = sizeof(struct in_addr);
145 }
146 #if defined(INET6)
147 else if (tcp->family == AF_INET6)
148 {
149 ap = (char *)&tcp->remote_addr6;
150 aap = (char *)&active_tcp->remote_addr6;
151 slen = sizeof(struct in6_addr);
152 }
153 #endif
154 else
155 return 0;
156 if ( memcmp(aap, ap, slen) == 0
157 && active_tcp->remote_port == tcp->remote_port
158 && active_tcp->local_port == tcp->local_port
159 )
160 {
161 active_tcp->state = TCP_ALIVE;
162 return active_tcp; /* Old hit still alive, not a new hit */
163 }
164 }
165 tcp->state = TCP_ALIVE;
166 tcp->new_hit = 1;
167 new_tcp = _tcp_alloc();
168 *new_tcp = *tcp;
169
170 if (_GK.debug_level & DEBUG_INET)
171 {
172 ap = inet_ntoa(tcp->remote_addr);
173 g_debug("inet OO-----> %x %s:%x\n",
174 tcp->local_port, ap, tcp->remote_port);
175 }
176 active_tcp_list = g_list_prepend(active_tcp_list, (gpointer) new_tcp);
177 return new_tcp; /* A new hit */
178 }
179
180 void
gkrellm_inet_log_tcp_port_data(gpointer data)181 gkrellm_inet_log_tcp_port_data(gpointer data)
182 {
183 GList *list;
184 InetMon *in;
185 ActiveTCP *tcp, *active_tcp = NULL;
186 gint krell_hit;
187
188 tcp = (ActiveTCP *) data;
189 for (list = inet_mon_list; list; list = list->next)
190 {
191 krell_hit = 0;
192 in = (InetMon *) list->data;
193 if ( (!in->data0_is_range
194 && ( in->port0_0 == tcp->local_port
195 || in->port0_1 == tcp->local_port))
196 || (in->data0_is_range
197 && tcp->local_port >= in->port0_0
198 && tcp->local_port <= in->port0_1)
199 )
200 {
201 ++in->active0;
202 active_tcp = _log_active_port(tcp);
203 krell_hit = active_tcp->new_hit;
204 in->hits0_minute += krell_hit;
205 in->hits0_hour += krell_hit;
206 }
207 if ( (!in->data1_is_range
208 && ( in->port1_0 == tcp->local_port
209 || in->port1_1 == tcp->local_port))
210 || (in->data1_is_range
211 && tcp->local_port >= in->port1_0
212 && tcp->local_port <= in->port1_1)
213 )
214 {
215 ++in->active1;
216 active_tcp = _log_active_port(tcp);
217 krell_hit = active_tcp->new_hit;
218 in->hits1_minute += krell_hit;
219 in->hits1_hour += krell_hit;
220 }
221 in->krell_hits += krell_hit;
222 }
223 /* Defer setting new hit to 0 until here so multiple inet charts can
224 | monitor the same port number. The above active_port will be the
225 | same if found for both data0 and data1.
226 */
227 if (active_tcp)
228 active_tcp->new_hit = 0;
229 }
230
231
232 static gboolean
setup_inet_interface(void)233 setup_inet_interface(void)
234 {
235 if (!read_tcp_data && !_GK.client_mode && gkrellm_sys_inet_init())
236 {
237 read_tcp_data = gkrellm_sys_inet_read_tcp_data;
238 }
239 return read_tcp_data ? TRUE : FALSE;
240 }
241
242 void
gkrellm_inet_client_divert(void (* read_tcp_func)())243 gkrellm_inet_client_divert(void (*read_tcp_func)())
244 {
245 read_tcp_data = read_tcp_func;
246 }
247
248
249 /* ======================================================================== */
250
251 #define DUMP_IN(in,tag) g_debug("%s: %s %s %ld %ld %ld %ld\n", \
252 tag, in->label0, in->label1, \
253 in->port0_0, in->port0_1, in->port1_0, in->port1_1);
254
255 static void
format_chart_text(InetMon * in,gchar * src_string,gchar * buf,gint size)256 format_chart_text(InetMon *in, gchar *src_string, gchar *buf, gint size)
257 {
258 GList *list;
259 GkrellmChart *cp;
260 GkrellmChartdata *cd;
261 gchar c, *s, *s1;
262 gint len, value, n, i, w;
263
264 if (!buf || size < 1)
265 return;
266 --size;
267 *buf = '\0';
268 if (!src_string)
269 return;
270 cp = in->chart;
271 w = gkrellm_chart_width();
272 for (s = text_format_locale; *s != '\0' && size > 0; ++s)
273 {
274 len = 1;
275 if (*s == '$' && *(s + 1) != '\0')
276 {
277 value = -1;
278 s1 = " ";
279 if ((c = *(s + 1)) == 'M')
280 value = gkrellm_get_chart_scalemax(cp);
281 else if (c == 'a' && *in->label0)
282 value = in->active0;
283 else if (c == 'l' && *in->label0)
284 s1 = in->label0;
285 else if (c == 'c' && *(s + 2))
286 {
287 i = 0;
288 sscanf(s + 2, "%d%n", &n, &i);
289 s += i;
290 --n;
291 if (n > w || n < 0)
292 n = w;
293 list = in->hour_mode ?
294 in->chart_hour->cd_list : in->chart_minute->cd_list;
295 cd = (GkrellmChartdata *) list->data;
296 if (*in->label0)
297 {
298 value = in->hour_mode ? in->hits0_hour : in->hits0_minute;
299 for ( ; n > 0; --n)
300 value += gkrellm_get_chartdata_data(cd, w - n);
301 }
302 }
303 else if (c == 'A' && *in->label1)
304 value = in->active1;
305 else if (c == 'L' && *in->label1)
306 s1 = in->label1;
307 else if (c == 'C' && *(s + 2))
308 {
309 i = 0;
310 sscanf(s + 2, "%d%n", &n, &i);
311 s += i;
312 --n;
313 if (n > w || n < 0)
314 n = w;
315 list = in->hour_mode ?
316 in->chart_hour->cd_list : in->chart_minute->cd_list;
317 if (list->next)
318 list = list->next;
319 cd = (GkrellmChartdata *) list->data;
320 if (*in->label1)
321 {
322 value = in->hour_mode ? in->hits1_hour : in->hits1_minute;
323 for ( ; n > 0; --n)
324 value += gkrellm_get_chartdata_data(cd, w - n);
325 }
326 }
327 else if (c == 'H')
328 s1 = gkrellm_sys_get_host_name();
329 if (value >= 0)
330 len = snprintf(buf, size, "%d", value);
331 else
332 len = snprintf(buf, size, "%s", s1);
333 ++s;
334 }
335 else
336 *buf = *s;
337 size -= len;
338 buf += len;
339 }
340 *buf = '\0';
341 }
342
343 static void
draw_inet_extra(InetMon * in)344 draw_inet_extra(InetMon *in)
345 {
346 gchar buf[128];
347
348 if (!in->extra_info)
349 return;
350 format_chart_text(in, text_format_locale, buf, sizeof(buf));
351 gkrellm_draw_chart_text(in->chart, style_id, buf);
352 }
353
354 /* Use the reserved area below the main chart to draw marks if any
355 | hits in second intervals.
356 */
357 static void
draw_inet_mark_data(InetMon * in,gint minute_mark)358 draw_inet_mark_data(InetMon *in, gint minute_mark)
359 {
360 GkrellmChart *cp;
361 GdkGC *gc1, *gc2, *gc3;
362 gint hits, x, y, n;
363
364 cp = in->chart;
365 in->mark_position = (in->mark_position + 1) % cp->w;
366 if (minute_mark)
367 {
368 in->mark_data[in->mark_position] = -1; /* minute flag in the data */
369 return;
370 }
371 hits = in->hits0_minute + in->hits1_minute;
372 in->mark_data[in->mark_position] = hits - in->mark_prev_hits;
373 in->mark_prev_hits = hits;
374
375 gc1 = gkrellm_draw_GC(1);
376 gc2 = gkrellm_draw_GC(2);
377 gc3 = gkrellm_draw_GC(3);
378
379 /* Clear out the area and redraw the marks.
380 */
381 y = cp->h - cp->y;
382 gdk_draw_drawable(cp->pixmap, gc1, cp->bg_src_pixmap,
383 0, y, 0, y, cp->w, cp->y);
384 gdk_gc_set_foreground(gc1, gkrellm_out_color());
385 gdk_gc_set_foreground(gc2, gkrellm_in_color());
386 gdk_gc_set_foreground(gc3, gkrellm_white_color());
387 for (n = 0; n < cp->w; ++n)
388 {
389 x = (in->mark_position + n + 1) % cp->w;
390 if (in->mark_data[x] > 0)
391 gdk_draw_line(cp->pixmap, gc1,
392 cp->x + n, cp->h - 1, cp->x + n, y);
393 else if (in->mark_data[x] == -1) /* Minute tick */
394 gdk_draw_line(cp->pixmap, gc3,
395 cp->x + n, cp->h - 1, cp->x + n, y);
396 }
397 gdk_draw_drawable(cp->drawing_area->window, gc1, cp->pixmap,
398 0, y, 0, y, cp->w, cp->y);
399 }
400
401 static void
draw_inet_chart(InetMon * in)402 draw_inet_chart(InetMon *in)
403 {
404 struct tm tm;
405 GdkGC *gc3;
406 GkrellmChart *cp;
407 GkrellmTextstyle *ts;
408 GdkColor tmp_color;
409 gchar buf[32];
410 guint32 pixel0, pixel1;
411 gint y0, h4, w, h, n;
412
413 cp = in->chart;
414 gkrellm_draw_chartdata(cp);
415
416 y0 = cp->h - cp->y;
417 h4 = y0 / 4;
418 gdk_drawable_get_size(in->chart->bg_grid_pixmap, &w, &h);
419 if (grid == NULL)
420 grid = gdk_drawable_get_image(in->chart->bg_grid_pixmap, 0, 0, w, h);
421 ts = gkrellm_chart_alt_textstyle(style_id);
422
423 tm = *gkrellm_get_current_time();
424 gc3 = gkrellm_draw_GC(3);
425 gdk_gc_set_foreground(gkrellm_draw_GC(3), gkrellm_white_color());
426 if (in->hour_mode)
427 {
428 for (n = cp->w - 1; n >= 0; --n)
429 {
430 /* When hour ticked to 0, 23rd hour data was stored and a slot
431 | was skipped.
432 */
433 if (tm.tm_hour == 0) /* Draw day mark at midnight */
434 {
435 pixel0 = gdk_image_get_pixel(grid, cp->x + n, 0);
436 tmp_color.pixel = pixel0;
437 gdk_gc_set_foreground(gc3, &tmp_color);
438 gdk_draw_line(cp->pixmap, gc3,
439 cp->x + n - 1, y0 - 3, cp->x + n - 1, 3);
440 if (h > 1)
441 {
442 pixel1 = gdk_image_get_pixel(grid, cp->x + n, 1);
443 tmp_color.pixel = pixel1;
444 gdk_gc_set_foreground(gc3, &tmp_color);
445 gdk_draw_line(cp->pixmap, gc3,
446 cp->x + n, y0 - 3, cp->x + n, 3);
447 }
448 }
449 if (in->extra_info && tm.tm_hour == 1 && n < cp->w - 5)
450 {
451 strftime(buf, sizeof(buf), "%a", &tm);
452 buf[1] = '\0';
453 gkrellm_draw_chart_label(in->chart, ts,
454 cp->x + n, in->chart->h - 4, buf);
455 }
456 if (--tm.tm_hour < 0)
457 {
458 tm.tm_hour = 24; /* Extra hour for skipped slot */
459 if (--tm.tm_wday < 0)
460 tm.tm_wday = 6;
461 }
462 }
463 }
464 else
465 {
466 for (n = cp->w - 1; n >= 0; --n)
467 {
468 /* When minute ticked to 0, 59 minute data was stored and a slot
469 | was skipped.
470 */
471 if (tm.tm_min == 0) /* Draw hour mark */
472 {
473 pixel0 = gdk_image_get_pixel(grid, cp->x + n, 0);
474 tmp_color.pixel = pixel0;
475 gdk_gc_set_foreground(gc3, &tmp_color);
476 gdk_draw_line(cp->pixmap, gc3,
477 cp->x + n - 1, y0 - 3, cp->x + n - 1, y0 - h4);
478 if (h > 1)
479 {
480 pixel1 = gdk_image_get_pixel(grid, cp->x + n, 1);
481 tmp_color.pixel = pixel1;
482 gdk_gc_set_foreground(gc3, &tmp_color);
483 gdk_draw_line(cp->pixmap, gc3,
484 cp->x + n, y0 - 3, cp->x + n, y0 - h4);
485 }
486 }
487 if (--tm.tm_min < 0)
488 tm.tm_min = 60; /* extra minute for skipped slot */
489 }
490 }
491 if (in->extra_info)
492 draw_inet_extra(in);
493 gkrellm_draw_chart_to_screen(cp);
494 in->prev_active0 = in->active0;
495 in->prev_active1 = in->active1;
496 }
497
498 static void
select_hour_or_minute_chart(InetMon * in)499 select_hour_or_minute_chart(InetMon *in)
500 {
501 gkrellm_freeze_side_frame_packing();
502 if (in->hour_mode && in->chart == in->chart_minute)
503 {
504 gkrellm_chart_hide(in->chart_minute, FALSE);
505 gkrellm_chart_show(in->chart_hour, FALSE);
506 in->chart = in->chart_hour;
507 gkrellm_chartconfig_window_destroy(in->chart_minute);
508 }
509 else if (!in->hour_mode && in->chart == in->chart_hour)
510 {
511 gkrellm_chart_hide(in->chart_hour, FALSE);
512 gkrellm_chart_show(in->chart_minute, FALSE);
513 in->chart = in->chart_minute;
514 gkrellm_chartconfig_window_destroy(in->chart_hour);
515 }
516 gkrellm_thaw_side_frame_packing();
517 }
518
519 static void
update_inet(void)520 update_inet(void)
521 {
522 InetMon *in;
523 ActiveTCP *tcp;
524 GList *list;
525 gchar buf[32], *ap;
526 gint i;
527 static gint check_tcp;
528
529 if (!inet_mon_list)
530 return;
531
532 if (GK.second_tick && check_tcp == 0)
533 {
534 for (list = inet_mon_list; list; list = list->next)
535 {
536 in = (InetMon *) list->data;
537 in->active0 = 0;
538 in->active1 = 0;
539 }
540 /* Assume all connections are dead, then read_tcp_data() will set
541 | still alive ones back to alive. Then I can prune really dead ones.
542 */
543 for (list = active_tcp_list; list; list = list->next)
544 {
545 tcp = (ActiveTCP *)(list->data);
546 tcp->state = TCP_DEAD;
547 }
548
549 (*read_tcp_data)();
550
551 for (list = active_tcp_list; list; )
552 {
553 tcp = (ActiveTCP *)(list->data);
554 if (tcp->state == TCP_DEAD)
555 {
556 if (list == active_tcp_list)
557 active_tcp_list = active_tcp_list->next;
558 list = g_list_remove(list, tcp);
559 if (_GK.debug_level & DEBUG_INET)
560 {
561 ap = inet_ntoa(tcp->remote_addr);
562 g_debug("inet XX-----> %x %s:%x\n",
563 tcp->local_port, ap, tcp->remote_port);
564 }
565 free_tcp_list = g_list_prepend(free_tcp_list, tcp);
566 }
567 else
568 list = list->next;
569 }
570 }
571 if (GK.second_tick)
572 check_tcp = (check_tcp + 1) % update_interval;
573
574 for (list = inet_mon_list; list; list = list->next)
575 {
576 in = (InetMon *) list->data;
577 if (GK.hour_tick)
578 {
579 if (!*in->label0)
580 in->hits0_hour = in->hits1_hour;
581 gkrellm_store_chartdata(in->chart_hour, 0,
582 in->hits0_hour, in->hits1_hour);
583 in->hits0_hour = in->hits1_hour = 0;
584 if (GK.day_tick) /* Make room for vertical day grid */
585 {
586 gkrellm_store_chartdata(in->chart_hour, 0, 0, 0);
587 gkrellm_store_chartdata(in->chart_hour, 0, 0, 0);
588 }
589 }
590 if (GK.minute_tick)
591 {
592 if (!*in->label0)
593 in->hits0_minute = in->hits1_minute;
594 gkrellm_store_chartdata(in->chart_minute, 0,
595 in->hits0_minute, in->hits1_minute);
596 in->hits0_minute = in->hits1_minute = 0;
597 if (GK.hour_tick) /* Make room for vertical hour grid */
598 {
599 gkrellm_store_chartdata(in->chart_minute, 0, 0, 0);
600 gkrellm_store_chartdata(in->chart_minute, 0, 0, 0);
601 }
602 gkrellm_refresh_chart(in->chart);
603 draw_inet_mark_data(in, 1);
604 }
605 else if ( GK.second_tick
606 && ( in->prev_active0 != in->active0
607 || in->prev_active1 != in->active1
608 )
609 )
610 draw_inet_chart(in); /* Just to update extra info draw */
611
612 if (GK.second_tick)
613 draw_inet_mark_data(in, 0);
614
615 if (in->busy && in->list_button->cur_index == D_MISC_BUTTON_OUT)
616 i = D_MISC_BUTTON_ON;
617 else
618 i = D_MISC_BUTTON_OUT;
619 gkrellm_set_decal_button_index(in->list_button, i);
620
621 gkrellm_update_krell(in->panel, KRELL(in->panel), in->krell_hits);
622 gkrellm_draw_panel_layers(in->panel);
623
624 if (in->connection_string_event)
625 {
626 snprintf(buf, sizeof(buf), _("%s Connections"), in->name);
627 gkrellm_message_dialog(buf, in->connection_string->str);
628 in->connection_string_event = FALSE;
629 in->busy = FALSE;
630 }
631 }
632 }
633
634 static gboolean
tcp_port_is_monitored(ActiveTCP * tcp,gboolean range,gulong p0,gulong p1)635 tcp_port_is_monitored(ActiveTCP *tcp, gboolean range, gulong p0, gulong p1)
636 {
637 if ( (!range && (p0 == tcp->local_port || p1 == tcp->local_port))
638 || ( range && tcp->local_port >= p0 && tcp->local_port <= p1)
639 )
640 return TRUE;
641 return FALSE;
642 }
643
644 static gpointer
get_connection_string_thread(void * data)645 get_connection_string_thread(void *data)
646 {
647 InetMon *in = (InetMon *) data;
648 GList *list;
649 ActiveTCP *tcp;
650 #if defined(INET6)
651 union {
652 struct sockaddr_storage ss;
653 struct sockaddr_in sin;
654 struct sockaddr_in6 sin6;
655 struct sockaddr sa;
656 } ss;
657 gint salen, flag = 0;
658 gchar hbuf[NI_MAXHOST];
659 gchar buf[NI_MAXHOST + 64];
660 #else
661 struct hostent *hostent;
662 gchar buf[128];
663 #endif
664 gchar *remote_host, *udp_note;
665
666 if (in->connection_string)
667 in->connection_string = g_string_truncate(in->connection_string, 0);
668 else
669 in->connection_string = g_string_new("");
670 for (list = in->tcp_save_list; list; list = list->next)
671 {
672 tcp = (ActiveTCP *) list->data;
673 #if defined(INET6)
674 memset(&ss.ss, 0, sizeof(ss.ss));
675 switch (tcp->family)
676 {
677 case AF_INET:
678 salen = sizeof(struct sockaddr_in);
679 memcpy(&ss.sin.sin_addr, &tcp->remote_addr, salen);
680 #if defined(SIN6_LEN)
681 ss.sin.sin_len = salen;
682 #endif
683 ss.sin.sin_family = tcp->family;
684 break;
685 case AF_INET6:
686 salen = sizeof(struct sockaddr_in6);
687 memcpy(&ss.sin6.sin6_addr, &tcp->remote_addr6, salen);
688 #if defined(SIN6_LEN)
689 ss.sin6.sin6_len = salen;
690 #endif
691 ss.sin6.sin6_family = tcp->family;
692 /* XXX: We should mention about
693 | scope, too. */
694 break;
695 default:
696 continue;
697 }
698 if (getnameinfo(&ss.sa, salen,
699 hbuf, sizeof(hbuf), NULL, 0, flag))
700 continue;
701 remote_host = hbuf;
702 #else
703 hostent = gethostbyaddr((char *) &tcp->remote_addr,
704 sizeof(struct in_addr), AF_INET);
705 if (hostent)
706 remote_host = hostent->h_name;
707 else
708 remote_host = inet_ntoa(tcp->remote_addr);
709 #endif
710 udp_note = tcp->is_udp ? " (UDP)" : "";
711 snprintf(buf, sizeof(buf), "%6d: %s%s\n",
712 tcp->local_port, remote_host, udp_note);
713
714 g_string_append(in->connection_string, buf);
715 }
716 if (in->connection_string->len == 0)
717 g_string_append(in->connection_string, _("No current connections."));
718 in->connection_string_event = TRUE;
719 gkrellm_free_glist_and_data(&in->tcp_save_list);
720 return NULL;
721 }
722
723 static void
cb_list_button(GkrellmDecalbutton * button)724 cb_list_button(GkrellmDecalbutton *button)
725 {
726 InetMon *in = (InetMon *) button->data;
727 GList *list;
728 GThread *gth;
729 ActiveTCP *tcp, *tcp_save;
730
731 if (in->busy)
732 return;
733 in->busy = TRUE;
734
735 /* Save a snapshot of active connections so I don't have to worry about
736 | the active_tcp_list changing while in the thread.
737 */
738 for (list = active_tcp_list; list; list = list->next)
739 {
740 tcp = (ActiveTCP *) list->data;
741 if ( tcp_port_is_monitored(tcp, in->data0_is_range,
742 in->port0_0, in->port0_1)
743 || tcp_port_is_monitored(tcp, in->data1_is_range,
744 in->port1_0, in->port1_1)
745 )
746 {
747 tcp_save = g_new0(ActiveTCP, 1);
748 *tcp_save = *tcp;
749 in->tcp_save_list = g_list_append(in->tcp_save_list, tcp_save);
750 }
751 }
752 gth = g_thread_new("get_connection_string",
753 get_connection_string_thread, in);
754 g_thread_unref(gth);
755 }
756
757 static gint
inet_expose_event(GtkWidget * widget,GdkEventExpose * ev)758 inet_expose_event(GtkWidget *widget, GdkEventExpose *ev)
759 {
760 InetMon *in;
761 GList *list;
762 GdkPixmap *pixmap = NULL;
763
764 for (list = inet_mon_list; list; list = list->next)
765 {
766 in = (InetMon *) list->data;
767 if (widget == in->panel->drawing_area)
768 pixmap = in->panel->pixmap;
769 else if (widget == in->chart_minute->drawing_area)
770 pixmap = in->chart_minute->pixmap;
771 else if (widget == in->chart_hour->drawing_area)
772 pixmap = in->chart_hour->pixmap;
773 if (pixmap)
774 {
775 gdk_draw_drawable(widget->window, gkrellm_draw_GC(1), pixmap,
776 ev->area.x, ev->area.y, ev->area.x, ev->area.y,
777 ev->area.width, ev->area.height);
778 break;
779 }
780 }
781 return FALSE;
782 }
783
784 static gint
cb_inet_extra(GtkWidget * widget,GdkEventButton * ev)785 cb_inet_extra(GtkWidget *widget, GdkEventButton *ev)
786 {
787 InetMon *in;
788 GList *list;
789
790 for (list = inet_mon_list; list; list = list->next)
791 {
792 in = (InetMon *) list->data;
793 if (widget != in->chart->drawing_area)
794 continue;
795 if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS)
796 {
797 in->extra_info = !in->extra_info;
798 gkrellm_refresh_chart(in->chart);
799 gkrellm_config_modified();
800 }
801 else if (ev->button == 2)
802 {
803 in->hour_mode = !in->hour_mode;
804 select_hour_or_minute_chart(in);
805 gkrellm_rescale_chart(in->chart);
806 }
807 else if ( ev->button == 3
808 || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)
809 )
810 gkrellm_chartconfig_window_create(in->chart);
811 break;
812 }
813 return FALSE;
814 }
815
816 static gint
cb_panel_press(GtkWidget * widget,GdkEventButton * ev)817 cb_panel_press(GtkWidget *widget, GdkEventButton *ev)
818 {
819 if (ev->button == 3)
820 gkrellm_open_config_window(mon_inet);
821 return FALSE;
822 }
823
824 /* Lock the hour and minute heights together.
825 */
826 static void
cb_inet_height(GkrellmChartconfig * cf,InetMon * in)827 cb_inet_height(GkrellmChartconfig *cf, InetMon *in)
828 {
829 gint h;
830
831 h = gkrellm_get_chartconfig_height(cf);
832 if (in->chart_minute->h != h)
833 gkrellm_set_chart_height(in->chart_minute, h);
834 if (in->chart_hour->h != h)
835 gkrellm_set_chart_height(in->chart_hour, h);
836 }
837
838 static void
destroy_inet_monitor(InetMon * in)839 destroy_inet_monitor(InetMon *in)
840 {
841 if (in->launch_table)
842 gtk_widget_destroy(in->launch_table);
843 g_free(in->name);
844 g_free(in->label0);
845 g_free(in->label1);
846 if (in->launch.command)
847 g_free(in->launch.command);
848 if (in->launch.button)
849 gkrellm_destroy_button(in->launch.button);
850 g_free(in->mark_data);
851
852 /* The panel doesn't live in the chart struct, so destroy it separately
853 */
854 gkrellm_panel_destroy(in->panel);
855
856 gkrellm_chartconfig_destroy(&in->chart_config_minute);
857 gkrellm_chart_destroy(in->chart_minute);
858
859 gkrellm_chartconfig_destroy(&in->chart_config_hour);
860 gkrellm_chart_destroy(in->chart_hour);
861
862 gtk_widget_destroy(in->vbox);
863 g_free(in);
864 }
865
866
867 #define MIN_GRID_RES 2
868 #define MAX_GRID_RES 1000000
869 #define DEFAULT_GRID_RES 10
870
871 static void
chart_create(InetMon * in,GkrellmChart * cp,GkrellmChartconfig ** cfp,gint first_create)872 chart_create(InetMon *in, GkrellmChart *cp, GkrellmChartconfig **cfp,
873 gint first_create)
874 {
875 GkrellmChartconfig *cf;
876 GkrellmChartdata *cd;
877 GdkPixmap **src_pixmap, *grid_pixmap;
878
879 cp->y = 3;
880 gkrellm_chart_create(in->vbox, mon_inet, cp, cfp);
881 cf = *cfp;
882
883 /* I accumulate tcp hits myself, so I'm free to make the chartdata
884 | accumulate monotonically or not. I choose not monotonic to make saving
885 | and loading data simpler.
886 */
887 src_pixmap = gkrellm_data_out_pixmap();
888 grid_pixmap = gkrellm_data_out_grid_pixmap();
889 if (*in->label0)
890 {
891 cd = gkrellm_add_chartdata(cp, src_pixmap, grid_pixmap, in->label0);
892 gkrellm_monotonic_chartdata(cd, FALSE);
893 }
894 src_pixmap = gkrellm_data_in_pixmap();
895 grid_pixmap = gkrellm_data_in_grid_pixmap();
896 if (*in->label1)
897 {
898 cd = gkrellm_add_chartdata(cp, src_pixmap, grid_pixmap, in->label1);
899 gkrellm_monotonic_chartdata(cd, FALSE);
900 }
901 gkrellm_set_draw_chart_function(cp, draw_inet_chart, in);
902
903 /* krell is not function of chart grids or resolution, so no interest
904 | in connecting to grid or resolution changes.
905 */
906 gkrellm_chartconfig_height_connect(cf, cb_inet_height, in);
907 gkrellm_chartconfig_grid_resolution_adjustment(cf, TRUE,
908 0, (gfloat) MIN_GRID_RES, (gfloat) MAX_GRID_RES, 0, 0, 0, 70);
909 if (gkrellm_get_chartconfig_grid_resolution(cf) < MIN_GRID_RES)
910 gkrellm_set_chartconfig_grid_resolution(cf, DEFAULT_GRID_RES);
911
912 /* Don't want to waste an hour priming the pump, and don't need to
913 | because data always starts at zero.
914 */
915 cp->primed = TRUE; /* XXX */
916 gkrellm_alloc_chartdata(cp);
917
918 if (first_create)
919 {
920 g_signal_connect(G_OBJECT (cp->drawing_area), "expose_event",
921 G_CALLBACK(inet_expose_event), NULL);
922 g_signal_connect(G_OBJECT(cp->drawing_area),"button_press_event",
923 G_CALLBACK(cb_inet_extra), NULL);
924 }
925 }
926
927 static void
create_inet_monitor(GtkWidget * vbox1,InetMon * in,gint first_create)928 create_inet_monitor(GtkWidget *vbox1, InetMon *in, gint first_create)
929 {
930 GtkWidget *vbox;
931 GkrellmChart *cp;
932 GkrellmPanel *p;
933 GkrellmMargin *m;
934 GkrellmStyle *style;
935 gint x;
936
937 if (first_create)
938 {
939 vbox = gtk_vbox_new(FALSE, 0);
940 gtk_container_add(GTK_CONTAINER(vbox1), vbox);
941 in->vbox = vbox;
942 in->chart_minute = gkrellm_chart_new0();
943 in->chart_hour = gkrellm_chart_new0();
944 in->panel = gkrellm_panel_new0();
945 in->chart = in->chart_minute;
946 in->name = g_strdup_printf(_("inet%d"), n_inet_monitors++);
947 }
948 else
949 {
950 vbox = in->vbox;
951 gkrellm_destroy_decal_list(in->panel);
952 gkrellm_destroy_krell_list(in->panel);
953 }
954 if (in->chart_config_hour && in->chart_config_minute)
955 in->chart_config_hour->h = in->chart_config_minute->h;
956 chart_create(in, in->chart_minute, &in->chart_config_minute, first_create);
957 gkrellm_chartconfig_grid_resolution_label(in->chart_config_minute,
958 _("TCP hits per minute"));
959 chart_create(in, in->chart_hour, &in->chart_config_hour, first_create);
960 gkrellm_chartconfig_grid_resolution_label(in->chart_config_hour,
961 _("TCP hits per hour"));
962 cp = in->chart;
963
964 p = in->panel;
965 style = gkrellm_panel_style(style_id);
966 m = gkrellm_get_style_margins(style);
967 if (style->label_position == 50 && gkrellm_chart_width() < 80)
968 style->label_position = 40; /* Not a kludge, an adjustment! */
969 in->list_decal = gkrellm_create_decal_pixmap(p,
970 gkrellm_decal_misc_pixmap(), gkrellm_decal_misc_mask(),
971 N_MISC_DECALS, style, -1, -1);
972 if (style->label_position <= 50)
973 x = gkrellm_chart_width() - in->list_decal->w - m->right;
974 else
975 x = m->left;
976 gkrellm_move_decal(p, in->list_decal, x, in->list_decal->y);
977
978 gkrellm_create_krell(p, gkrellm_krell_panel_piximage(style_id), style);
979
980 /* Inet krells are not related to chart scale_max. Just give a constant
981 | full scale of 5.
982 */
983 KRELL(p)->full_scale = 5;
984 gkrellm_panel_configure(p, in->name, style);
985 gkrellm_panel_create(vbox, mon_inet, p);
986
987 /* At first_create both charts will be visible, but this will be
988 | undone below
989 */
990 in->list_button = gkrellm_make_decal_button(p, in->list_decal,
991 cb_list_button, in, D_MISC_BUTTON_OUT, D_MISC_BUTTON_IN);
992
993 if (first_create)
994 {
995 g_signal_connect(G_OBJECT(p->drawing_area),"expose_event",
996 G_CALLBACK(inet_expose_event), NULL);
997 g_signal_connect(G_OBJECT(p->drawing_area), "button_press_event",
998 G_CALLBACK(cb_panel_press), NULL);
999
1000 gtk_widget_show(vbox);
1001 gkrellm_chart_hide(in->chart_hour, FALSE);
1002 }
1003 gkrellm_setup_launcher(p, &in->launch, CHART_PANEL_TYPE, 4);
1004
1005 if (in->mark_data)
1006 g_free(in->mark_data);
1007 in->mark_data = g_new0(gshort, cp->w);
1008
1009 if (! first_create)
1010 gkrellm_rescale_chart(in->chart);
1011 }
1012
1013 static void
create_inet(GtkWidget * vbox,gint first_create)1014 create_inet(GtkWidget *vbox, gint first_create)
1015 {
1016 GList *list;
1017 gint new_data = FALSE;
1018 gint i;
1019 static gint last_chart_width;
1020
1021 inet_vbox = vbox;
1022 if (grid)
1023 {
1024 g_object_unref(G_OBJECT(grid));
1025 grid = NULL;
1026 }
1027 n_inet_monitors = 0;
1028 if (!first_create && last_chart_width != gkrellm_chart_width())
1029 { /* Will be allocating new data arrays */
1030 gkrellm_inet_save_data();
1031 new_data = TRUE;
1032 last_chart_width = gkrellm_chart_width();
1033 }
1034 for (i = 0, list = inet_mon_list; list; ++i, list = list->next)
1035 create_inet_monitor(inet_vbox, (InetMon *)list->data, first_create);
1036 if (first_create || new_data)
1037 gkrellm_inet_load_data();
1038 if (inet_mon_list)
1039 gkrellm_spacers_show(mon_inet);
1040 else
1041 gkrellm_spacers_hide(mon_inet);
1042 }
1043
1044 static InetMon *
lookup_inet(gchar * name)1045 lookup_inet(gchar *name)
1046 {
1047 InetMon *in;
1048 GList *list;
1049
1050 for (list = inet_mon_list; list; list = list->next)
1051 {
1052 in = (InetMon *) list->data;
1053 if (name && in->name && !strcmp(in->name, name))
1054 return in;
1055 }
1056 return NULL;
1057 }
1058
1059 /* --------------------------------------------------------------------- */
1060 #define INET_CONFIG_KEYWORD "inet"
1061
1062 static void
save_inet_config(FILE * f)1063 save_inet_config(FILE *f)
1064 {
1065 GList *list;
1066 InetMon *in;
1067 gchar buf[128];
1068 gchar *l0, *l1;
1069 gint i;
1070
1071 for (i = 0, list = inet_mon_list; list; list = list->next, ++i)
1072 {
1073 in = (InetMon *) list->data;
1074 l0 = (*in->label0) ? in->label0: "NONE";
1075 l1 = (*in->label1) ? in->label1: "NONE";
1076 fprintf(f, "%s monitor %s %s %lu %lu %s %lu %lu %d %d %d\n",
1077 INET_CONFIG_KEYWORD, in->name,
1078 l0, in->port0_0, in->port0_1,
1079 l1, in->port1_0, in->port1_1,
1080 in->extra_info, in->data0_is_range, in->data1_is_range);
1081 snprintf(buf, sizeof(buf), "%s:minute", in->name);
1082 gkrellm_save_chartconfig(f, in->chart_config_minute,
1083 INET_CONFIG_KEYWORD, buf);
1084 snprintf(buf, sizeof(buf), "%s:hour", in->name);
1085 gkrellm_save_chartconfig(f, in->chart_config_hour,
1086 INET_CONFIG_KEYWORD, buf);
1087 if (in->launch.command)
1088 fprintf(f, "%s launch %s %s\n", INET_CONFIG_KEYWORD,
1089 in->name, in->launch.command);
1090 if (in->launch.tooltip_comment)
1091 fprintf(f, "%s tooltip %s %s\n", INET_CONFIG_KEYWORD,
1092 in->name, in->launch.tooltip_comment);
1093 }
1094 fprintf(f, "%s text_format all %s\n", INET_CONFIG_KEYWORD, text_format);
1095 if (!_GK.client_mode)
1096 fprintf(f, "%s update_interval all %d\n",
1097 INET_CONFIG_KEYWORD, update_interval);
1098 }
1099
1100 static gint
fix_ports(InetMon * in)1101 fix_ports(InetMon *in)
1102 {
1103 gint cd_length = 2;
1104 gulong tmp;
1105
1106 if (!*in->label0)
1107 {
1108 in->port0_1 = 0;
1109 in->data0_is_range = 0;
1110 --cd_length;
1111 }
1112 if (!*in->label1)
1113 {
1114 in->port1_1 = 0;
1115 in->data1_is_range = 0;
1116 --cd_length;
1117 }
1118 if (in->data0_is_range && (in->port0_1 < in->port0_0))
1119 {
1120 tmp = in->port0_1;
1121 in->port0_1 = in->port0_0;
1122 in->port0_0 = tmp;
1123 }
1124 if (in->data1_is_range && (in->port1_1 < in->port1_0))
1125 {
1126 tmp = in->port1_1;
1127 in->port1_1 = in->port1_0;
1128 in->port1_0 = tmp;
1129 }
1130 return cd_length;
1131 }
1132
1133 static void
load_inet_config(gchar * arg)1134 load_inet_config(gchar *arg)
1135 {
1136 InetMon *in;
1137 gchar config[32], name[32];
1138 gchar item[CFG_BUFSIZE];
1139 gchar label0[16], label1[16];
1140 gchar *hr_min;
1141 gint n;
1142
1143 if ((n = sscanf(arg, "%31s %31s %[^\n]", config, name, item)) != 3)
1144 return;
1145 hr_min = strrchr(name, (gint) ':');
1146 if (hr_min)
1147 *hr_min++ = '\0';
1148 if (!strcmp(config, "text_format"))
1149 {
1150 gkrellm_locale_dup_string(&text_format, item, &text_format_locale);
1151 return;
1152 }
1153 else if (!strcmp(config, "update_interval"))
1154 {
1155 sscanf(item, "%d", &update_interval);
1156 if (update_interval < 1)
1157 update_interval = 1;
1158 }
1159 else if (!strcmp(config, "monitor"))
1160 {
1161 in = g_new0(InetMon, 1);
1162 label0[0] = '\0';
1163 label1[0] = '\0';
1164 sscanf(item, "%15s %lu %lu %15s %lu %lu %d %d %d",
1165 label0, &in->port0_0, &in->port0_1,
1166 label1, &in->port1_0, &in->port1_1,
1167 &in->extra_info, &in->data0_is_range, &in->data1_is_range);
1168 if (!strcmp(label0, "NONE"))
1169 label0[0] = '\0';
1170 if (!strcmp(label1, "NONE"))
1171 label1[0] = '\0';
1172 in->label0 = g_strdup(label0);
1173 in->label1 = g_strdup(label1);
1174 in->cd_length = fix_ports(in);
1175 if (in->cd_length > 0)
1176 {
1177 in->name = g_strdup(name);
1178 in->chart_config_minute = gkrellm_chartconfig_new0();
1179 in->chart_config_hour = gkrellm_chartconfig_new0();
1180 inet_mon_list = g_list_append(inet_mon_list, in);
1181 }
1182 else /* Bogus config line */
1183 {
1184 g_free(in->label0);
1185 g_free(in->label1);
1186 g_free(in);
1187 }
1188 return;
1189 }
1190 if ((in = lookup_inet(name)) == NULL)
1191 return;
1192 if (!strcmp(config, GKRELLM_CHARTCONFIG_KEYWORD))
1193 {
1194 if (hr_min && !strcmp(hr_min, "hour"))
1195 gkrellm_load_chartconfig(&in->chart_config_hour, item,
1196 in->cd_length);
1197 if (hr_min && !strcmp(hr_min, "minute"))
1198 gkrellm_load_chartconfig(&in->chart_config_minute, item,
1199 in->cd_length);
1200 }
1201 else if (!strcmp(config, "launch"))
1202 gkrellm_dup_string(&in->launch.command, item);
1203 else if (!strcmp(config, "tooltip"))
1204 gkrellm_dup_string(&in->launch.tooltip_comment, item);
1205 }
1206
1207
1208 /* --------------------------------------------------------------------- */
1209
1210 /* Read saved inet data (from a previous gkrellm process). Return the
1211 | number of missing data slots (skew).
1212 */
1213 static gint
read_inet_data(GkrellmChart * cp,FILE * f,gint minute_chart,gint min,gint hour,gint yday,gint width)1214 read_inet_data(GkrellmChart *cp, FILE *f, gint minute_chart,
1215 gint min, gint hour, gint yday, gint width)
1216 {
1217 struct tm *tm;
1218 gchar data[64];
1219 gint n, in, out, cur_slot, skew, day;
1220
1221 tm = gkrellm_get_current_time();
1222 day = tm->tm_yday - yday;
1223
1224 /* Check for new years wrap around. I don't handle leap year here, will
1225 | get some email, then be safe for four more years...
1226 */
1227 if (day < 0)
1228 day = tm->tm_yday + ((yday < 365) ? 365 - yday : 0);
1229
1230 cur_slot = day * 24 + tm->tm_hour;
1231 n = hour;
1232 if (minute_chart)
1233 {
1234 cur_slot = cur_slot * 60 + tm->tm_min;
1235 n = n * 60 + min;
1236 }
1237 skew = cur_slot - n;
1238
1239 gkrellm_reset_chart(cp);
1240 for (n = 0; n < width; ++n)
1241 {
1242 if (fgets(data, sizeof(data), f) == NULL)
1243 break;
1244
1245 if (skew >= cp->w) /* All stored data is off the chart */
1246 continue;
1247
1248 /* Use chart data storing routines to load in data so I don't care
1249 | if current chart width is less or greater than stored data width.
1250 | Charts will circular buff fill until data runs out.
1251 */
1252 out = in = 0;
1253 sscanf(data, "%d %d", &out, &in);
1254 gkrellm_store_chartdata(cp, 0, out, in);
1255 }
1256 /* Need to store zero data for time slots not in read data to bring
1257 | the chart up to date wrt current time. As in update_inet() I need
1258 | to skip slots for hour or minute ticks.
1259 | Warning: skew can be negative if quit gkrellm, change system clock
1260 | to earlier time, then restart gkrellm.
1261 */
1262 if ((n = skew) < cp->w) /* Do this only if some data was stored */
1263 {
1264 while (n-- > 0)
1265 {
1266 gkrellm_store_chartdata(cp, 0, 0, 0);
1267 if (minute_chart && min++ == 0)
1268 {
1269 gkrellm_store_chartdata(cp, 0, 0, 0);
1270 gkrellm_store_chartdata(cp, 0, 0, 0);
1271 if (min == 60)
1272 min = 0;
1273 }
1274 else if (!minute_chart && hour++ == 0)
1275 {
1276 gkrellm_store_chartdata(cp, 0, 0, 0);
1277 gkrellm_store_chartdata(cp, 0, 0, 0);
1278 if (hour == 24)
1279 hour = 0;
1280 }
1281 }
1282 }
1283 return skew;
1284 }
1285
1286 static void
write_inet_data(GkrellmChart * cp,FILE * f)1287 write_inet_data(GkrellmChart *cp, FILE *f)
1288 {
1289 GList *list;
1290 gint n;
1291
1292 for (n = 0; n < cp->w; ++n)
1293 {
1294 for (list = cp->cd_list; list; list = list->next)
1295 fprintf(f, "%d ",
1296 gkrellm_get_chartdata_data((GkrellmChartdata *) list->data, n));
1297 fprintf(f, "\n");
1298 }
1299 }
1300
1301 static gchar *
make_inet_data_fname(InetMon * in)1302 make_inet_data_fname(InetMon *in)
1303 {
1304 static gchar idata_fname[256];
1305 gchar c_sep0, c_sep1;
1306
1307 c_sep0 = in->data0_is_range ? '-': '_';
1308 c_sep1 = in->data1_is_range ? '-': '_';
1309 snprintf(idata_fname, sizeof(idata_fname), "%s%cinet_%ld%c%ld_%ld%c%ld",
1310 inet_data_dir, G_DIR_SEPARATOR,
1311 in->port0_0, c_sep0, in->port0_1, in->port1_0, c_sep1, in->port1_1);
1312 return idata_fname;
1313 }
1314
1315 void
gkrellm_inet_save_data(void)1316 gkrellm_inet_save_data(void)
1317 {
1318 FILE *f;
1319 struct tm *tm;
1320 GList *list;
1321 InetMon *in;
1322 gchar *fname, buf[64];
1323
1324 tm = gkrellm_get_current_time();
1325 for (list = inet_mon_list; list; list = list->next)
1326 {
1327 in = (InetMon *) list->data;
1328 fname = make_inet_data_fname(in);
1329 if ((f = g_fopen(fname, "w")) == NULL)
1330 continue;
1331
1332 fputs("minute hour yday width\n", f);
1333 snprintf(buf, sizeof(buf), "%d %d %d %d\n", tm->tm_min,
1334 tm->tm_hour, tm->tm_yday, in->chart->w);
1335 fputs(buf, f);
1336
1337 /* Save any accumulated hits which have not been stored into the
1338 | chart data array, and then save the chart data.
1339 */
1340 fputs("hits0_minute hits1_minute hits0_hour hits1_hour\n", f);
1341 fprintf(f, "%ld %ld %ld %ld\n",
1342 in->hits0_minute, in->hits1_minute,
1343 in->hits0_hour, in->hits1_hour);
1344 write_inet_data(in->chart_minute, f);
1345 write_inet_data(in->chart_hour, f);
1346 fclose(f);
1347 }
1348 }
1349
1350 void
gkrellm_inet_load_data(void)1351 gkrellm_inet_load_data(void)
1352 {
1353 FILE *f;
1354 GList *list;
1355 InetMon *in;
1356 gchar buf[96], *fname;
1357 gint min, hour, yday, len, skew;
1358
1359 for (list = inet_mon_list; list; list = list->next)
1360 {
1361 in = (InetMon *) list->data;
1362 fname = make_inet_data_fname(in);
1363 if ((f = g_fopen(fname, "r")) == NULL)
1364 {
1365 gkrellm_reset_chart(in->chart);
1366 draw_inet_chart(in);
1367 continue;
1368 }
1369 fgets(buf, sizeof(buf), f); /* Comment line */
1370 fgets(buf, sizeof(buf), f);
1371 sscanf(buf, "%d %d %d %d", &min, &hour, &yday, &len);
1372 fgets(buf, sizeof(buf), f); /* Comment line */
1373 fgets(buf, sizeof(buf), f);
1374 sscanf(buf, "%lu %lu %lu %lu",
1375 &in->hits0_minute, &in->hits1_minute,
1376 &in->hits0_hour, &in->hits1_hour);
1377
1378 skew = read_inet_data(in->chart_minute, f, 1, min, hour, yday, len);
1379 if (skew > 0) /* Current minute slot is different from saved */
1380 in->hits0_minute = in->hits1_minute = 0;
1381
1382 skew = read_inet_data(in->chart_hour, f, 0, min, hour, yday, len);
1383 if (skew > 0) /* Current hour slot is different from saved */
1384 in->hits0_hour = in->hits1_hour = 0;
1385
1386 fclose(f);
1387 gkrellm_rescale_chart(in->chart);
1388 }
1389 }
1390
1391 /* --------------------------------------------------------------------- */
1392 #define DEFAULT_TEXT_FORMAT "\\t$a\\f $l\\N$A\\f $L"
1393
1394 enum
1395 {
1396 LABEL0_COLUMN,
1397 PORT00_COLUMN,
1398 PORT01_COLUMN,
1399 RANGE0_COLUMN,
1400 SPACER_COLUMN,
1401 LABEL1_COLUMN,
1402 PORT10_COLUMN,
1403 PORT11_COLUMN,
1404 RANGE1_COLUMN,
1405 DUMMY_COLUMN,
1406 INET_COLUMN,
1407 N_COLUMNS
1408 };
1409
1410 static GtkTreeView *treeview;
1411 static GtkTreeRowReference *row_reference;
1412 static GtkTreeSelection *selection;
1413
1414
1415 static GtkWidget *label0_entry,
1416 *label1_entry;
1417 static GtkWidget *port0_0_entry,
1418 *port0_1_entry,
1419 *port1_0_entry,
1420 *port1_1_entry;
1421
1422 static GtkWidget *launch_vbox;
1423
1424 static GtkWidget *data0_range_button,
1425 *data1_range_button;
1426
1427 static GtkWidget *text_format_combo_box;
1428
1429
1430 static void
set_list_store_model_data(GtkListStore * store,GtkTreeIter * iter,InetMon * in)1431 set_list_store_model_data(GtkListStore *store, GtkTreeIter *iter, InetMon *in)
1432 {
1433 gchar p00[16], p01[16], p10[16], p11[16];
1434
1435 snprintf(p00, sizeof(p00), "%d", (int) in->port0_0);
1436 snprintf(p01, sizeof(p01), "%d", (int) in->port0_1);
1437 snprintf(p10, sizeof(p10), "%d", (int) in->port1_0);
1438 snprintf(p11, sizeof(p11), "%d", (int) in->port1_1);
1439 gtk_list_store_set(store, iter,
1440 LABEL0_COLUMN, in->label0,
1441 PORT00_COLUMN, p00,
1442 PORT01_COLUMN, p01,
1443 SPACER_COLUMN, "",
1444 RANGE0_COLUMN, in->data0_is_range,
1445 LABEL1_COLUMN, in->label1,
1446 PORT10_COLUMN, p10,
1447 PORT11_COLUMN, p11,
1448 RANGE1_COLUMN, in->data1_is_range,
1449 DUMMY_COLUMN, "",
1450 -1);
1451 }
1452
1453 static GtkTreeModel *
create_model(void)1454 create_model(void)
1455 {
1456 GtkListStore *store;
1457 GtkTreeIter iter;
1458 GList *list;
1459 InetMon *in;
1460
1461 store = gtk_list_store_new(N_COLUMNS,
1462 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN,
1463 G_TYPE_STRING,
1464 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN,
1465 G_TYPE_STRING, G_TYPE_POINTER);
1466 for (list = inet_mon_list; list; list = list->next)
1467 {
1468 in = (InetMon *) list->data;
1469 in->config_modified = FALSE;
1470 gtk_list_store_append(store, &iter);
1471 set_list_store_model_data(store, &iter, in);
1472 gtk_list_store_set(store, &iter, INET_COLUMN, in, -1);
1473 }
1474 return GTK_TREE_MODEL(store);
1475 }
1476
1477 static void
change_row_reference(GtkTreeModel * model,GtkTreePath * path)1478 change_row_reference(GtkTreeModel *model, GtkTreePath *path)
1479 {
1480 gtk_tree_row_reference_free(row_reference);
1481 if (model && path)
1482 row_reference = gtk_tree_row_reference_new(model, path);
1483 else
1484 row_reference = NULL;
1485 }
1486
1487 static InetMon *
inet_new_from_model(GtkTreeModel * model,GtkTreeIter * iter,gchar * ports[])1488 inet_new_from_model(GtkTreeModel *model, GtkTreeIter *iter, gchar *ports[])
1489 {
1490 InetMon *in;
1491 gchar *_ports[4];
1492 gint i;
1493 gboolean free_ports = FALSE;
1494
1495 if (!ports)
1496 {
1497 ports = _ports;
1498 free_ports = TRUE;
1499 }
1500 in = g_new0(InetMon, 1);
1501 gtk_tree_model_get(model, iter,
1502 LABEL0_COLUMN, &in->label0,
1503 PORT00_COLUMN, &ports[0],
1504 PORT01_COLUMN, &ports[1],
1505 RANGE0_COLUMN, &in->data0_is_range,
1506 LABEL1_COLUMN, &in->label1,
1507 PORT10_COLUMN, &ports[2],
1508 PORT11_COLUMN, &ports[3],
1509 RANGE1_COLUMN, &in->data1_is_range,
1510 -1);
1511 in->port0_0 = atoi(ports[0]);
1512 in->port0_1 = atoi(ports[1]);
1513 in->port1_0 = atoi(ports[2]);
1514 in->port1_1 = atoi(ports[3]);
1515 for (i = 0; i < 4 && free_ports; ++i)
1516 g_free(ports[i]);
1517
1518 return in;
1519 }
1520
1521 static void
reset_entries(void)1522 reset_entries(void)
1523 {
1524 gtk_entry_set_text(GTK_ENTRY(label0_entry), "");
1525 gtk_entry_set_text(GTK_ENTRY(port0_0_entry), "0");
1526 gtk_entry_set_text(GTK_ENTRY(port0_1_entry), "0");
1527 gtk_entry_set_text(GTK_ENTRY(label1_entry), "");
1528 gtk_entry_set_text(GTK_ENTRY(port1_0_entry), "0");
1529 gtk_entry_set_text(GTK_ENTRY(port1_1_entry), "0");
1530 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data0_range_button), 0);
1531 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data1_range_button), 0);
1532
1533 change_row_reference(NULL, NULL);
1534 gtk_tree_selection_unselect_all(selection);
1535 }
1536
1537
1538 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)1539 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
1540 {
1541 GtkTreeIter iter;
1542 GtkTreeModel *model;
1543 GtkTreePath *path;
1544 InetMon *in;
1545 gchar *ports[4];
1546 gint i;
1547
1548 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1549 {
1550 reset_entries();
1551 return;
1552 }
1553 path = gtk_tree_model_get_path(model, &iter);
1554 change_row_reference(model, path);
1555 gtk_tree_path_free(path);
1556
1557 in = inet_new_from_model(model, &iter, ports);
1558
1559 gtk_entry_set_text(GTK_ENTRY(label0_entry), in->label0);
1560 gtk_entry_set_text(GTK_ENTRY(port0_0_entry), ports[0]);
1561 gtk_entry_set_text(GTK_ENTRY(port0_1_entry), ports[1]);
1562 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data0_range_button),
1563 in->data0_is_range);
1564
1565 gtk_entry_set_text(GTK_ENTRY(label1_entry), in->label1);
1566 gtk_entry_set_text(GTK_ENTRY(port1_0_entry), ports[2]);
1567 gtk_entry_set_text(GTK_ENTRY(port1_1_entry), ports[3]);
1568 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data1_range_button),
1569 in->data1_is_range);
1570 g_free(in->label0);
1571 g_free(in->label1);
1572 for (i = 0; i < 4; ++i)
1573 g_free(ports[i]);
1574 }
1575
1576 static void
cb_launch_entry(GtkWidget * widget,InetMon * in)1577 cb_launch_entry(GtkWidget *widget, InetMon *in)
1578 {
1579 gkrellm_apply_launcher(&in->launch_entry, &in->tooltip_entry,
1580 in->panel, &in->launch, gkrellm_launch_button_cb);
1581 }
1582
1583 static void
add_launch_entry(GtkWidget * vbox,InetMon * in)1584 add_launch_entry(GtkWidget *vbox, InetMon *in)
1585 {
1586 in->launch_table = gkrellm_gtk_launcher_table_new(vbox, 1);
1587 gkrellm_gtk_config_launcher(in->launch_table, 0, &in->launch_entry,
1588 &in->tooltip_entry, in->name, &in->launch);
1589 g_signal_connect(G_OBJECT(in->launch_entry), "changed",
1590 G_CALLBACK(cb_launch_entry), in);
1591 g_signal_connect(G_OBJECT(in->tooltip_entry), "changed",
1592 G_CALLBACK(cb_launch_entry), in);
1593 gtk_widget_show_all(in->launch_table);
1594 }
1595
1596
1597 static void
sync_inet_list(void)1598 sync_inet_list(void)
1599 {
1600 GtkTreeModel *model;
1601 GtkTreeIter iter;
1602 InetMon *in, *in_tmp;
1603 GList *list, *new_inet_list;
1604
1605 /* Just save all data and then later read it back in. This avoids
1606 | complicated detecting of name changes while ports the same, moving
1607 | a inet down or up slots, etc. Data is lost only if a port number
1608 | for a monitor is changed.
1609 */
1610 gkrellm_inet_save_data();
1611 new_inet_list = NULL;
1612 n_inet_monitors = 0;
1613
1614 model = gtk_tree_view_get_model(treeview);
1615 if (gtk_tree_model_get_iter_first(model, &iter))
1616 {
1617 do
1618 {
1619 in = inet_new_from_model(model, &iter, NULL);
1620 new_inet_list = g_list_append(new_inet_list, in);
1621 gtk_tree_model_get(model, &iter, INET_COLUMN, &in_tmp, -1);
1622 fix_ports(in);
1623
1624 /* If an existing inet still has the same port numbers, preserve
1625 | its config. Otherwise, it is same as making a new entry.
1626 | (plus the data layers could go from 2 to 1 and then there would
1627 | be an extra data layer in the config - not good).
1628 */
1629 if ( in_tmp
1630 && in_tmp->port0_0 == in->port0_0
1631 && in_tmp->port0_1 == in->port0_1
1632 && in_tmp->port1_0 == in->port1_0
1633 && in_tmp->port1_1 == in->port1_1
1634 )
1635 {
1636 in->chart_config_minute = in_tmp->chart_config_minute;
1637 in_tmp->chart_config_minute = NULL;
1638 in->chart_config_hour = in_tmp->chart_config_hour;
1639 in_tmp->chart_config_hour = NULL;
1640 in->extra_info = in_tmp->extra_info;
1641 in->hour_mode = in_tmp->hour_mode;
1642 }
1643 else
1644 {
1645 in->chart_config_minute = gkrellm_chartconfig_new0();
1646 in->chart_config_hour = gkrellm_chartconfig_new0();
1647 gkrellm_set_chartconfig_auto_grid_resolution(
1648 in->chart_config_minute, TRUE);
1649 gkrellm_set_chartconfig_auto_grid_resolution(
1650 in->chart_config_hour, TRUE);
1651 in->extra_info = TRUE;
1652 }
1653 if (in_tmp)
1654 {
1655 gkrellm_dup_string(&in->launch.command,
1656 in_tmp->launch.command);
1657 gkrellm_dup_string(&in->launch.tooltip_comment,
1658 in_tmp->launch.tooltip_comment);
1659 }
1660 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
1661 INET_COLUMN, in, -1);
1662 }
1663 while (gtk_tree_model_iter_next(model, &iter));
1664 }
1665 while (inet_mon_list)
1666 {
1667 in = (InetMon *) inet_mon_list->data;
1668 destroy_inet_monitor(in);
1669 inet_mon_list = g_list_remove(inet_mon_list, in);
1670 }
1671 inet_mon_list = new_inet_list;
1672 for (list = inet_mon_list; list; list = list->next)
1673 create_inet_monitor(inet_vbox, (InetMon *)list->data, TRUE);
1674
1675 gkrellm_inet_load_data();
1676
1677 for (list = inet_mon_list; list; list = list->next)
1678 {
1679 in = (InetMon *) list->data;
1680 draw_inet_chart(in);
1681 add_launch_entry(launch_vbox, in);
1682 }
1683 if (inet_mon_list)
1684 gkrellm_spacers_show(mon_inet);
1685 else
1686 gkrellm_spacers_hide(mon_inet);
1687 }
1688
1689 static gboolean
cb_drag_end(GtkWidget * widget,GdkDragContext * context,gpointer data)1690 cb_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
1691 {
1692 reset_entries();
1693 sync_inet_list();
1694 return FALSE;
1695 }
1696
1697 static void
cb_enter(GtkWidget * widget,gpointer data)1698 cb_enter(GtkWidget *widget, gpointer data)
1699 {
1700 GtkTreeModel *model;
1701 GtkTreePath *path = NULL;
1702 GtkTreeIter iter;
1703 InetMon *in;
1704
1705 in = g_new0(InetMon, 1);
1706
1707 in->data0_is_range = GTK_TOGGLE_BUTTON(data0_range_button)->active;
1708 in->data1_is_range = GTK_TOGGLE_BUTTON(data1_range_button)->active;
1709
1710 in->label0 = gkrellm_gtk_entry_get_text(&label0_entry);
1711 if (*(in->label0))
1712 {
1713 in->port0_0 = atoi(gkrellm_gtk_entry_get_text(&port0_0_entry));
1714 in->port0_1 = atoi(gkrellm_gtk_entry_get_text(&port0_1_entry));
1715 }
1716 in->label1 = gkrellm_gtk_entry_get_text(&label1_entry);
1717 if (*(in->label1))
1718 {
1719 in->port1_0 = atoi(gkrellm_gtk_entry_get_text(&port1_0_entry));
1720 in->port1_1 = atoi(gkrellm_gtk_entry_get_text(&port1_1_entry));
1721 }
1722
1723 /* Validate the values
1724 */
1725 if ( (!*(in->label0) && !*(in->label1))
1726 || (*(in->label0) && in->port0_0 == 0 && in->port0_1 == 0)
1727 || (*(in->label1) && in->port1_0 == 0 && in->port1_1 == 0)
1728 )
1729 {
1730 g_free(in);
1731 return;
1732 }
1733
1734 model = gtk_tree_view_get_model(treeview);
1735 if (row_reference)
1736 {
1737 path = gtk_tree_row_reference_get_path(row_reference);
1738 gtk_tree_model_get_iter(model, &iter, path);
1739 }
1740 else
1741 {
1742 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
1743 gtk_list_store_set(GTK_LIST_STORE(model), &iter, INET_COLUMN, NULL,-1);
1744 }
1745 in->config_modified = TRUE;
1746 set_list_store_model_data(GTK_LIST_STORE(model), &iter, in);
1747 g_free(in);
1748 reset_entries();
1749 sync_inet_list();
1750 }
1751
1752 static void
cb_delete(GtkWidget * widget,gpointer data)1753 cb_delete(GtkWidget *widget, gpointer data)
1754 {
1755 GtkTreeModel *model;
1756 GtkTreePath *path;
1757 GtkTreeIter iter;
1758
1759 if (!row_reference)
1760 return;
1761 model = gtk_tree_view_get_model(treeview);
1762 path = gtk_tree_row_reference_get_path(row_reference);
1763 gtk_tree_model_get_iter(model, &iter, path);
1764 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1765
1766 reset_entries();
1767 sync_inet_list();
1768 }
1769
1770 static void
cb_text_format(GtkWidget * widget,gpointer data)1771 cb_text_format(GtkWidget *widget, gpointer data)
1772 {
1773 GList *list;
1774 gchar *s;
1775 GtkWidget *entry;
1776
1777 entry = gtk_bin_get_child(GTK_BIN(text_format_combo_box));
1778 s = gkrellm_gtk_entry_get_text(&entry);
1779 gkrellm_locale_dup_string(&text_format, s, &text_format_locale);
1780 for (list = inet_mon_list; list; list = list->next)
1781 draw_inet_chart((InetMon *) list->data);
1782 }
1783
1784 static void
cb_update_interval(GtkWidget * entry,GtkSpinButton * spin)1785 cb_update_interval(GtkWidget *entry, GtkSpinButton *spin)
1786 {
1787 update_interval = gtk_spin_button_get_value_as_int(spin);
1788 }
1789
1790 static gchar *inet_info_text[] =
1791 {
1792 N_("Inet charts show historical TCP port hits on a minute or hourly\n"
1793 "chart. Below the chart there is a strip where marks are drawn for\n"
1794 "port hits in second intervals. The inet krell has a full scale\n"
1795 "value of 5 hits and samples once per second. The extra info\n"
1796 "display shows current TCP port connections.\n\n"
1797 "For each internet monitor, you can specify two labeled data sets with\n"
1798 "one or two non-zero port numbers entered for each data set. Two\n"
1799 "ports are allowed because some internet ports are related and you\n"
1800 "might want to group them. Check /etc/services for port numbers.\n\n"
1801 "For example, if you created an inet monitor:\n"),
1802
1803 N_("<i>\thttp 80 8080 ftp 21\n"),
1804
1805 N_("Http hits on the standard http port 80 and www web caching service\n"
1806 "on port 8080 are combined and plotted in the one color. Ftp hits\n"
1807 "on the single ftp port 21 are plotted in another color.\n\n"),
1808
1809 N_("If the range button is checked, then all port numbers between Port0 and\n"
1810 "Port1 are monitored and included in the plot.\n\n"),
1811
1812 N_("<h>Chart Labels\n"),
1813 N_("Substitution variables for the format string for chart labels:\n"),
1814 N_("\t$M maximum chart value\n"),
1815 N_("\t$a current active connections for Data0\n"),
1816 N_("\t$cN total connections in last N minutes (or hours) for Data0\n"),
1817 N_("\t$l label for Data0\n"),
1818 N_("\t$A current active connections for Data1\n"),
1819 N_("\t$CN total connections in last N minutes (or hours) for Data1\n"),
1820 N_("\t$L label for Data1\n"),
1821
1822 "\n",
1823 N_("<h>Mouse Button Actions:\n"),
1824 N_("<b>\tLeft "),
1825 N_("click on an inet chart to toggle the extra info display of\n"
1826 "\t\tcurrent TCP port connections.\n"),
1827 N_("<b>\tMiddle "),
1828 N_("click on an inet chart to toggle hour/minute charts.\n")
1829 };
1830
1831
1832 static void
create_inet_tab(GtkWidget * tab_vbox)1833 create_inet_tab(GtkWidget *tab_vbox)
1834 {
1835 GtkWidget *tabs;
1836 GtkWidget *table;
1837 GtkWidget *hbox, *vbox, *vbox1;
1838 GtkWidget *separator;
1839 GtkWidget *scrolled;
1840 GtkWidget *text;
1841 GtkWidget *label;
1842 GtkWidget *button;
1843 GtkTreeModel *model;
1844 GtkCellRenderer *renderer;
1845 GList *list;
1846 InetMon *in;
1847 gint i;
1848
1849 row_reference = NULL;
1850
1851 tabs = gtk_notebook_new();
1852 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1853 gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
1854
1855 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Ports"));
1856
1857 table = gtk_table_new(6, 7, FALSE /*homogeneous*/);
1858 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1859 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 3);
1860
1861 label = gtk_label_new(_("Data0"));
1862 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 3, 0, 1);
1863 separator = gtk_hseparator_new();
1864 gtk_table_attach_defaults(GTK_TABLE(table), separator, 0, 3, 1, 2);
1865 label = gtk_label_new(_("Data1"));
1866 gtk_table_attach_defaults(GTK_TABLE(table), label, 4, 7, 0, 1);
1867 separator = gtk_hseparator_new();
1868 gtk_table_attach_defaults(GTK_TABLE(table), separator, 4, 7, 1, 2);
1869
1870 separator = gtk_vseparator_new();
1871 gtk_table_attach_defaults(GTK_TABLE(table), separator, 3, 4, 0, 6);
1872
1873 label = gtk_label_new(_("Label"));
1874 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1875 label = gtk_label_new(_("Port0"));
1876 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, 2, 3);
1877 label = gtk_label_new(_("Port1"));
1878 gtk_table_attach_defaults(GTK_TABLE(table), label, 2, 3, 2, 3);
1879 label = gtk_label_new(_("Label"));
1880 gtk_table_attach_defaults(GTK_TABLE(table), label, 4, 5, 2, 3);
1881 label = gtk_label_new(_("Port0"));
1882 gtk_table_attach_defaults(GTK_TABLE(table), label, 5, 6, 2, 3);
1883 label = gtk_label_new(_("Port1"));
1884 gtk_table_attach_defaults(GTK_TABLE(table), label, 6, 7, 2, 3);
1885
1886 label0_entry = gtk_entry_new();
1887 gtk_entry_set_max_length(GTK_ENTRY(label0_entry), 8);
1888 gtk_widget_set_size_request(label0_entry, 32, -1);
1889 gtk_table_attach_defaults(GTK_TABLE(table), label0_entry, 0, 1, 3, 4);
1890 port0_0_entry = gtk_entry_new();
1891 gtk_entry_set_max_length(GTK_ENTRY(port0_0_entry), 8);
1892 gtk_widget_set_size_request(port0_0_entry, 32, -1);
1893 gtk_table_attach_defaults(GTK_TABLE(table), port0_0_entry, 1, 2, 3, 4);
1894 port0_1_entry = gtk_entry_new();
1895 gtk_entry_set_max_length(GTK_ENTRY(port0_1_entry), 8);
1896 gtk_widget_set_size_request(port0_1_entry, 32, -1);
1897 gtk_table_attach_defaults(GTK_TABLE(table), port0_1_entry, 2, 3, 3, 4);
1898
1899 label1_entry = gtk_entry_new();
1900 gtk_entry_set_max_length(GTK_ENTRY(label1_entry), 8);
1901 gtk_widget_set_size_request(label1_entry, 32, -1);
1902 gtk_table_attach_defaults(GTK_TABLE(table), label1_entry, 4, 5, 3, 4);
1903 port1_0_entry = gtk_entry_new();
1904 gtk_entry_set_max_length(GTK_ENTRY(port1_0_entry), 8);
1905 gtk_widget_set_size_request(port1_0_entry, 32, -1);
1906 gtk_table_attach_defaults(GTK_TABLE(table), port1_0_entry, 5, 6, 3, 4);
1907 port1_1_entry = gtk_entry_new();
1908 gtk_entry_set_max_length(GTK_ENTRY(port1_1_entry), 8);
1909 gtk_widget_set_size_request(port1_1_entry, 32, -1);
1910 gtk_table_attach_defaults(GTK_TABLE(table), port1_1_entry, 6, 7, 3, 4);
1911
1912 hbox = gtk_hbox_new(FALSE, 2);
1913 gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 3, 4, 5);
1914 gkrellm_gtk_check_button(hbox, &data0_range_button, 0, TRUE, 0,
1915 _("Port0 - Port1 is a range"));
1916
1917 hbox = gtk_hbox_new(FALSE, 2);
1918 gtk_table_attach_defaults(GTK_TABLE(table), hbox, 4, 7, 4, 5);
1919 gkrellm_gtk_check_button(hbox, &data1_range_button, 0, TRUE, 0,
1920 _("Port0 - Port1 is a range"));
1921
1922 separator = gtk_hseparator_new();
1923 gtk_table_attach_defaults(GTK_TABLE(table), separator, 0, 7, 5, 6);
1924
1925 hbox = gtk_hbutton_box_new();
1926 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
1927 gtk_box_set_spacing(GTK_BOX(hbox), 5);
1928 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1929
1930 button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
1931 g_signal_connect(G_OBJECT(button), "clicked",
1932 G_CALLBACK(cb_delete), NULL);
1933 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1934
1935 /* everybody knows about CNTL click, right? */
1936 // button = gtk_button_new_from_stock(GTK_STOCK_NEW);
1937 // g_signal_connect(G_OBJECT(button), "clicked",
1938 // G_CALLBACK(reset_entries), NULL);
1939 // gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1940
1941 button = gtk_button_new_from_stock(GTK_STOCK_ADD);
1942 g_signal_connect(G_OBJECT(button), "clicked",
1943 G_CALLBACK(cb_enter), NULL);
1944 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1945
1946 separator = gtk_hseparator_new();
1947 gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 2);
1948
1949 scrolled = gtk_scrolled_window_new(NULL, NULL);
1950 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1951 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1952 gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
1953
1954
1955 model = create_model();
1956 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
1957 g_object_unref(G_OBJECT(model));
1958 gtk_tree_view_set_rules_hint(treeview, TRUE);
1959 gtk_tree_view_set_reorderable(treeview, TRUE);
1960 g_signal_connect(G_OBJECT(treeview), "drag_end",
1961 G_CALLBACK(cb_drag_end), NULL);
1962
1963 renderer = gtk_cell_renderer_text_new();
1964 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Label"),
1965 renderer,
1966 "text", LABEL0_COLUMN, NULL);
1967 renderer = gtk_cell_renderer_text_new();
1968 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1969 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Port0"),
1970 renderer,
1971 "text", PORT00_COLUMN, NULL);
1972 renderer = gtk_cell_renderer_text_new();
1973 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1974 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Port1"),
1975 renderer,
1976 "text", PORT01_COLUMN, NULL);
1977
1978 renderer = gtk_cell_renderer_text_new();
1979 gtk_tree_view_insert_column_with_attributes(treeview, -1, " ",
1980 renderer,
1981 "text", SPACER_COLUMN, NULL);
1982
1983 renderer = gtk_cell_renderer_text_new();
1984 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Label"),
1985 renderer,
1986 "text", LABEL1_COLUMN, NULL);
1987 renderer = gtk_cell_renderer_text_new();
1988 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1989 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Port0"),
1990 renderer,
1991 "text", PORT10_COLUMN, NULL);
1992 renderer = gtk_cell_renderer_text_new();
1993 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1994 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Port1"),
1995 renderer,
1996 "text", PORT11_COLUMN, NULL);
1997
1998 renderer = gtk_cell_renderer_text_new();
1999 gtk_tree_view_insert_column_with_attributes(treeview, -1, " ",
2000 renderer,
2001 "text", DUMMY_COLUMN, NULL);
2002
2003
2004 gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
2005 selection = gtk_tree_view_get_selection(treeview);
2006 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
2007 g_signal_connect(G_OBJECT(selection), "changed",
2008 G_CALLBACK(cb_tree_selection_changed), NULL);
2009
2010 /* --Setup tab */
2011 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Setup"));
2012
2013 if (!_GK.client_mode)
2014 gkrellm_gtk_spin_button(vbox, NULL,
2015 (gfloat) update_interval, 1, 20, 1, 1, 0, 55,
2016 cb_update_interval, NULL, FALSE,
2017 _("Seconds between updates"));
2018
2019 label = gtk_label_new(""); /* padding */
2020 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
2021
2022 vbox1 = gkrellm_gtk_category_vbox(vbox,
2023 _("Format String for Chart Labels"),
2024 4, 0, TRUE);
2025
2026 text_format_combo_box = gtk_combo_box_entry_new_text();
2027 gtk_box_pack_start(GTK_BOX(vbox1), text_format_combo_box, FALSE, FALSE, 2);
2028 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
2029 text_format);
2030 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
2031 DEFAULT_TEXT_FORMAT);
2032 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
2033 "\\r\\f $M\\t$a\\f $l\\N$A\\f $L");
2034 gtk_combo_box_append_text(GTK_COMBO_BOX(text_format_combo_box),
2035 "\\r\\f $M\\D1$a\\f $l\\D2$A\\f $L");
2036 gtk_combo_box_set_active(GTK_COMBO_BOX(text_format_combo_box), 0);
2037 g_signal_connect(G_OBJECT(GTK_COMBO_BOX(text_format_combo_box)), "changed",
2038 G_CALLBACK(cb_text_format), NULL);
2039
2040 vbox1 = gkrellm_gtk_category_vbox(vbox,
2041 _("Launch Commands"),
2042 4, 0, TRUE);
2043 launch_vbox = gkrellm_gtk_scrolled_vbox(vbox1, NULL,
2044 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2045 gtk_widget_show(launch_vbox);
2046 gtk_widget_realize(launch_vbox);
2047 for (i = 0, list = inet_mon_list; list; list = list->next, ++i)
2048 {
2049 in = (InetMon *) list->data;
2050 add_launch_entry(launch_vbox, in);
2051 }
2052
2053 /* --Info tab */
2054 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
2055 text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
2056 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2057 for (i = 0; i < sizeof(inet_info_text)/sizeof(gchar *); ++i)
2058 gkrellm_gtk_text_view_append(text, _(inet_info_text[i]));
2059
2060 reset_entries();
2061 }
2062
2063
2064
2065 static GkrellmMonitor monitor_inet =
2066 {
2067 N_("Internet"), /* Name, for config tab. */
2068 MON_INET, /* Id, 0 if a plugin */
2069 create_inet, /* The create function */
2070 update_inet, /* The update function */
2071 create_inet_tab, /* The config tab create function */
2072 NULL, /* Instant apply */
2073
2074 save_inet_config, /* Save user conifg */
2075 load_inet_config, /* Load user config */
2076 "inet", /* config keyword */
2077
2078 NULL, /* Undef 2 */
2079 NULL, /* Undef 1 */
2080 NULL, /* Undef 0 */
2081
2082 0, /* insert_before_id - place plugin before this mon */
2083
2084 NULL, /* Handle if a plugin, filled in by GKrellM */
2085 NULL /* path if a plugin, filled in by GKrellM */
2086 };
2087
2088 GkrellmMonitor *
gkrellm_init_inet_monitor(void)2089 gkrellm_init_inet_monitor(void)
2090 {
2091 monitor_inet.name = _(monitor_inet.name);
2092 style_id = gkrellm_add_chart_style(&monitor_inet, INET_STYLE_NAME);
2093 gkrellm_locale_dup_string(&text_format, DEFAULT_TEXT_FORMAT,
2094 &text_format_locale);
2095 mon_inet = &monitor_inet;
2096 if (setup_inet_interface())
2097 { /* Make the "data-suffix/inet" directory */
2098 inet_data_dir = gkrellm_make_data_file_name("inet", NULL);
2099 return &monitor_inet;
2100 }
2101 return NULL;
2102 }
2103