$OpenBSD: patch-wmmon_wmmon_c,v 1.2 2001/04/14 02:38:31 naddy Exp $ --- wmmon/wmmon.c.orig Wed May 20 03:13:16 1998 +++ wmmon/wmmon.c Thu Apr 5 23:52:44 2001 @@ -28,6 +28,10 @@ Changes: ---- + 28/09/2000 (Vladimir Popov, pva48@mail.ru) + * Ported to OpenBSD + Based on FreeBSD port by Stephen Kiernan, + OpenBSD top and vmstat 18/05/1998 (Antoine Nulle, warp@xs4all.nl) * MEM/SWAP/UPTIME only updated when visible * Using global file descriptors to reduce file @@ -72,10 +76,22 @@ #include #include +#include +#include + #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -102,9 +118,28 @@ char *ProgName; int stat_current = 0; /* now global */ -FILE *fp_meminfo; -FILE *fp_stat; -FILE *fp_loadavg; +kvm_t *kd = NULL; +struct nlist nlst[] = { +#define X_CP_TIME 0 + { "_cp_time" }, +#define X_AVERUN 1 + { "_averunnable" }, +#define X_DISK_COUNT 2 + { "_disk_count" }, +#define X_DISKLIST 3 + { "_disklist" }, +#define X_KMEMBUCKETS 4 + { "_bucket" }, +#define X_KMEMSTAT 5 + { "_kmemstats" }, + { 0 } +}; +int ndrives; +struct disklist_head disk_head; +struct disk *dk_drivehead; +static int pagesize; +static int pageshift; +char errbuf[_POSIX2_LINE_MAX]; /* functions */ void usage(void); @@ -114,7 +149,11 @@ void DrawStats_io(int *, int, int, int, void wmmon_routine(int, char **); -void main(int argc, char *argv[]) { +/* OpenBSD specific functions */ +#define pagetok(size) ((size) << pageshift) +int swapmode(long *, long *); + +int main(int argc, char *argv[]) { int i; @@ -154,7 +193,11 @@ void main(int argc, char *argv[]) { } } + signal(SIGPIPE, exit); + wmmon_routine(argc, argv); + + return 0; } /*******************************************************************************\ @@ -213,8 +256,9 @@ void wmmon_routine(int argc, char **argv long istat; long idle; - FILE *fp; - char temp[128]; + int mib[2]; + size_t size; + struct timeval boottime; char *p; int xpm_X = 0, xpm_Y = 0; @@ -223,22 +267,58 @@ void wmmon_routine(int argc, char **argv long ref_time = 0; long cnt_time; + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + size = sizeof(boottime); + if ( (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && (boottime.tv_sec != 0) ) { + ref_time = time(NULL); + online_time = ref_time - boottime.tv_sec + 30; + } + + /* get the page size and calculate pageshift from it */ + pagesize = sysconf(_SC_PAGESIZE); + pageshift = 0; + while (pagesize > 1) { + pageshift++; + pagesize >>= 1; + } + + /* we only need the amount of log(2)1024 for our conversion */ + pageshift -= 10; + + if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) { + fprintf(stderr, "kvm_openfiles: %s\n", errbuf); + exit(errno); + } + + /* drop privs */ + setegid(getgid()); + setgid(getgid()); + + if (kd) { + if (kvm_nlist(kd, nlst) >= 0) { + int i; + for ( i = 0; nlst[i].n_name == NULL; i++) + if (nlst[i].n_type == 0) { + /* this one wasn't found */ + (void) fprintf(stderr, "kernel: no symbol named `%s'\n", nlst[i].n_name); + kvm_close(kd); + exit(-1); + } - fp = fopen("/proc/uptime", "r"); - fp_meminfo = fopen("/proc/meminfo", "r"); - fp_loadavg = fopen("/proc/loadavg", "r"); - fp_stat = fopen("/proc/stat", "r"); - - if (fp) { - fscanf(fp, "%ld", &online_time); - ref_time = time(0); - fclose(fp); + if (nlst[0].n_type != 0) { + (void) kvm_read(kd, nlst[X_DISK_COUNT].n_value, (char *)&ndrives, sizeof(ndrives)); + if ( ndrives > 0 ) { + kvm_read(kd, nlst[X_DISKLIST].n_value, &disk_head, sizeof(disk_head)); + dk_drivehead = disk_head.tqh_first; + } + } + } else fprintf(stderr, "kvm_nlist: %s\n", kvm_geterr(kd)); } for (i=0; irt_idle, &st->rt_stat, - &free, &shared, &buffers, &cached); - st->rt_idle >>= 10; - st->rt_stat -= buffers+cached; - st->rt_stat >>= 10; -// break; - } - if (strstr(temp, "Swap:")) { - sscanf(temp, "Swap: %ld %ld", &st2->rt_idle, &st2->rt_stat); - st2->rt_idle >>= 10; - st2->rt_stat >>= 10; - break; - } - } -} - -void update_stat_swp(stat_dev *st) { - - char temp[128]; - - fseek(fp_meminfo, 0, SEEK_SET); - while (fgets(temp, 128, fp_meminfo)) { - if (strstr(temp, "Swap:")) { - sscanf(temp, "Swap: %ld %ld", &st->rt_idle, &st->rt_stat); - st->rt_idle >>= 10; - st->rt_stat >>= 10; - break; - } + struct vmtotal total; + size_t size = sizeof(total); + static int mib[] = { CTL_VM, VM_METER }; + + /* get total -- systemwide main memory usage structure */ + if ( sysctl(mib, 2, &total, &size, NULL, 0) < 0 ) + bzero(&total, sizeof(total)); + + /* FIXME: is it right to count memory like this */ + st->rt_idle = pagetok(total.t_rm); + st->rt_stat = pagetok(total.t_arm); + + if ( !swapmode(&st2->rt_stat, &st2->rt_idle) ) { + st2->rt_idle = 0; + st2->rt_stat = 0; } - } /*******************************************************************************\ @@ -545,48 +606,41 @@ void update_stat_swp(stat_dev *st) { void get_statistics(char *devname, long *is, long *ds, long *idle) { int i; - char temp[128]; - char *p; - char *tokens = " \t\n"; - float f; + long averun[3]; + long cp_time[CPUSTATES]; long maxdiskio=0; *is = 0; *ds = 0; *idle = 0; - if (!strncmp(devname, "cpu", 3)) { - fseek(fp_stat, 0, SEEK_SET); - while (fgets(temp, 128, fp_stat)) { - if (strstr(temp, "cpu")) { - p = strtok(temp, tokens); - /* 1..3, 4 == idle, we don't want idle! */ - for (i=0; i<3; i++) { - p = strtok(NULL, tokens); - *ds += atol(p); - } - p = strtok(NULL, tokens); - *idle = atol(p); - } - } - fp_loadavg = freopen("/proc/loadavg", "r", fp_loadavg); - fscanf(fp_loadavg, "%f", &f); - *is = (long) (100 * f); - } + if (!strncmp(devname, "cpu", 3)) + if (kd) + if (kvm_nlist(kd, nlst) >= 0) + if (nlst[0].n_type != 0) + if ((kvm_read(kd, nlst[X_CP_TIME].n_value, (char *)&cp_time, sizeof(cp_time))==sizeof(cp_time)) && + (kvm_read(kd, nlst[X_AVERUN].n_value, (char *)&averun, sizeof(averun))==sizeof(averun))) { + *is = (long) (100 * ((double)averun[0] / FSCALE)); + + for (i = 0; i < CPUSTATES; i++) + if (i != CP_IDLE) *ds += cp_time[i]; + *idle = cp_time[CP_IDLE]; + } if (!strncmp(devname, "i/o", 3)) { + struct disk cur_disk, *p; + + p = dk_drivehead; + + if (kd) + if (kvm_nlist(kd, nlst) >= 0) + if (nlst[0].n_type != 0) + for (i = 0; i < ndrives; i++) + if ( kvm_read(kd, (u_long)p, &cur_disk, sizeof(cur_disk)) == sizeof(cur_disk) ) { + *ds += cur_disk.dk_seek; + p = cur_disk.dk_link.tqe_next; + } - fseek(fp_stat, 0, SEEK_SET); - while (fgets(temp, 128, fp_stat)) { - if (strstr(temp, "disk_rio") || strstr(temp, "disk_wio")) { - p = strtok(temp, tokens); - /* 1..4 */ - for (i=0; i<4; i++) { - p = strtok(NULL, tokens); - *ds += atol(p); - } - } - } if (*ds > maxdiskio) maxdiskio = *ds; } } @@ -597,9 +651,9 @@ void get_statistics(char *devname, long int checksysdevs(void) { - strcpy(stat_device[0].name, "cpu0"); - strcpy(stat_device[1].name, "i/o"); - strcpy(stat_device[2].name, "sys"); + strncpy(stat_device[0].name, "cpu0", 5); + strncpy(stat_device[1].name, "i/o", 5); + strncpy(stat_device[2].name, "sys", 5); return 3; } @@ -736,4 +790,34 @@ void printversion(void) { if (!strcmp(ProgName, "wmmon")) { fprintf(stderr, "%s\n", WMMON_VERSION); } +} + +int swapmode(long *used, long *total) { + int nswap, rnswap, i; + struct swapent *swdev; + + nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap == 0) + return 0; + + swdev = malloc(nswap * sizeof(*swdev)); + if(swdev == NULL) + return 0; + + rnswap = swapctl(SWAP_STATS, swdev, nswap); + if(rnswap == -1) + return 0; + + /* if rnswap != nswap, then what? */ + + /* Total things up */ + *total = *used = 0; + for (i = 0; i < nswap; i++) + if (swdev[i].se_flags & SWF_ENABLE) { + *used += (swdev[i].se_inuse / (1024/DEV_BSIZE)); + *total += (swdev[i].se_nblks / (1024/DEV_BSIZE)); + } + + free (swdev); + return 1; }