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 | solaris.c code is Copyright (C) Daisuke Yabuki <dxy@acm.org>
8 |
9 |
10 | GKrellM is free software: you can redistribute it and/or modify it
11 | under the terms of the GNU General Public License as published by
12 | the Free Software Foundation, either version 3 of the License, or
13 | (at your option) any later version.
14 |
15 | GKrellM is distributed in the hope that it will be useful, but WITHOUT
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 | License for more details.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with this program. If not, see http://www.gnu.org/licenses/
22 |
23 |
24 | Additional permission under GNU GPL version 3 section 7
25 |
26 | If you modify this program, or any covered work, by linking or
27 | combining it with the OpenSSL project's OpenSSL library (or a
28 | modified version of that library), containing parts covered by
29 | the terms of the OpenSSL or SSLeay licenses, you are granted
30 | additional permission to convey the resulting work.
31 | Corresponding Source for a non-source form of such a combination
32 | shall include the source code for the parts of OpenSSL used as well
33 | as that of the covered work.
34 */
35
36 #include <kstat.h>
37 #include <kvm.h>
38 #include <fcntl.h>
39
40 kstat_ctl_t *kc;
41 kvm_t *kd = NULL;
42
43 struct nlist nl[] = {
44 { "mpid" },
45 { 0 }
46 };
47
48 extern void solaris_list_harddisks(void);
49
50
51 void
gkrellm_sys_main_init(void)52 gkrellm_sys_main_init(void)
53 {
54 /*
55 * Most of stats (cpu, proc, disk, memory, net and uptime) are
56 * unavailable if kstat_open() failed. So we just exit in that case.
57 */
58 if ((kc = kstat_open()) == NULL) {
59 perror("kstat_open");
60 exit(1);
61 }
62
63 /*
64 * kvm is utilized solely for getting a value for proc.n_forks
65 * from kernel variable called mpid. Even if kvm_open() fails,
66 * we proceed without it.
67 */
68 if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) != NULL) {
69 kvm_nlist(kd, nl);
70 }
71
72 /*
73 * a function called by the following requires sys gid privilege.
74 * the following function should be performed here just for that reason.
75 */
76 solaris_list_harddisks();
77
78 if (setgid(getgid()) != 0) {
79 perror("Failed to drop setgid privilege");
80 exit(1);
81 }
82 }
83
84 void
gkrellm_sys_main_cleanup(void)85 gkrellm_sys_main_cleanup(void)
86 {
87 }
88
89
90 /* ===================================================================== */
91 /* CPU monitor interface */
92
93 #include <kstat.h>
94 #include <sys/sysinfo.h>
95
96 void
gkrellm_sys_cpu_read_data(void)97 gkrellm_sys_cpu_read_data(void)
98 {
99 extern kstat_ctl_t *kc;
100 kstat_t *ksp;
101 cpu_stat_t cs;
102
103 if (kstat_chain_update(kc) == -1) {
104 perror("kstat_chain_update");
105 return;
106 }
107
108 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
109 if (strcmp(ksp->ks_module, "cpu_stat"))
110 continue;
111 if (kstat_read(kc, ksp, &cs) == -1) {
112 perror("kstat_read");
113 continue;
114 }
115 gkrellm_cpu_assign_data(ksp->ks_instance,
116 cs.cpu_sysinfo.cpu[CPU_USER],
117 cs.cpu_sysinfo.cpu[CPU_WAIT],
118 cs.cpu_sysinfo.cpu[CPU_KERNEL],
119 cs.cpu_sysinfo.cpu[CPU_IDLE]);
120
121 }
122 }
123
124 /*
125 * note: on some SPARC systems, you can monitor temperature of CPUs
126 * with kstat (unix::temperature:[min/max/state/trend...])
127 */
128
129 gboolean
gkrellm_sys_cpu_init()130 gkrellm_sys_cpu_init() {
131 extern kstat_ctl_t *kc;
132 kstat_t *ksp;
133 gint n_cpus = 0;
134
135 if(kstat_chain_update(kc) == -1) {
136 perror("kstat_chain_update");
137 return FALSE;
138 }
139
140 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
141 if (strcmp(ksp->ks_module, "cpu_stat"))
142 continue;
143 if (kstat_read(kc, ksp, NULL) != -1) {
144 gkrellm_cpu_add_instance(ksp->ks_instance);
145 ++n_cpus;
146 }
147 }
148 gkrellm_cpu_set_number_of_cpus(n_cpus);
149 return TRUE;
150 }
151
152
153 /* ===================================================================== */
154 /* Proc monitor interface */
155
156 #include <utmp.h>
157 #include <sys/types.h>
158 #include <dirent.h>
159 #include <sys/loadavg.h>
160 #include <kstat.h>
161 #include <fcntl.h>
162 #include <kvm.h>
163 #include <sys/sysinfo.h>
164
165 void
gkrellm_sys_proc_read_data(void)166 gkrellm_sys_proc_read_data(void)
167 {
168
169 double avenrun[LOADAVG_NSTATS], fload = 0;
170 guint n_processes = 0, n_forks = 0;
171 int last_pid;
172 extern kstat_ctl_t *kc;
173 kstat_t *ksp;
174 kstat_named_t *knp;
175
176 extern kvm_t *kd;
177 extern struct nlist nl[];
178
179 if (!GK.second_tick) /* Only one read per second */
180 return;
181
182 if (getloadavg(avenrun, LOADAVG_NSTATS) > 0)
183 fload = avenrun[LOADAVG_1MIN];
184
185 if (kstat_chain_update(kc) == -1) {
186 perror("kstat_chain_update");
187 return;
188 }
189 ksp = kstat_lookup(kc, "unix", -1, "system_misc");
190 if (ksp && kstat_read(kc, ksp, NULL) >= 0) {
191 knp = (kstat_named_t *)kstat_data_lookup(ksp, "nproc");
192 if (knp) {
193 n_processes = knp->value.ui32;
194 }
195 }
196
197 if (kd) {
198 if (kvm_kread(kd, nl[0].n_value, (char *)&last_pid, sizeof(int)) != -1)
199 n_forks = last_pid;
200 } else {
201 n_forks = 0;
202 }
203 /* NOTE: code to get 'n_running' is not implemented (stays untouched).
204 * but it wouldn't do any harm since nobody seems to refer to it.
205 */
206 gkrellm_proc_assign_data(n_processes, 0, n_forks, fload);
207 }
208
209
210 void
gkrellm_sys_proc_read_users(void)211 gkrellm_sys_proc_read_users(void)
212 {
213 static struct utmp *utmpp;
214 gint n_users;
215
216 n_users = 0;
217 setutent();
218 while ((utmpp = getutent()) != NULL) {
219 if (utmpp->ut_type == USER_PROCESS && utmpp->ut_name[0] != '\0')
220 n_users++;
221 }
222 gkrellm_proc_assign_users(n_users);
223 }
224
225 gboolean
gkrellm_sys_proc_init(void)226 gkrellm_sys_proc_init(void)
227 {
228 return TRUE;
229 }
230
231
232
233 /* ===================================================================== */
234 /* Disk monitor interface */
235
236 #include <sys/types.h>
237 #include <sys/sysinfo.h>
238 #include <unistd.h>
239 #include <kstat.h>
240 #include <libdevinfo.h>
241 #include <errno.h>
242 #include <sys/dkio.h>
243
244 #define UNIT_SHIFT 3
245
246 #define NAME2MAJOR 0
247 #define MAJOR2NAME 1
248
249 typedef struct {
250 gint major;
251 gchar name[32];
252 } name_to_major_t;
253
254 static gint check_media_type(kstat_t *);
255 static gint isharddisk(kstat_t *);
256 void solaris_list_harddisks(void); /* called from main.c */
257
258 static gint lookup_name_to_major(name_to_major_t *, int);
259 static gint get_major(gchar *);
260 static gint get_devname(gint, gchar *);
261 static gint get_minor(gint);
262 static gint get_instance(gint);
263
264 typedef struct {
265 char name[8];
266 } probed_harddisk;
267
268 GList *hard_disk_list;
269
270
271 gchar *
gkrellm_sys_disk_name_from_device(gint device_number,gint unit_number,gint * order)272 gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number,
273 gint *order)
274 {
275 return NULL; /* Disk data by device not implemented in Solaris */
276 }
277
278 gint
gkrellm_sys_disk_order_from_name(const gchar * name)279 gkrellm_sys_disk_order_from_name(const gchar *name)
280 {
281 return -1; /* Append as added */
282 }
283
284 void
gkrellm_sys_disk_read_data(void)285 gkrellm_sys_disk_read_data(void)
286 {
287 probed_harddisk *drive;
288 GList *list;
289
290 extern kstat_ctl_t *kc;
291 kstat_t *ksp;
292 kstat_io_t kios;
293
294 if (kstat_chain_update(kc) == -1) {
295 perror("kstat_chain_update");
296 return;
297 }
298 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
299 for (list = hard_disk_list; list; list = list->next) {
300 drive = (probed_harddisk *)list->data;
301
302 if(strcmp(drive->name, ksp->ks_name))
303 continue;
304
305 memset((void *)&kios, 0, sizeof(kstat_io_t));
306 kstat_read(kc, ksp, &kios);
307
308 gkrellm_disk_assign_data_by_name(drive->name,
309 kios.nread, kios.nwritten, FALSE);
310 }
311 }
312 }
313
314 gboolean
gkrellm_sys_disk_init(void)315 gkrellm_sys_disk_init(void)
316 {
317 return TRUE;
318 }
319
320
321 /* Is this needed any longer? */
322 static gint
lookup_name_to_major(name_to_major_t * name_to_major,gint type)323 lookup_name_to_major(name_to_major_t *name_to_major, gint type) {
324 FILE *fp;
325 char line[80];
326 char *name, *maj;
327 gint name2major, major2name;
328 gint majnum;
329
330 name2major = major2name = 0;
331 switch (type) {
332 case NAME2MAJOR:
333 name2major = 1;
334 break;
335 case MAJOR2NAME:
336 major2name = 1;
337 break;
338 default:
339 break;
340 }
341
342 if ((fp = fopen("/etc/name_to_major", "r")) == NULL) {
343 perror("fopen");
344 return -1;
345 }
346
347 while (fgets(line, sizeof(line), fp) != NULL) {
348 name = strtok(line, " \t");
349 if (name == NULL)
350 continue;
351
352 maj = strtok(NULL, "\n");
353 if (maj == NULL)
354 continue;
355 majnum = (gint) atol(maj);
356
357 if (name2major) {
358 if (strcmp(name_to_major->name, name) == 0) {
359 name_to_major->major = majnum;
360 fclose(fp);
361 return 0;
362 }
363 } else if (major2name) {
364 if (name_to_major->major == majnum) {
365 strcpy(name_to_major->name, name);
366 fclose(fp);
367 return 0;
368 }
369 }
370 }
371 fclose(fp);
372 return -1;
373 }
374
375 #if 0
376 /* Is this needed any longer? */
377 static gint
378 get_major(gchar *devname) {
379 /* xlation from device name to major (e.g. sd -> 32) */
380 name_to_major_t name_to_major;
381
382 strcpy(name_to_major.name, devname);
383 if (lookup_name_to_major(&name_to_major, NAME2MAJOR) < 0)
384 return -1;
385 return name_to_major.major;
386 }
387
388 /* Is this needed any longer? */
389 static gint
390 get_devname(gint major, gchar *devname) {
391 /* xlation from major to device name (e.g. 118 -> ssd) */
392 name_to_major_t name_to_major;
393
394 name_to_major.major = major;
395 if (lookup_name_to_major(&name_to_major, MAJOR2NAME) < 0)
396 return -1;
397 strcpy(devname, name_to_major.name);
398 return 0;
399 }
400
401 /* Is this needed any longer? */
402 static gint
403 get_minor(gint instance) {
404 return instance << UNIT_SHIFT;
405 }
406
407 /* Is this needed any longer? */
408 static gint
409 get_instance(gint minor) {
410 return minor >> UNIT_SHIFT;
411 }
412 #endif
413
414 /*
415 * An sd instance could be a cdrom or a harddrive. You can't simply tell,
416 * from contents of kstat, which type of device an sd device is
417 * (well, maybe you could, but at least i can't.)
418 * It, however, doesn't make much sense to count cdrom read/write as
419 * "Disk" activity. So I'd like to exclude removable media's from
420 * monitoring target. In order to do this, I try to open a physical
421 * device of a corresponding sd instance. If it's succeeded, I assume
422 * it's a hard drive. If I get ENXIO or EBUSY, I'll guess it's CDROM.
423 * If you come up with a better (simpler or safer) way to tell it's
424 * a removable media or a hard drive, please drop me an e-mail at
425 * Daisuke Yabuki <dxy@acm.org>.
426 * I don't know any other driver which handle both hard drive and
427 * removable media, by the way. I hope it wouldn't do any harm on
428 * other type of devices, i.e. ssd, or IDE drivers.
429 */
430 static gint
check_media_type(kstat_t * ksp)431 check_media_type(kstat_t *ksp) {
432 gint fd;
433 char *phys_path, devices_path[256]; /* or OBP_MAXPATHLEN? */
434 di_node_t node;
435 static di_node_t root_node = NULL;
436 #if 0
437 /* Not supported on Solaris 7 */
438 struct dk_minfo dk;
439 #else
440 int dkRemovable;
441 #endif
442
443 if (root_node == NULL) {
444 if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
445 perror("di_init");
446 return -1;
447 }
448 }
449
450 node = di_drv_first_node(ksp->ks_module, root_node);
451 while (node != DI_NODE_NIL) {
452 if (di_instance(node) != ksp->ks_instance) {
453 node = di_drv_next_node(node);
454 continue;
455 }
456 if ((phys_path = di_devfs_path(node)) == NULL) {
457 perror("di_devfs_path");
458 return -1;
459 }
460 if (sprintf(devices_path, "/devices%s:c,raw", phys_path) <= 0) {
461 di_devfs_path_free(phys_path);
462 return -1;
463 }
464 if ((fd = open(devices_path, O_RDONLY)) == -1) {
465 if (errno == ENXIO || errno == EBUSY) {
466 close(fd);
467 di_devfs_path_free(phys_path);
468 return 0; /* guess it's removable media */
469 } else {
470 #ifdef DEBUG
471 g_message("opening %s\n", devices_path);
472 g_message("unexpected errno: %d\n", errno);
473 g_message("disabled auto-detection/exclusion of removable media\n");
474 #endif
475 close(fd);
476 di_devfs_path_free(phys_path);
477 return -1; /* EACCESS (unless setgid sys) or suchlike */
478 }
479 }
480 #if 0
481 /* Not supported on Solaris 7 */
482 if (ioctl(fd, DKIOCGMEDIAINFO, &dk) < 0)
483 #else
484 if (ioctl(fd, DKIOCREMOVABLE, &dkRemovable) < 0)
485 #endif
486 {
487 close(fd);
488 di_devfs_path_free(phys_path);
489 return -1;
490 }
491 #if 0
492 if (dk.dki_media_type == DK_FIXED_DISK)
493 #else
494 if (!dkRemovable)
495 #endif
496 {
497 close(fd);
498 di_devfs_path_free(phys_path);
499 return 1;
500 }
501 return 0;
502 }
503 return -1; /* shouldn't be reached */
504 }
505
506 static gint
isharddisk(kstat_t * ksp)507 isharddisk(kstat_t *ksp) {
508 if (ksp->ks_type != KSTAT_TYPE_IO)
509 return 0;
510 if (strncmp(ksp->ks_class, "disk", 4))
511 return 0; /* excluding nfs etc. */
512 if (!strcmp(ksp->ks_module, "fd"))
513 return 0; /* excluding fd */
514 if (check_media_type(ksp) == 0)
515 return 0; /* guess it's removable media (e.g. CD-ROM, CD-R/W etc) */
516 return 1;
517 }
518
519 /*
520 * creating a preliminary list of drives, which should be a complete
521 * list of drives available on the system. the list is not supposed to
522 * contain nfs, fd, cdrom, cdrw etc.
523 */
524 void
solaris_list_harddisks(void)525 solaris_list_harddisks(void) {
526 extern kstat_ctl_t *kc;
527 kstat_t *ksp;
528 probed_harddisk *drive;
529
530 if (kstat_chain_update(kc) == -1) {
531 perror("kstat_chain_update");
532 return;
533 }
534
535 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
536 if(isharddisk(ksp)) {
537 drive = g_new0(probed_harddisk, 1);
538 hard_disk_list = g_list_append(hard_disk_list, drive);
539 strcpy(drive->name, ksp->ks_name);
540 }
541 }
542 }
543
544
545 /* ===================================================================== */
546 /* Inet monitor interface */
547
548 #include "../inet.h"
549
550 #include <stropts.h>
551 #include <inet/mib2.h>
552 #include <fcntl.h>
553 #include <sys/tihdr.h>
554
555 void
gkrellm_sys_inet_read_tcp_data()556 gkrellm_sys_inet_read_tcp_data() {
557
558 ActiveTCP tcp;
559 gint tcp_status;
560
561 static int tcpfd = 0;
562
563 mib2_tcpConnEntry_t *tp;
564 #if defined(INET6)
565 mib2_tcp6ConnEntry_t *tp6;
566 #endif
567
568 char buf[512];
569 int i, flags, getcode, num_ent;
570 struct strbuf ctlbuf, databuf;
571 struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
572 struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
573 struct T_error_ack *tea = (struct T_error_ack *)buf;
574 struct opthdr *mibhdr;
575
576 if (tcpfd == 0) {
577 if ((tcpfd = open("/dev/tcp", O_RDWR)) == -1) {
578 perror("open");
579 }
580 }
581
582 tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
583 tor->OPT_offset = sizeof (struct T_optmgmt_req);
584 tor->OPT_length = sizeof (struct opthdr);
585 tor->MGMT_flags = T_CURRENT;
586 mibhdr = (struct opthdr *)&tor[1];
587 mibhdr->level = MIB2_TCP;
588 mibhdr->name = 0;
589 mibhdr->len = 0;
590
591 ctlbuf.buf = buf;
592 ctlbuf.len = tor->OPT_offset + tor->OPT_length;
593 flags = 0; /* request to be sent in non-priority */
594
595 if (putmsg(tcpfd, &ctlbuf, (struct strbuf *)0, flags) == -1) {
596 perror("putmsg");
597 }
598
599 mibhdr = (struct opthdr *)&toa[1];
600 ctlbuf.maxlen = sizeof (buf);
601
602 /* now receiving response from stream */
603
604 for (;;) {
605 flags = 0; /* read any messages available */
606 getcode = getmsg(tcpfd, &ctlbuf, (struct strbuf *)0, &flags);
607
608 if (getcode != MOREDATA ||
609 ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
610 toa->PRIM_type != T_OPTMGMT_ACK ||
611 toa->MGMT_flags != T_SUCCESS) {
612 break;
613 }
614
615 if (ctlbuf.len >= sizeof (struct T_error_ack) &&
616 tea->PRIM_type == T_ERROR_ACK) {
617 perror("ERROR_ACK");
618 return;
619 }
620
621 if (getcode == 0 &&
622 ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
623 toa->PRIM_type == T_OPTMGMT_ACK &&
624 toa->MGMT_flags == T_SUCCESS) {
625 return;
626 }
627
628 /* prepare for receiving data */
629 databuf.maxlen = mibhdr->len;
630 databuf.len = 0;
631 databuf.buf = (char *)malloc((int)mibhdr->len);
632 if(!databuf.buf) {
633 perror("malloc");
634 break;
635 }
636 flags = 0;
637
638 getcode = getmsg(tcpfd, (struct strbuf *)0, &databuf, &flags);
639
640 if (mibhdr->level == MIB2_TCP && mibhdr->name == MIB2_TCP_13) {
641 tp = (mib2_tcpConnEntry_t *)databuf.buf;
642 num_ent = mibhdr->len / sizeof(mib2_tcpConnEntry_t);
643 for (i = 0; i < num_ent; i++, tp++) {
644 if (tp->tcpConnState != MIB2_TCP_established)
645 continue;
646 tcp.local_port = tp->tcpConnLocalPort;
647 tcp.remote_addr.s_addr = tp->tcpConnRemAddress;
648 tcp.remote_port = tp->tcpConnRemPort;
649 tcp.family = AF_INET;
650 tcp_status = (tp->tcpConnState == MIB2_TCP_established);
651 if (tcp_status == TCP_ALIVE)
652 gkrellm_inet_log_tcp_port_data(&tcp);
653 }
654 }
655
656 #if defined(INET6)
657 if (mibhdr->level == MIB2_TCP6 && mibhdr->name == MIB2_TCP6_CONN) {
658 tp6 = (mib2_tcp6ConnEntry_t *)databuf.buf;
659 num_ent = mibhdr->len / sizeof(mib2_tcp6ConnEntry_t);
660 for (i = 0; i < num_ent; i++, tp6++) {
661 if (tp6->tcp6ConnState != MIB2_TCP_established)
662 continue;
663 tcp.local_port = tp6->tcp6ConnLocalPort;
664 tcp.remote_port = tp6->tcp6ConnRemPort;
665 memcpy(&tcp.remote_addr6, &tp6->tcp6ConnRemAddress,
666 sizeof(struct in6_addr));
667 tcp.family = AF_INET6;
668 tcp_status = (tp6->tcp6ConnState == MIB2_TCP_established);
669 if (tcp_status == TCP_ALIVE)
670 gkrellm_inet_log_tcp_port_data(&tcp);
671 }
672 }
673 #endif /* INET6 */
674
675 free(databuf.buf);
676 }
677
678 }
679
680 gboolean
gkrellm_sys_inet_init(void)681 gkrellm_sys_inet_init(void)
682 {
683 return TRUE;
684 }
685
686
687 /* ===================================================================== */
688 /* Net monitor interface */
689
690 #include <kstat.h>
691 #include <net/if.h>
692 #include <sys/sockio.h>
693
694 /*
695 * FIXME: I haven't tested Net timer (and never will), but I believe it's
696 * not going to work. Name of the lock file is different from one on Linux.
697 * If you need this functionality, feel free to modify my code.
698 */
699
700 void
gkrellm_sys_net_read_data(void)701 gkrellm_sys_net_read_data(void)
702 {
703 gulong rx, tx;
704 extern kstat_ctl_t *kc;
705 kstat_t *ksp;
706 kstat_named_t *knp;
707
708 if (kstat_chain_update(kc) == -1) {
709 perror("kstat_chain_update");
710 return;
711 }
712
713 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
714 if (!strcmp(ksp->ks_class, "net")) {
715 kstat_read(kc, ksp, NULL);
716
717 knp = kstat_data_lookup(ksp, "rbytes");
718 if (knp == NULL)
719 continue;
720 rx = knp->value.ui32;
721
722 knp = kstat_data_lookup(ksp, "obytes");
723 if (knp == NULL)
724 continue;
725 tx = knp->value.ui32;
726
727 gkrellm_net_assign_data(ksp->ks_name, rx, tx);
728 }
729 }
730
731 }
732
733 #if 0
734 /* New way is for above gkrellm_sys_net_read_data() to just assign data
735 | for all net interfaces.
736 */
737 void
738 gkrellm_sys_net_sync(void)
739 {
740 GList *list;
741 int numifs, numifreqs;
742 int i, sockfd;
743 size_t bufsize;
744 gchar *buf;
745 struct ifreq ifr, *ifrp;
746 struct ifconf ifc;
747
748 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
749 return;
750
751 if (ioctl(sockfd, SIOCGIFNUM, (char *)&numifs) < 0) {
752 perror("SIOCGIFNUM");
753 close(sockfd);
754 return;
755 }
756
757 bufsize = ((size_t)numifs) * sizeof(struct ifreq);
758 buf = (char *)malloc(bufsize);
759 if (!buf) {
760 perror("malloc");
761 close(sockfd);
762 return;
763 }
764
765 ifc.ifc_len = bufsize;
766 ifc.ifc_buf = buf;
767
768 if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0) {
769 perror("SIOCGIFCONF");
770 free(buf);
771 close(sockfd);
772 return;
773 }
774
775 #ifdef DEBUG
776 g_message("interfaces probed: ");
777 for (i=0; i < numifs; i++) {
778 g_message("%s ", ifc.ifc_req[i].ifr_name);
779 }
780 g_message("\n");
781 #endif
782
783 ifrp = ifc.ifc_req;
784 numifreqs = ifc.ifc_len / sizeof(struct ifreq);
785
786 for (i = 0; i < numifreqs; i++, ifrp++)
787 {
788 memset((char *)&ifr, 0, sizeof(ifr));
789 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
790 if (!strncmp(ifr.ifr_name, "lo", 2))
791 continue;
792 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)
793 {
794 perror("SIOCGIFFLAGS");
795 continue;
796 }
797 if (ifr.ifr_flags & IFF_UP)
798 gkrellm_net_interface_is_up(ifr.ifr_name);
799 }
800 free(buf);
801 close(sockfd);
802 }
803 #endif
804
805 gboolean
gkrellm_sys_net_isdn_online(void)806 gkrellm_sys_net_isdn_online(void)
807 {
808 return FALSE;
809 }
810
811 void
gkrellm_sys_net_check_routes(void)812 gkrellm_sys_net_check_routes(void)
813 {
814 }
815
816 gboolean
gkrellm_sys_net_init(void)817 gkrellm_sys_net_init(void)
818 {
819 gkrellm_net_set_lock_directory("/var/spool/locks");
820 gkrellm_net_add_timer_type_ppp("ipdptp0");
821 gkrellm_net_add_timer_type_ppp("ppp0");
822 return TRUE;
823 }
824
825
826
827 /* ===================================================================== */
828 /* Memory/Swap monitor interface */
829
830 #include <unistd.h>
831 #include <kstat.h>
832 #include <sys/stat.h>
833 #include <sys/swap.h>
834
835 static guint64 swap_total, swap_used;
836
837 void
gkrellm_sys_mem_read_data()838 gkrellm_sys_mem_read_data() {
839
840 gulong pagesize;
841 guint64 total, used = 0, free = 0;
842 static gulong pageshift = 0, physpages = 0;
843 extern kstat_ctl_t *kc;
844 kstat_t *ksp;
845 kstat_named_t *knp;
846
847 struct anoninfo ai;
848
849 if (!GK.second_tick)
850 return;
851
852 if (pageshift == 0) {
853 for (pagesize = sysconf(_SC_PAGESIZE); pagesize > 1; pagesize >>= 1)
854 pageshift++;
855 }
856 if (physpages == 0) {
857 physpages = sysconf(_SC_PHYS_PAGES);
858 }
859
860 total = physpages;
861 total <<= pageshift;
862
863 ksp = kstat_lookup(kc, "unix", -1, "system_pages");
864 if (ksp && kstat_read(kc, ksp, NULL) >= 0) {
865 knp = (kstat_named_t *)kstat_data_lookup(ksp, "pagesfree");
866 if (knp) {
867 free = knp->value.ui32;
868 free <<= pageshift;
869 used = total - free;
870 }
871 }
872 gkrellm_mem_assign_data(total, used, free, 0, 0, 0);
873 if (swapctl(SC_AINFO, &ai) == -1) {
874 perror("swapctl");
875 }
876 swap_total = ai.ani_max;
877 swap_total <<= pageshift;
878
879 swap_used = ai.ani_resv;
880 swap_used <<= pageshift;
881
882 /* NEED TO BE COMPLETED
883 * mem.x_used, mem.shared, mem.buffers, mem.cached
884 * swap_chart.page_in, swap_chart.page_out (for swap pages in/out chart)
885 */
886
887 }
888
889 void
gkrellm_sys_swap_read_data(void)890 gkrellm_sys_swap_read_data(void)
891 {
892 /* page in/out UNIMPLEMENTED */
893 gkrellm_swap_assign_data(swap_total, swap_used, 0, 0);
894 }
895
896 gboolean
gkrellm_sys_mem_init(void)897 gkrellm_sys_mem_init(void)
898 {
899 return TRUE;
900 }
901
902
903 /* ===================================================================== */
904 /* FS monitor interface */
905
906 #include <sys/mnttab.h>
907 #include <sys/vfstab.h>
908 #include <sys/statvfs.h>
909 #include <sys/cdio.h>
910
911 gboolean
gkrellm_sys_fs_fstab_modified(void)912 gkrellm_sys_fs_fstab_modified(void)
913 {
914 struct stat s;
915 static time_t fstab_mtime;
916 gint modified = FALSE;
917
918 if (stat("/etc/fstab", &s) == 0 && s.st_mtime != fstab_mtime)
919 modified = TRUE;
920 fstab_mtime = s.st_mtime;
921 return modified;
922 }
923
924
925 void
gkrellm_sys_fs_get_fstab_list()926 gkrellm_sys_fs_get_fstab_list(){
927 FILE *fp;
928 struct vfstab vfsbuf;
929
930 if ((fp = fopen(VFSTAB, "r")) == NULL)
931 return;
932
933 while (getvfsent(fp, &vfsbuf) == 0) {
934 if (!vfsbuf.vfs_fstype || strcmp(vfsbuf.vfs_fstype, "ufs"))
935 continue;
936 gkrellm_fs_add_to_fstab_list(
937 vfsbuf.vfs_mountp ? vfsbuf.vfs_mountp : "",
938 vfsbuf.vfs_special ? vfsbuf.vfs_special : "",
939 vfsbuf.vfs_fstype ? vfsbuf.vfs_fstype : "",
940 vfsbuf.vfs_mntopts ? vfsbuf.vfs_mntopts : "");
941 }
942
943 fclose(fp);
944 }
945
946 void
gkrellm_sys_fs_get_mounts_list(void)947 gkrellm_sys_fs_get_mounts_list(void){
948 FILE *fp;
949 struct mnttab mntbuf;
950
951 if ((fp = fopen(MNTTAB, "r")) == NULL)
952 return;
953
954 while (getmntent(fp, &mntbuf) == 0) {
955 if (strcmp(mntbuf.mnt_fstype, "ufs") &&
956 strcmp(mntbuf.mnt_fstype, "nfs"))
957 continue;
958 gkrellm_fs_add_to_mounts_list(
959 mntbuf.mnt_mountp ? mntbuf.mnt_mountp : "",
960 mntbuf.mnt_special ? mntbuf.mnt_special : "",
961 mntbuf.mnt_fstype ? mntbuf.mnt_fstype : "");
962 }
963 fclose(fp);
964 }
965
966 void
gkrellm_sys_fs_get_fsusage(gpointer fs,gchar * dir)967 gkrellm_sys_fs_get_fsusage(gpointer fs, gchar *dir){
968 struct statvfs st;
969
970 if (dir && statvfs(dir, &st) == 0) {
971 gkrellm_fs_assign_fsusage_data(fs,
972 (gint64) st.f_blocks, (gint64) st.f_bavail,
973 (glong) st.f_bfree, (glong) st.f_bsize);
974 } else {
975 gkrellm_fs_assign_fsusage_data(fs, 0, 0, 0, 0);
976 }
977 }
978
979 static void
eject_solaris_cdrom(gchar * device)980 eject_solaris_cdrom(gchar *device) {
981 #if defined(CDROMEJECT)
982 gint d;
983
984 if ((d = open(device, O_RDONLY)) >= 0) {
985 ioctl(d, CDROMEJECT);
986 close(d);
987 }
988 #endif
989 }
990
991 gboolean
gkrellm_sys_fs_init(void)992 gkrellm_sys_fs_init(void)
993 {
994 gkrellm_fs_setup_eject(NULL, NULL, eject_solaris_cdrom, NULL);
995 return TRUE;
996 }
997
998
999 /* ===================================================================== */
1000 /* Battery monitor interface */
1001 void
gkrellm_sys_battery_read_data(void)1002 gkrellm_sys_battery_read_data(void)
1003 {
1004 }
1005
1006 gboolean
gkrellm_sys_battery_init()1007 gkrellm_sys_battery_init()
1008 {
1009 return FALSE;
1010 }
1011
1012
1013 /* ===================================================================== */
1014 /* Uptime monitor interface */
1015
1016 #include <time.h>
1017 #include <kstat.h>
1018
1019 time_t
gkrellm_sys_uptime_read_uptime(void)1020 gkrellm_sys_uptime_read_uptime(void)
1021 {
1022 return (time_t) 0; /* Will calculate using base_uptime */
1023 }
1024
1025 gboolean
gkrellm_sys_uptime_init(void)1026 gkrellm_sys_uptime_init(void) {
1027 time_t boot, now, base_uptime;
1028
1029 extern kstat_ctl_t *kc;
1030 kstat_t *ksp;
1031 kstat_named_t *knp;
1032
1033 boot = 0;
1034
1035 if (kstat_chain_update(kc) == -1) {
1036 perror("kstat_chain_update");
1037 return FALSE;
1038 }
1039 ksp = kstat_lookup(kc, "unix", -1, "system_misc");
1040 if (ksp && kstat_read(kc, ksp, NULL) >= 0) {
1041 knp = (kstat_named_t *)kstat_data_lookup(ksp, "boot_time");
1042 if (knp) {
1043 boot = knp->value.ui32;
1044 }
1045 }
1046 if (time(&now) < 0)
1047 return FALSE;
1048 if (now <= boot)
1049 return FALSE;
1050
1051 base_uptime = now - boot;
1052 base_uptime += 30;
1053 gkrellm_uptime_set_base_uptime(base_uptime);
1054
1055 return (base_uptime == (time_t) 0) ? FALSE : TRUE;
1056 }
1057
1058
1059 /* ===================================================================== */
1060 /* Sensor monitor interface */
1061 /* (nonfunctional) */
1062
1063 gboolean
gkrellm_sys_sensors_init(void)1064 gkrellm_sys_sensors_init(void)
1065 {
1066 return FALSE;
1067 }
1068
1069 gboolean
gkrellm_sys_sensors_get_temperature(gchar * name,gint id,gint iodev,gint inter,gfloat * t)1070 gkrellm_sys_sensors_get_temperature(gchar *name, gint id, gint iodev, gint inter, gfloat *t)
1071 {
1072 return FALSE;
1073 }
1074
1075 gboolean
gkrellm_sys_sensors_get_fan(gchar * name,gint id,gint iodev,gint inter,gfloat * t)1076 gkrellm_sys_sensors_get_fan(gchar *name, gint id, gint iodev, gint inter, gfloat *t)
1077 {
1078 return FALSE;
1079 }
1080
1081 gboolean
gkrellm_sys_sensors_get_voltage(gchar * name,gint id,gint iodev,gint inter,gfloat * t)1082 gkrellm_sys_sensors_get_voltage(gchar *name, gint id, gint iodev, gint inter, gfloat *t)
1083 {
1084 return FALSE;
1085 }
1086
1087