📄 freebsd.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| FreeBSD code: Hajimu UMEMOTO <ume@FreeBSD.org>|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program is distributed in the hope that it will be useful,| but WITHOUT ANY WARRANTY; without even the implied warranty of| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the| GNU General Public License for more details. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <kvm.h>kvm_t *kvmd = NULL;char errbuf[_POSIX2_LINE_MAX];// extern gboolean force_meminfo_update(void);#if defined(__i386__)static void scan_for_sensors();#endifvoidgkrellm_sys_main_init(void) { /* We just ignore error, here. Even if GKrellM doesn't have | kmem privilege, it runs with available information. */ kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); if (setgid(getgid()) != 0) { fprintf(stderr, "Can't drop setgid privileges."); exit(1); }#if defined(__i386__) scan_for_sensors();#endif if (setuid(getuid()) != 0) { fprintf(stderr, "Can't drop setuid privileges."); exit(1); } }voidgkrellm_sys_main_cleanup(void) { }#include <sys/param.h>#include <sys/sysctl.h>static intgk_sysctlnametomib(const char *name, int *mibp, size_t *lenp) { static int oid_name2oid[2] = { 0, 3 }; if (sysctl(oid_name2oid, 2, mibp, lenp, (void *)name, strlen(name)) < 0) return -1; *lenp /= sizeof(int); return 0; }/* ===================================================================== *//* CPU monitor interface */#include <osreldate.h>#if __FreeBSD_version >= 500101#include <sys/resource.h>#else#include <sys/dkstat.h>#endif#include <kvm.h>extern kvm_t *kvmd;static int oid_cp_time[CTL_MAXNAME + 2];static size_t oid_cp_time_len = sizeof(oid_cp_time);static gint have_cp_time;voidgkrellm_sys_cpu_read_data(void) { long cp_time[CPUSTATES]; int len = sizeof(cp_time); static struct nlist nl[] = {#define N_CP_TIME 0 { "_cp_time" }, { "" } }; if (have_cp_time) { if (sysctl(oid_cp_time, oid_cp_time_len, cp_time, &len, 0, 0) < 0) return; } else { if (kvmd == NULL) return; if (nl[0].n_type == 0) if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) return; if (kvm_read(kvmd, nl[N_CP_TIME].n_value, (char *)&cp_time, sizeof(cp_time)) != sizeof(cp_time)) return; } /* Currently, SMP is not supported */ gkrellm_cpu_assign_data(0, cp_time[CP_USER], cp_time[CP_NICE], cp_time[CP_SYS], cp_time[CP_IDLE]); }gbooleangkrellm_sys_cpu_init(void) { static char *name = "kern.cp_time"; gkrellm_cpu_set_number_of_cpus(1); if (gk_sysctlnametomib(name, oid_cp_time, &oid_cp_time_len) < 0) return TRUE; ++have_cp_time; return TRUE; }/* ===================================================================== *//* Proc monitor interface */#include <osreldate.h>#include <sys/sysctl.h>#if __FreeBSD_version >= 400000#include <sys/user.h>#endif/* * This is ugly, but we need PID_MAX, in anyway. Since 5.0-RELEASE * will have vm.stats.vm.v_forks, this will be obsolete in the future. */#if __FreeBSD_version >= 400000#define PID_MAX 99999#else#include <sys/signalvar.h>#define KERNEL#include <sys/proc.h>#undef KERNEL#endif#include <kvm.h>#include <limits.h>#include <paths.h>#include <utmp.h>extern kvm_t *kvmd;static int oid_v_forks[CTL_MAXNAME + 2];static int oid_v_vforks[CTL_MAXNAME + 2];static int oid_v_rforks[CTL_MAXNAME + 2];static size_t oid_v_forks_len = sizeof(oid_v_forks);static size_t oid_v_vforks_len = sizeof(oid_v_vforks);static size_t oid_v_rforks_len = sizeof(oid_v_rforks);static int have_v_forks = 0;gbooleangkrellm_sys_proc_init(void) { static char *name = "vm.stats.vm.v_forks"; static char *vname = "vm.stats.vm.v_vforks"; static char *rname = "vm.stats.vm.v_rforks"; /* check if vm.stats.vm.v_forks is available */ if (gk_sysctlnametomib(name, oid_v_forks, &oid_v_forks_len) < 0) return TRUE; if (gk_sysctlnametomib(vname, oid_v_vforks, &oid_v_vforks_len) < 0) return TRUE; if (gk_sysctlnametomib(rname, oid_v_rforks, &oid_v_rforks_len) < 0) return TRUE; ++have_v_forks; return TRUE; }voidgkrellm_sys_proc_read_data(void) {#if __FreeBSD_version >= 400000 static int oid_proc[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };#endif double avenrun; static u_int n_processes, n_forks = 0, curpid = -1; u_int n_vforks, n_rforks; gint r_forks, r_vforks, r_rforks; gint len; gint nextpid, nforked; static struct nlist nl[] = {#define N_NEXTPID 0 { "_nextpid" }, { "" } }; if (getloadavg(&avenrun, 1) <= 0) avenrun = 0; if (have_v_forks) { /* We don't want to just use sysctlbyname(). Because, * we call it so often. */ len = sizeof(n_forks); r_forks = sysctl(oid_v_forks, oid_v_forks_len, &n_forks, &len, NULL, 0); len = sizeof(n_vforks); r_vforks = sysctl(oid_v_vforks, oid_v_vforks_len, &n_vforks, &len, NULL, 0); len = sizeof(n_rforks); r_rforks = sysctl(oid_v_rforks, oid_v_rforks_len, &n_rforks, &len, NULL, 0); if (r_forks >= 0 && r_vforks >= 0 && r_rforks >= 0) n_forks = n_forks + n_vforks + n_rforks; } else { /* workaround: Can I get total number of processes? */ if (kvmd != NULL) { if (nl[0].n_type == 0) kvm_nlist(kvmd, nl); if (nl[0].n_type != 0 && kvm_read(kvmd, nl[N_NEXTPID].n_value, (char *)&nextpid, sizeof(nextpid)) == sizeof(nextpid)) { if (curpid < 0) curpid = nextpid; if ((nforked = nextpid - curpid) < 0) n_forks += PID_MAX - 100; n_forks += nforked; curpid = nextpid; n_forks = n_forks; } } }#if __FreeBSD_version >= 400000 if (sysctl(oid_proc, 3, NULL, &len, NULL, 0) >= 0) n_processes = len / sizeof(struct kinfo_proc);#else if (kvmd != NULL) kvm_getprocs(kvmd, KERN_PROC_ALL, 0, &n_processes);#endif gkrellm_proc_assign_data(n_processes, 0, n_forks, avenrun); }voidgkrellm_sys_proc_read_users(void) { gint n_users; struct stat sb, s; gchar ttybuf[MAXPATHLEN]; FILE *ut; struct utmp utmp; static time_t utmp_mtime; if (stat(_PATH_UTMP, &s) != 0 || s.st_mtime == utmp_mtime) return; if ((ut = fopen(_PATH_UTMP, "r")) != NULL) { n_users = 0; while (fread(&utmp, sizeof(utmp), 1, ut)) { if (utmp.ut_name[0] == '\0') continue; (void)snprintf(ttybuf, sizeof(ttybuf), "%s/%s", _PATH_DEV, utmp.ut_line); /* corrupted record */ if (stat(ttybuf, &sb)) continue; ++n_users; } (void)fclose(ut); gkrellm_proc_assign_users(n_users); } utmp_mtime = s.st_mtime; }/* ===================================================================== *//* Disk monitor interface */#if __FreeBSD_version >= 300000#include <devstat.h>static struct statinfo statinfo_cur;#else#include <kvm.h>extern kvm_t *kvmd;#endifgchar *gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number, gint *order) { return NULL; /* Not implemented */ }#if __FreeBSD_version < 300000gintgkrellm_sys_disk_order_from_name(gchar *name) { return 0; /* Not implemented */ }voidgkrellm_sys_disk_read_data(void) { int ndevs; long *cur_dk_xfer; int dn; GList *list; static struct nlist nl[] = {#define N_DK_NDRIVE 0 { "_dk_ndrive" },#define N_DK_XFER 1 { "_dk_xfer" }, { "" } }; if (kvmd == NULL) return; if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) return; (void) kvm_read(kvmd, nl[N_DK_NDRIVE].n_value, (char *)&ndevs, sizeof(ndevs)); if (ndevs <= 0) return; if ((cur_dk_xfer = calloc(ndevs, sizeof(long))) == NULL) return; if (kvm_read(kvmd, nl[N_DK_XFER].n_value, (char *)cur_dk_xfer, ndevs * sizeof(long)) == ndevs * sizeof(long)) { for (dn = 0; dn < ndevs; ++dn) gkrellm_disk_assign_data_nth(dn, 0, cur_dk_xfer[dn], FALSE); } free(cur_dk_xfer); }gbooleangkrellm_sys_disk_init(void) { gkrellm_disk_units_are_blocks(); return TRUE; }#else#if __FreeBSD_version >= 500107#define getdevs(stats) devstat_getdevs(NULL, stats)#define selectdevs devstat_selectdevs#define bytes_read bytes[DEVSTAT_READ]#define bytes_written bytes[DEVSTAT_WRITE]#endifgintgkrellm_sys_disk_order_from_name(gchar *name) { return -1; /* Append as added */ }voidgkrellm_sys_disk_read_data(void) { int ndevs; int num_selected; int num_selections; int maxshowdevs = 10; struct device_selection *dev_select = NULL; long select_generation; int dn; gchar name[32]; if (getdevs(&statinfo_cur) < 0) return; ndevs = statinfo_cur.dinfo->numdevs; if (selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, statinfo_cur.dinfo->generation, statinfo_cur.dinfo->devices, ndevs, NULL, 0, NULL, 0, DS_SELECT_ONLY, maxshowdevs, 1) >= 0) { for (dn = 0; dn < ndevs; ++dn) { int di; struct devstat *dev;// int block_size;// int blocks_read, blocks_written; di = dev_select[dn].position; dev = &statinfo_cur.dinfo->devices[di];// block_size = (dev->block_size > 0)// ? dev->block_size : 512;// blocks_read = dev->bytes_read / block_size;// blocks_written = dev->bytes_written / block_size; /* to use gkrellm_disk_assign_data_by_device() would need gkrellm_sys_disk_name_from_device() implemented */ snprintf(name, sizeof(name), "%s%d", dev->device_name, dev->unit_number); gkrellm_disk_assign_data_by_name(name, dev->bytes_read, dev->bytes_written, FALSE); } free(dev_select); } }gbooleangkrellm_sys_disk_init(void) { bzero(&statinfo_cur, sizeof(statinfo_cur)); statinfo_cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); bzero(statinfo_cur.dinfo, sizeof(struct devinfo)); return TRUE; }#endif/* ===================================================================== *//* Inet monitor interface */#include "../inet.h"#if defined(INET6)#include <netinet6/ip6_var.h>#endif#include <netinet/in_pcb.h>#include <netinet/ip_var.h>#if defined(INET6)#include <netinet/ip6.h>#endif#include <netinet/tcp.h>#include <netinet/tcpip.h>#include <netinet/tcp_seq.h>#include <netinet/tcp_fsm.h>#include <netinet/tcp_timer.h>#include <netinet/tcp_var.h>#if __FreeBSD_version < 300000#if defined(INET6)#include <netinet6/tcp6.h>#include <netinet6/in6_pcb.h>#include <netinet6/tcp6_timer.h>#include <netinet6/tcp6_var.h>#endif#include <kvm.h>#include <nlist.h>extern kvm_t *kvmd;extern char errbuf[];#endif#if __FreeBSD_version < 300000voidgkrellm_sys_inet_read_tcp_data(void) { ActiveTCP tcp; gint tcp_status; struct inpcbhead head; struct inpcb inpcb, *next;#if defined(INET6) struct in6pcb in6pcb, *prev6, *next6; u_long off = nl[N_TCB6].n_value;#endif static struct nlist nl[] = {#define N_TCB 0 { "_tcb" },#if defined(INET6)#define N_TCB6 1 { "_tcb6" },#endif { "" }, }; if (kvmd == NULL) return; if (nl[0].n_type == 0) if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) return; if (kvm_read(kvmd, nl[N_TCB].n_value, (char *)&head, sizeof(struct inpcbhead)) != sizeof(struct inpcbhead)) return; for (next = head.lh_first; next != NULL; next = inpcb.inp_list.le_next) { struct tcpcb tcpcb; if (kvm_read(kvmd, (u_long)next, (char *)&inpcb, sizeof(inpcb)) != sizeof(inpcb)) return; if (kvm_read(kvmd, (u_long)inpcb.inp_ppcb, (char *)&tcpcb, sizeof(tcpcb)) != sizeof(tcpcb)) return; tcp.local_port = ntohs(inpcb.inp_lport); tcp.remote_addr.s_addr = inpcb.inp_faddr.s_addr; tcp.remote_port = ntohs(inpcb.inp_fport); tcp_status = (tcpcb.t_state == TCPS_ESTABLISHED); tcp.family = AF_INET; if (tcp_status == TCP_ALIVE) gkrellm_inet_log_tcp_port_data(&tcp); }#if defined(INET6) if (kvm_read(kvmd, off, (char *)&in6pcb, sizeof(struct in6pcb)) != sizeof(struct in6pcb)) return; prev6 = (struct in6pcb *)off; if (in6pcb.in6p_next == (struct in6pcb *)off) return; while (in6pcb.in6p_next != (struct in6pcb *)off) { struct tcp6cb tcp6cb; next6 = in6pcb.in6p_next; if (kvm_read(kvmd, (u_long)next6, (char *)&in6pcb, sizeof(in6pcb)) != sizeof(in6pcb)) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -