refresh.c

/* This is free software.  See LICENSE for terms.
 * Copyright 2004 - 2015, Patricia Kirk.
 */

#if defined(__FreeBSD__)

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fstab.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <devinfo.h>
#include <netdb.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/vmmeter.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <net/if_media.h>
#include <netinet/in.h>

#include "proto.h"

extern struct global g;
extern struct data fresh;

char buffer[BUFPLUS];
char showbuf[SHOWBUF];

void getMem() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int page[4], free[4], pagesize=0;
    size_t len;
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	if (!pagesize) {
	    len = sizeof(page);
	    sysctlnametomib("vm.stats.vm.v_page_count", page, &len);
	    len = sizeof(free);
	    sysctlnametomib("vm.stats.vm.v_free_count", free, &len);
	    pagesize = getpagesize();
	}
	len = sizeof(int);
	if ((sysctl(page, 4, &i, &len, NULL, 0)) < 0)
	    i = 0;
	fresh.memtotal = i * pagesize;
	len = sizeof(int);
	if ((sysctl(free, 4, &i, &len, NULL, 0)) < 0)
	    i = 0;
	fresh.memfree = i * pagesize;
	fresh.memused = fresh.memtotal - fresh.memfree;
	lasttime = timenow;
    }
}

void getSwap() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static char swapinfo[SMALBUF];
    static int init=1, mib[2];
    double avenrun[3];
    int i;
    size_t len;
    FILE *fd;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    len = sizeof(mib);
	    sysctlnametomib("vm.nswapdev", mib, &len);
	    findExecutable(swapinfo, SMALBUF, "swapinfo");
	    init = 0;
	}
	fresh.swaptotal = fresh.swapused = fresh.swapfree = 0;
	if ((fd = popen(swapinfo, "r"))) {
	    while (fgets(buffer, sizeof(buffer), fd)) {
		if (strstr(buffer, "Total") == buffer) {
		    if (sscanf(buffer, "%*s %lf %lf %lf",
			    &avenrun[0], &avenrun[1], &avenrun[2]) == 3) {
			fresh.swaptotal = avenrun[0] * 1024;
			fresh.swapused = avenrun[1] * 1024;
			fresh.swapfree = avenrun[2] * 1024;
		    }
		    break;
		}
	    }
	    pclose(fd);
	}
	/* swap devices */
	len = sizeof(int);
	if (!(sysctl(mib, 2, &i, &len, NULL, 0)))
	    fresh.swapdev = i;
	else
	    fresh.swapdev = 0;
	lasttime = timenow;
    }
}

void getSplit() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static long cptime[5], cptimelast[5];
    static long **cptimes, **cptimeslast;
    static int init=1, mib[2], mibs[2];
    static int timesmax=0;
    float temp;
    size_t len;
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    len = sizeof(mib);
	    sysctlnametomib("kern.cp_time", mib, &len);
	    if (g.split) {
		sysctlnametomib("kern.cp_times", mibs, &len);
		sysctl(mibs, 2, NULL, &len, NULL, 0);
		timesmax = len / sizeof(long);
		if (!((cptimes = (long **)calloc(timesmax, sizeof(long))) &&
			(cptimeslast = (long **)calloc(timesmax, sizeof(long))) &&
			(fresh.splits = (float **)calloc(timesmax, sizeof(float)))))
		    allocFailed("getSplit");
		for (i = 0; i < timesmax; i++) {
		    cptimes[i] = (long *)calloc(1, sizeof(long));
		    cptimeslast[i] = (long *)calloc(1, sizeof(long));
		    fresh.splits[i] = (float *)calloc(1, sizeof(float));
		}
	    }
	    init = 0;
	}
	if (g.split) {
	    bzero(*fresh.splits, timesmax * sizeof(float));
	    len = timesmax * sizeof(long);
	    if (sysctl(mibs, 2, cptimes, &len, NULL, 0) != -1) {
		for (j = 0; j < g.ncpu; j++) {
		    temp = 0;
		    for (i = 0; i < 5; i++) {
			*fresh.splits[i + (j * 5)] = cptimes[i + (j * 5)] - cptimeslast[i + (j * 5)];
			temp += *fresh.splits[i + (j * 5)];
			cptimeslast[i + (j * 5)] = cptimes[i + (j * 5)];
		    }
		    for (i = 0; i < 5; i++)
			*fresh.splits[i + (j * 5)] /= temp;
		}
	    }
	}
	bzero(&fresh.states, sizeof(fresh.states));
	len = sizeof(cptime);
	if (sysctl(mib, 2, &cptime, &len, NULL, 0) != -1) {
	    temp = 0;
	    for (i = 0; i < 5; i++) {
		fresh.states[i] = cptime[i] - cptimelast[i];
		temp += fresh.states[i];
		cptimelast[i] = cptime[i];
	    }
	    for (i = 0; i < 5; i++)
		fresh.states[i] /= temp;
	}
	lasttime = timenow;
    }
}

void getProcs() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    struct kinfo_proc *t, *u;
    static int init=1, mib[3];
    int i, j;
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    mib[0] = CTL_KERN;
	    mib[1] = KERN_PROC;
	    mib[2] = KERN_PROC_ALL;
	    init = 0;
	}
	bzero(&fresh.proc, sizeof(fresh.proc));
	if (!sysctl(mib, 3, NULL, &len, NULL, 0)) {
	    if ((t = calloc(len, sizeof(struct kinfo_proc)))) {
		if (!sysctl(mib, 3, t, &len, NULL, 0)) {
		    j = len / sizeof(struct kinfo_proc);
		    fresh.proc[0] = j;
		    for (i = 0; i < j; i++) {
			u = (t + j - i - 1);
			if (u->ki_stat == 2)	/* running */
			    fresh.proc[1]++;
		    }
		}
		FREE(t);
	    }
	}
	lasttime = timenow;
    }
}

void getABC() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int pagesize=0, mib[2], buf[2], cach[4];
    struct vmtotal vmtotal;
    int i;
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (!pagesize) {
	    mib[0] = CTL_VM;
	    mib[1] = VM_TOTAL;
	    len = sizeof(buf);
	    sysctlnametomib("vfs.bufspace", buf, &len);
	    len = sizeof(cach);
	    sysctlnametomib("vm.stats.vm.v_cache_count", cach, &len);
	    pagesize = getpagesize();
	}
	len = sizeof(vmtotal);
	if (!(sysctl(mib, 2, &vmtotal, &len, NULL, 0)))
	    fresh.share = vmtotal.t_rmshr + vmtotal.t_armshr + vmtotal.t_vmshr + vmtotal.t_avmshr;
	else
	    fresh.share = 0;
	len = sizeof(int);
	if (!(sysctl(buf, 2, &i, &len, NULL, 0)))
	    fresh.buffer = i < 0 ? 0 : i;
	else
	    fresh.buffer = 0;
	len = sizeof(int);
	if (!(sysctl(cach, 4, &i, &len, NULL, 0)))
	    fresh.cache = i < 0 ? 0 : i * pagesize;
	else
	    fresh.cache = 0;
	lasttime = timenow;
    }
}

void getPower() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int init=1, pow[3], bat[4];
    fixpt_t ccpu;
    size_t len;
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    len = sizeof(pow);
	    sysctlnametomib("hw.acpi.acline", pow, &len);
	    len = sizeof(bat);
	    sysctlnametomib("hw.acpi.battery.life", bat, &len);
	    init = 0;
	}
	len = sizeof(ccpu);
	sysctl(pow, 3, &i, &len, NULL, 0);
	if (!i)			/* ac line not on */
	    sysctl(bat, 4, &i, &len, NULL, 0);
	fresh.power = i;
	lasttime = timenow;
    }
}

void getTherm() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int init=1;
    int i, j=0;
    size_t len;
    fixpt_t ccpu;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    for (;; j++) {
		len = sizeof(ccpu);
		snprintf(buffer, sizeof(buffer), "hw.acpi.thermal.tz%d.temperature", j);
		if (sysctlbyname(buffer, &i, &len, NULL, 0) < 0) {
		    fresh.maxtherm = j;
		    break;
		}
	    }
	    if (fresh.maxtherm) {
		if (!(fresh.zones = (int **)calloc(fresh.maxtherm, sizeof(int))))
		    allocFailed("getTherm");
		for (i = 0; i < fresh.maxtherm; i++)
		    fresh.zones[i] = (int *)calloc(1, sizeof(int));
	    }
	    init = 0;
	}
	for (j = 0; j < fresh.maxtherm; j++) {
	    *fresh.zones[j] = 0;
	    snprintf(buffer, sizeof(buffer), "hw.acpi.thermal.tz%d.temperature", j);
	    len = sizeof(ccpu);
	    if (!sysctlbyname(buffer, &i, &len, NULL, 0))
		*fresh.zones[j] = i;
	}
	lasttime = timenow;
    }
}

int search(struct devinfo_dev *device, void *arg) {

    if (!strcmp(device->dd_name, arg))
	return 1;
    if (devinfo_foreach_device_child(device, search, arg))
	return device->dd_state;
    return 0;
}

#elif defined(__NetBSD__)

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fstab.h>
#include <fcntl.h>
#include <kvm.h>
#include <errno.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <sys/swap.h>
#include <sys/sysctl.h>
#include <sys/statvfs.h>
#include <net/if.h>
#include <net/if_media.h>
#include <netinet/in.h>

#include "proto.h"

extern struct global g;
extern struct data fresh;

char buffer[BUFPLUS];
char smalbuf[SMALBUF];
char showbuf[SHOWBUF];

void getMem() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	fresh.memtotal = fresh.memused = fresh.memfree = 0;
	readFile("/proc/meminfo", buffer);
	if (strlen(buffer)) {
	    if (strstr(buffer, "MemTotal:") && sscanf(strstr(buffer, "MemTotal:"), "%*s %d", &i) == 1)
		fresh.memtotal = i * 1024;
	    if (strstr(buffer, "MemFree:") && sscanf(strstr(buffer, "MemFree:"), "%*s %d", &i) == 1)
		fresh.memfree = i * 1024;
	    fresh.memused = fresh.memtotal - fresh.memfree;
	}
	lasttime = timenow;
    }
}

void getSwap() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    struct swapent *swapent;
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	fresh.swaptotal = fresh.swapused = fresh.swapfree = 0;
	i = swapctl(SWAP_NSWAP, NULL, 0);
	fresh.swapdev = i;
	if ((swapent = calloc(i, sizeof(struct swapent)))) {
	    swapctl(SWAP_STATS, swapent, i);
	    for (j = 0; j < i; j++) {
		if (swapent[j].se_flags & SWF_ENABLE) {
		    fresh.swapused += (double)(swapent[j].se_inuse * DEV_BSIZE);
		    fresh.swaptotal += (double)(swapent[j].se_nblks * DEV_BSIZE);
		}
	    }
	    fresh.swapfree = fresh.swaptotal - fresh.swapused;
	    FREE(swapent);
	}
	lasttime = timenow;
    }
}

void getSplit() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static u_int64_t cptime[5], cptimelast[5];
    static u_int64_t **cptimeslast;
    static int init=1, mib[3];
    static int timesmax=0;
    uint64_t temp;
    size_t len;
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    sysctlnametomib("kern.cp_time", mib, &len);
	    if (g.split) {
		mib[2] = 0;
		sysctl(mib, 3, NULL, &len, NULL, 0);
		timesmax = (len / sizeof(u_int64_t)) * g.ncpu;
		if (!((cptimeslast = (u_int64_t **)calloc(timesmax, sizeof(u_int64_t))) &&
			(fresh.splits = (float **)calloc(timesmax, sizeof(float)))))
		    allocFailed("getSplit");
		for (i = 0; i < timesmax; i++) {
		    fresh.splits[i] = (float *)calloc(1, sizeof(float));
		    cptimeslast[i] = (u_int64_t *)calloc(1, sizeof(u_int64_t));
		}
	    }
	    init = 0;
	}
	if (g.split) {
	    bzero(*fresh.splits, timesmax * sizeof(float));
	    for (j = 0; j < g.ncpu; j++) {
		mib[2] = j;
		len = sizeof(cptime);
		if (sysctl(mib, 3, &cptime, &len, NULL, 0) != -1) {
		    temp = 0;
		    for (i = 0; i < 5; i++) {
			*fresh.splits[i + (j * 5)] = cptime[i] - *cptimeslast[i + (j * 5)];
			temp += *fresh.splits[i + (j * 5)];
			*cptimeslast[i + (j * 5)] = cptime[i];
		    }
		    for (i = 0; i < 5; i++)
			*fresh.splits[i + (j * 5)] /= temp;
		}
	    }
	}
	bzero(&fresh.states, sizeof(fresh.states));
	len = sizeof(cptime);
	sysctl(mib, 2, &cptime, &len, NULL, 0);
	if (cptime[0] != -1) {
	    temp = 0;
	    for (i = 0; i < 5; i++) {
		fresh.states[i] = cptime[i] - cptimelast[i];
		temp += fresh.states[i];
		cptimelast[i] = cptime[i];
	    }
	    for (i = 0; i < 5; i++)
		fresh.states[i] /= temp;
	}
	lasttime = timenow;
    }
}

void getProcs() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    struct vmtotal vmtotal;
    size_t len;
    int mib[2];

    if (timenow >= (lasttime + g.refresh)) {
	bzero(&fresh.proc, sizeof(fresh.proc));
	readFile("/proc/loadavg", buffer);
	sscanf(buffer, "%*f %*f %*f %*i/%i", &fresh.proc[0]);
	len = sizeof(vmtotal);
	mib[0] = CTL_VM;
	mib[1] = VM_METER;
	if (!sysctl(mib, 2, &vmtotal, &len, NULL, 0))
	    fresh.proc[1] = vmtotal.t_rq;
	lasttime = timenow;
    }
}

void getABC() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	fresh.share = 0;
	fresh.buffer = 0;
	fresh.cache = 0;
	readFile("/proc/meminfo", buffer);
	if (strlen(buffer)) {
	    if (strstr(buffer, "MemShared:") && sscanf(strstr(buffer, "MemShared:"), "%*s %d", &i) == 1)
		fresh.share = i * 1024;
	    if (strstr(buffer, "Buffers:") && sscanf(strstr(buffer, "Buffers:"), "%*s %d", &i) == 1)
		fresh.buffer = i * 1024;
	    if (strstr(buffer, "Cached:") && sscanf(strstr(buffer, "Cached:"), "%*s %d", &i) == 1)
		fresh.cache = i * 1024;
	}
	lasttime = timenow;
    }
}

void getPower() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static char envstat[SMALBUF];
    static int init=1;
    float e, f;
    size_t len;
    FILE *fd;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    findExecutable(envstat, sizeof(envstat), "envstat");
	    init = 0;
	}
	fresh.power = -1;
	if (strlen(envstat)) {
	    bzero(&buffer, sizeof(buffer));
	    snprintf(smalbuf, sizeof(smalbuf), "%s -d acpiacad0", envstat);
	    if ((fd = popen(smalbuf, "r"))) {
		len = fread(buffer, sizeof(char), sizeof(buffer), fd);
		if (len) {
		    if (strstr(buffer, "connected:") && (strstr(buffer, "TRUE") ||
			    strstr(buffer, "ON")))
			fresh.power = 1;
		}
		pclose(fd);
	    }
	    if (fresh.power < 0) {
		snprintf(smalbuf, sizeof(smalbuf), "%s -d acpibat0", envstat);
		if ((fd = popen(smalbuf, "r"))) {
		    len = fread(buffer, 1, BUFSIZE, fd);
		    if (len) {
			if (strstr(buffer, "last full cap:") &&
				sscanf(strstr(buffer, "last full cap:"), "%*s %*s %*s %f", &e) == 1 &&
				strstr(buffer, "charge:") &&
				sscanf(strstr(buffer, "charge:"), "%*s %f", &f) == 1)
			    fresh.power = (int)(f / e * 100);
		    }
		    pclose(fd);
		}
	    }
	}
	lasttime = timenow;
    }
}

void getTherm() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    char *ptr=NULL;
    static char envstat[SMALBUF];
    static int init=1;
    float f;
    size_t len;
    int i;
    FILE *fd;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    if (findExecutable(envstat, sizeof(envstat), "envstat")) {
		snprintf(smalbuf, sizeof(smalbuf), "%s -D", envstat);
		bzero(&buffer, sizeof(buffer));
		if ((fd = popen(smalbuf, "r"))) {
		    len = fread(buffer, sizeof(char), sizeof(buffer), fd);
		    if (len > 0 && !ferror(fd)) {
			buffer[len] = '\0';
			if ((ptr = strstr(buffer, "acpitz"))) {
			    do {
				fresh.maxtherm++;
				ptr++;
			    } while ((ptr = strstr(ptr, "acpitz")));
			}
		    }
		    pclose(fd);
		}
		if (fresh.maxtherm) {
		    if (!(fresh.zones = (int **)calloc(fresh.maxtherm, sizeof(int))))
			allocFailed("getTherm");
		    for (i = 0; i < fresh.maxtherm; i++)
			fresh.zones[i] = (int *)calloc(1, sizeof(int));
		}
	    }
	    init = 0;
	}
	for (i = 0; i < fresh.maxtherm; i++) {
	    snprintf(buffer, sizeof(buffer), "%s -d acpitz%d", envstat, i);
	    if ((fd = popen(buffer, "r"))) {
		len = fread(buffer, 1, BUFSIZE, fd);
		buffer[len] = '\0';
		pclose(fd);
		if (len > 0 && (ptr = strstr(buffer, "temperature")) &&
			(sscanf(ptr, "%*s %f", &f) == 1))
		    *fresh.zones[i] = (int)(f * 10) + CELSIUS;
	    }
	}
	lasttime = timenow;
    }
}

void readFile(char *file, char *buffer) {
    int n=0;
    FILE *fd;

    if (!(fd = fopen(file, "r"))) {
	buffer[0] = '\0';
	return;
    }
    n = fread(buffer, sizeof(char), BUFSIZE, fd);
    buffer[n] = '\0';
    fclose(fd);
}

#elif defined(__OpenBSD__)

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <kvm.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <errno.h>
#include <ctype.h>
#include <fstab.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/swap.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sensors.h>
#include <net/if.h>
#include <net/if_media.h>

#include "proto.h"

extern struct global g;
extern struct data fresh;

char buffer[BUFPLUS];
char showbuf[SHOWBUF];

void getMem() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    struct vmtotal vmtotal;
    static int pagesize, init=1;
    int i, mib[2];
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    pagesize = getpagesize();
	    init = 0;
	}
	len = sizeof(double);
	mib[0] = CTL_HW;
	mib[1] = HW_PHYSMEM;
	if (!sysctl(mib, 2, &i, &len, NULL, 0))
	    fresh.memtotal = i;
	len = sizeof(vmtotal);
	mib[0] = CTL_VM;
	mib[1] = VM_METER;
	if (!sysctl(mib, 2, &vmtotal, &len, NULL, 0)) {
	    fresh.memfree = (double)(vmtotal.t_free * pagesize);
	    fresh.memused = fresh.memtotal - fresh.memfree;
	}
	lasttime = timenow;
    }
}

void getSwap() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    struct swapent *swapent;
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	fresh.swaptotal = fresh.swapused = fresh.swapfree = 0;
	i = swapctl(SWAP_NSWAP, NULL, 0);
	fresh.swapdev = i;
	if ((swapent = calloc(i, sizeof(struct swapent)))) {
	    swapctl(SWAP_STATS, swapent, i);
	    for (j = 0; j < i; j++) {
		if (swapent[j].se_flags & SWF_ENABLE) {
		    fresh.swapused += (double)(swapent[j].se_inuse * DEV_BSIZE);
		    fresh.swaptotal += (double)(swapent[j].se_nblks * DEV_BSIZE);
		}
	    }
	    fresh.swapfree = fresh.swaptotal - fresh.swapused;
	    FREE(swapent);
	}
	lasttime = timenow;
    }
}

void getSplit() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    static long cptime[5], cptimelast[5];
    static u_int64_t cptimes[5], **cptimeslast;
    static int init=1, mib[2], mibs[3];
    static int timesmax=0;
    float temp;
    int i, j;
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    mib[0] = CTL_KERN;
	    mib[1] = KERN_CPTIME;
	    if (g.split) {
		mibs[0] = CTL_KERN;
		mibs[1] = KERN_CPTIME2;
		mibs[2] = 0;
		sysctl(mibs, 3, NULL, &len, NULL, 0);
		timesmax = (len / sizeof(u_int64_t)) * g.ncpu;
		if (!((cptimeslast = (u_int64_t **)calloc(timesmax, sizeof(u_int64_t))) &&
			(fresh.splits = (float **)calloc(timesmax, sizeof(float)))))
		    allocFailed("getSplit");
		for (i = 0; i < timesmax; i++) {
		    fresh.splits[i] = (float *)calloc(1, sizeof(float));
		    cptimeslast[i] = (u_int64_t *)calloc(1, sizeof(u_int64_t));
		}
	    }
	    init = 0;
	}
	if (g.split) {
	    bzero(*fresh.splits, timesmax * sizeof(float));
	    for (j = 0; j < g.ncpu; j++) {
		mibs[2] = j;
		len = sizeof(cptimes);
		if (sysctl(mibs, 3, &cptimes, &len, NULL, 0) != -1) {
		    temp = 0;
		    for (i = 0; i < 5; i++) {
			*fresh.splits[i + (j * 5)] = cptimes[i] - *cptimeslast[i + (j * 5)];
			temp += *fresh.splits[i + (j * 5)];
			*cptimeslast[i + (j * 5)] = cptimes[i];
		    }
		    for (i = 0; i < 5; i++)
			*fresh.splits[i + (j * 5)] /= temp;
		}
	    }
	}
	bzero(&fresh.states, sizeof(fresh.states));
	len = sizeof(cptime);
	if (!sysctl(mib, 2, &cptime, &len, NULL, 0)) {
	    if (cptime[0] != -1) {
		temp = 0;
		for (i = 0; i < 5; i++) {
		    fresh.states[i] = cptime[i] - cptimelast[i];
		    temp += fresh.states[i];
		    cptimelast[i] = cptime[i];
		}
		for (i = 0; i < 5; i++)
		    fresh.states[i] /= temp;
	    }
	}
	lasttime = timenow;
    }
}

void getProcs() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    struct vmtotal vmtotal;
    int i, mib[2];
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	bzero(&fresh.proc, sizeof(fresh.proc));
	len = sizeof(int);
	mib[0] = CTL_KERN;
	mib[1] = KERN_NPROCS;
	if (!sysctl(mib, 2, &i, &len, NULL, 0))
	    fresh.proc[0] = i;
	len = sizeof(vmtotal);
	mib[0] = CTL_VM;
	mib[1] = VM_METER;
	if (!sysctl(mib, 2, &vmtotal, &len, NULL, 0))
	    fresh.proc[1] = vmtotal.t_rq;
	lasttime = timenow;
    }
}

void getABC() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    struct bcachestats bcstats;
    static int pagesize=0;
    int mib[3];
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (!pagesize)
	    pagesize = getpagesize();
	len = sizeof(bcstats);
	mib[0] = CTL_VFS;
	mib[1] = VFS_GENERIC;
	mib[2] = VFS_BCACHESTAT;
	if (sysctl(mib, 3, &bcstats, &len, NULL, 0) == -1)
	    bzero(&bcstats, sizeof(bcstats));
	fresh.cache = bcstats.numbufpages * pagesize;
	lasttime = timenow;
    }
}

void getPower() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    struct sensordev sensordev;
    struct sensor sensor;
    static int batmib2=0, batmib3, batfull=-1, batleft=0;
    static char apmbuf[SMALBUF];
    char *ptr=NULL;
    int mib[5], i, j, k;
    static int init=1, refresh=0;
    size_t len;
    FILE *fd;

    if (timenow >= (lasttime + refresh)) {
	if (init) {
	    refresh = g.refresh;
	    mib[0] = CTL_HW;
	    mib[1] = HW_SENSORS;
	    k = 0;
	    for (i = 0; i < SENSOR_MAX_TYPES; i++) {
		mib[2] = i;
		len = sizeof(sensordev);
		if (!sysctl(mib, 3, &sensordev, &len, NULL, 0)) {
		    if (!strncmp(sensordev.xname, "acpibat", 7)) {
			batmib2 = i;
			len = sizeof(sensor);
			mib[3] = SENSOR_WATTHOUR;
			batmib3 = mib[3];
			for (j = 0; j < SENSOR_MAX_TYPES; j++) {
			    mib[4] = j;
			    if (!sysctl(mib, 5, &sensor, &len, NULL, 0)) {
				if (strstr(sensor.desc, "last full"))
				    batfull = (int)sensor.value;
				if (strstr(sensor.desc, "remaining"))
				    batleft = j;
				if (batfull && batleft) {
				    k = 1;
				    break;
				}
			    }
			}
			if (batfull < 0) {
			    mib[3] = SENSOR_AMPHOUR;
			    batmib3 = mib[3];
			    for (j = 0; j < SENSOR_MAX_TYPES; j++) {
				mib[4] = j;
				if (!sysctl(mib, 5, &sensor, &len, NULL, 0)) {
				    if (strstr(sensor.desc, "last full"))
					batfull = (int)sensor.value;
				    if (strstr(sensor.desc, "remaining"))
					batleft = j;
				    if (batfull && batleft) {
					k = 1;
					break;
				    }
				}
			    }
			}
			if (k)
			    break;
		    }
		}
	    }
	    if (!k) {
		if (findExecutable(apmbuf, sizeof(apmbuf), "apm -v")) {
		    if ((fd = popen(apmbuf, "r"))) {
			fread(buffer, sizeof(char), sizeof(buffer), fd);
			pclose(fd);
			if (strstr(buffer, "Battery state:") && strstr(buffer, "A/C adapter state:")) {
			    batmib2 = -1;
			    batfull = 0;
			}
		    }
		    if (refresh < 60)
			refresh = 60;
		}
	    }
	    init = 0;
	}
	fresh.power = -1;
	if (batfull >= 0) {
	    if (batmib2 < 0) {
		/* sysctl failed, use apm */
		if ((fd = popen(apmbuf, "r"))) {
		    fread(buffer, sizeof(char), sizeof(buffer), fd);
		    pclose(fd);
		    if ((ptr = strstr(buffer, "A/C adapter state:"))) {
			fresh.power = 1;
			if ((ptr = strstr(ptr, "not connected")))
			    fresh.power = 0;
		    }
		}
		if (!fresh.power && (ptr = strstr(buffer, "Battery state:")) &&
			(sscanf(ptr, "%*s %*s %*s %s", showbuf) == 1) &&
			(ptr = strchr(showbuf, '%'))) {
		    *ptr = '\0';
		    fresh.power = parseStrtol(showbuf, TRUE, "getPower");
		}
	    } else {
		len = sizeof(sensordev);
		mib[0] = CTL_HW;
		mib[1] = HW_SENSORS;
		mib[2] = batmib2;
		if (!sysctl(mib, 3, &sensordev, &len, NULL, 0)) {
		    mib[3] = SENSOR_INTEGER;
		    mib[4] = 0;
		    if (!sysctl(mib, 5, &sensor, &len, NULL, 0))
			fresh.power = (int)sensor.value;
		    if (fresh.power == 1) {
			mib[3] = batmib3;
			mib[4] = batleft;
			if (!sysctl(mib, 5, &sensor, &len, NULL, 0))
			    fresh.power = 100 - ((batfull - (int)sensor.value) / 100000);
		    } else {
			fresh.power = 1;
		    }
		}
	    }
	}
	lasttime = timenow;
    }
}

void getTherm() {
    static time_t lasttime = 0;
    time_t timenow=time(NULL);
    struct sensordev sensordev;
    struct sensor sensor;
    static int tzmib2[6], tzmib3[6], tzmib4[6];
    static int mib[5], init=1;
    int i, j, k;
    size_t len;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    mib[0] = CTL_HW;
	    mib[1] = HW_SENSORS;
	    j = 0;
	    for (i = 0; i < SENSOR_MAX_TYPES; i++) {
		len = sizeof(sensordev);
		mib[2] = i;
		if (!sysctl(mib, 3, &sensordev, &len, NULL, 0)) {
		    if (!strncmp(sensordev.xname, "acpitz", 6)) {
			tzmib2[j] = mib[2];
			len = sizeof(sensor);
			mib[3] = SENSOR_TEMP;
			tzmib3[j] = mib[3];
			for (k = 0; k < SENSOR_MAX_TYPES; k++) {
			    mib[4] = k;
			    if (!sysctl(mib, 5, &sensor, &len, NULL, 0)) {
				tzmib4[j++] = mib[4];
				break;
			    }
			}
		    }
		}
	    }
	    if ((fresh.maxtherm = j)) {
		if (!(fresh.zones = (int **)calloc(fresh.maxtherm, sizeof(int))))
		    allocFailed("getTherm");
		for (i = 0; i < fresh.maxtherm; i++)
		    fresh.zones[i] = (int *)calloc(1, sizeof(int));
	    }
	    init = 0;
	}
	for (j = 0; j < fresh.maxtherm; j++) {
	    *fresh.zones[j] = 0;
	    mib[2] = tzmib2[j];
	    mib[3] = tzmib3[j];
	    mib[4] = tzmib4[j];
	    len = sizeof(sensor);
	    if (!sysctl(mib, 5, &sensor, &len, NULL, 0))
		*fresh.zones[j] = (int)(sensor.value / 100000) + 1;
	}
	lasttime = timenow;
    }
}

#elif defined(__linux__)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fstab.h>
#include <mntent.h>
#include <sys/stat.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netdb.h>

#include "proto.h"

extern struct global g;
extern struct data fresh;
extern struct lineopts *linelist;

char buffer[BUFPLUS];
char smalbuf[SMALBUF];
char showbuf[SHOWBUF];

void getMem() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	readFile("/proc/meminfo", buffer);
	if (strstr(buffer, "MemTotal:") && sscanf(strstr(buffer, "MemTotal:"), "%*s %d", &i) == 1)
	    fresh.memtotal = i * 1024;
	else
	    fresh.memtotal = 0;
	if (strstr(buffer, "MemFree:") && sscanf(strstr(buffer, "MemFree:"), "%*s %d", &i) == 1)
	    fresh.memfree = i * 1024;
	else
	    fresh.memfree = 0;
	fresh.memused = fresh.memtotal - fresh.memfree;
	lasttime= timenow;
    }
}

void getSwap() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    FILE *fd;
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	fresh.swaptotal = fresh.swapused = fresh.swapfree = 0;
	readFile("/proc/meminfo", buffer);
	if (strstr(buffer, "SwapTotal:") && sscanf(strstr(buffer, "SwapTotal:"), "%*s %d", &i) == 1)
	    fresh.swaptotal = i * 1024;
	if (strstr(buffer, "SwapFree:") && sscanf(strstr(buffer, "SwapFree:"), "%*s %d", &i) == 1)
	    fresh.swapfree = i * 1024;
	fresh.swapused = fresh.swaptotal - fresh.swapfree;
	fresh.swapdev = 0;
	if ((fd = fopen("/proc/swaps", "r"))) {
	    fgets(buffer, sizeof(buffer), fd);
	    while (fgets(buffer, sizeof(buffer), fd))
		fresh.swapdev++;
	    fclose(fd);
	}
	lasttime= timenow;
    }
}

void getSplit() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static long cptime[4], cptimelast[4];
    static long **cptimes, **cptimeslast;
    static int init=1, timesmax=0;
    float temp;
    char showbuf[SHOWBUF], *ptr;
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    if (g.split) {
		timesmax = g.ncpu * 4;
		if (!((cptimes = (long **)calloc(timesmax, sizeof(long))) &&
			(cptimeslast = (long **)calloc(timesmax, sizeof(long))) &&
			(fresh.splits = (float **)calloc(timesmax, sizeof(float)))))
		    allocFailed("getSplit");
		for (i = 0; i < timesmax; i++) {
		    cptimes[i] = (long *)calloc(1, sizeof(long));
		    cptimeslast[i] = (long *)calloc(1, sizeof(long));
		    fresh.splits[i] = (float *)calloc(1, sizeof(float));
		}
	    }
	    init = 0;
	}
	readFile("/proc/stat", buffer);
	bzero(&fresh.states, sizeof(fresh.states));
	if (sscanf(buffer, "cpu %ld %ld %ld %ld", &cptime[0], &cptime[2],
		&cptime[1], &cptime[3]) == 4) {
	    temp = 0;
	    for (i = 0; i < 4; i++)
		temp += (cptime[i] - cptimelast[i]);
	    for (i = 0; i < 4; i++) {
		fresh.states[i] = (float)(cptime[i] - cptimelast[i]) / temp;
		cptimelast[i] = cptime[i];
	    }
	}
	if (g.split) {
	    for (i = 0; i < timesmax; i++)
		*fresh.splits[i] = 0;
	    for (j = 0; j < g.ncpu; j++) {
		snprintf(showbuf, sizeof(showbuf), "cpu%d", j);
		ptr = strstr(buffer, showbuf);
		sscanf(ptr, "%*s %ld %ld %ld %ld", cptimes[0 + (j * 4)], cptimes[2 + (j * 4)],
			cptimes[1 + (j * 4)], cptimes[3 + (j * 4)]);
		temp = 0;
		for (i = 0; i < 4; i++) {
		    *fresh.splits[i + (j * 4)] = *cptimes[i + (j * 4)] - *cptimeslast[i + (j * 4)];
		    temp += *fresh.splits[i + (j * 4)];
		    *cptimeslast[i + (j * 4)] = *cptimes[i + (j * 4)];
		}
		for (i = 0; i < 4; i++)
		    *fresh.splits[i + (j * 4)] /= temp;
	    }
	}
	lasttime= timenow;
    }
}

void getProcs() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    int i, j;

    if (timenow >= (lasttime + g.refresh)) {
	bzero(&fresh.proc, sizeof(fresh.proc));
	readFile("/proc/loadavg", buffer);
	if (sscanf(buffer, "%*f %*f %*f %i/%i", &j, &i) == 2) {
	    fresh.proc[0] = i;
	    fresh.proc[1] = j;
	}
	lasttime= timenow;
    }
}

void getABC() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	readFile("/proc/meminfo", buffer);
	if (strstr(buffer, "Shmem:") &&
		sscanf(strstr(buffer, "Shmem:"), "%*s %d", &i) == 1)
	    fresh.share = i * 1024;
	else
	    fresh.share = 0;
	if (strstr(buffer, "Buffers:") &&
		sscanf(strstr(buffer, "Buffers:"), "%*s %d", &i) == 1)
	    fresh.buffer = i * 1024;
	else
	    fresh.buffer = 0;
	if (strstr(buffer, "Cached:") &&
		sscanf(strstr(buffer, "Cached:"), "%*s %d", &i) == 1)
	    fresh.cache = i * 1024;
	else
	    fresh.cache = 0;
	lasttime = timenow;
    }
}

void getPower() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int init=1, batfull=0, invert=0;
    long temp;
    struct lineopts *line;
    static char *acad=NULL, *batf=NULL, *batn=NULL;
    char *setting=NULL, *cp0, *cp1;
    char *gbye = "getPower() Linux requires three file names to provide powerstate data"
		"\n\tsetting=pathto/ACstatus,pathto/battery^full,pathto/battery^now";
    char *base = "/sys/class/power_supply/";

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    for (line = linelist; line; line = line->next) {
		if (!strcmp(line->type, "powerstate"))
		    break;
	    }
	    if (!line->setting)
		gdayMate(gbye, NULL);
	    STRDUP(setting, line->setting);
	    cp0 = setting;
	    while ((cp0 = strchr(cp0, '^')))
		*cp0++ = '_';
	    if (!(cp0 = strchr(setting, ',')))
		gdayMate(gbye, NULL);
	    *cp0++ = '\0';
	    if (!(cp1 = strchr(cp0, ',')))
		gdayMate(gbye, NULL);
	    *cp1++ = '\0';
	    STRDUP(acad, setting);
	    STRDUP(batf, cp0);
	    STRDUP(batn, cp1);
	    FREE(setting);
	    FREE(line->setting);
	    snprintf(smalbuf, sizeof(smalbuf), "%s%s", base, batf);
	    readFile(smalbuf, showbuf);
	    batfull = parseStrtol(showbuf, TRUE, "getPower");
	    if (!batfull) {
		snprintf(smalbuf, sizeof(smalbuf), "%s%s", base, batn);
		readFile(smalbuf, showbuf);
		batfull = parseStrtol(showbuf, TRUE, "getPower");
	    }
	    if ((cp0 = rindex(acad, '-')) == (acad + strlen(acad) - 1)) {
		/* If the battery is near dead or maybe missing, the data
		 * while valid may not be meaningful.  Allow user to invert
		 * it by appending a dash to the end of the acad definition.
		 * This is also needed in some cases where everything is
		 * nominal but it still doesn`t read correctly.
		 * 
		 * no fewer than five steering wheels hidden about the cockpit
		 * ... but you'd be able to shift gears with your car stereo.
		 * Useful feature, that.
		 */
		*cp0 = '\0';
		invert = 1;
	    }
	    init = 0;
	}
	fresh.power = 0;
	snprintf(smalbuf, sizeof(smalbuf), "%s%s", base, acad);
	readFile(smalbuf, showbuf);
	fresh.power = parseStrtol(showbuf, TRUE, "getPower");
	if (invert)
	    fresh.power = !fresh.power;
	if (!fresh.power) {
	    snprintf(smalbuf, sizeof(smalbuf), "%s%s", base, batn);
	    readFile(smalbuf, showbuf);
	    errno = 0;
	    temp = strtol(showbuf, NULL, 10);
	    if (strlen(showbuf) && !errno)
		fresh.power = (int)((float)temp / (float)batfull * 100);
	    else
		fresh.power = -1;
	}
	lasttime = timenow;
    }
}

void getTherm() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    static int init=1;
    long temp;
    int i=0;

    if (timenow >= (lasttime + g.refresh)) {
	if (init) {
	    for (;; i++) {
		snprintf(smalbuf, sizeof(smalbuf),
			 "/sys/class/thermal/thermal_zone%d/temp", i);
		readFile(smalbuf, showbuf);
		if (showbuf[0] == '\0')
		    break;
	    }
	    if ((fresh.maxtherm = i)) {
		if (!(fresh.zones = (int **)calloc(fresh.maxtherm, sizeof(int))))
		    allocFailed("getTherm");
		for (i = 0; i < fresh.maxtherm; i++)
		    fresh.zones[i] = (int *)calloc(1, sizeof(int));
	    }
	    init = 0;
	}
	for (i = 0; i < fresh.maxtherm; i++) {
	    snprintf(smalbuf, sizeof(smalbuf),
		     "/sys/class/thermal/thermal_zone%d/temp", i);
	    readFile(smalbuf, showbuf);
	    temp = strtol(showbuf, NULL, 10);
	    *fresh.zones[i] = (temp / 100) + CELSIUS;
	}
	lasttime = timenow;
    }
}

void readFile(char *file, char *buffer) {
    int n=0;
    FILE *fd;

    if (!(fd = fopen(file, "r"))) {
	buffer[0] = '\0';
	return;
    }
    n = fread(buffer, sizeof(char), BUFSIZE, fd);
    buffer[n] = '\0';
    fclose(fd);
}

#endif	/* (__FreeBSD__) etc... */

void getOSVals() {
#if defined (__linux__)
    char *ptr, *cp0;
    time_t timenow=time(NULL);
    double uptime;

    bzero(&fresh, sizeof(struct data));
    readFile("/proc/version", buffer);
    STRDUP(g.ostype, "Unknown|OS");
    if ((ptr = strchr(buffer, ' '))) {
	/* Center type and version. */
	*ptr = '\0';
	snprintf(showbuf, sizeof(showbuf), "|%s|", buffer);
	STRDUP(g.ostype, showbuf);
	*ptr = ' ';
    }
    STRDUP(g.osvers, "Unknown|VS");
    if ((ptr = strstr(buffer, "version")) && (ptr = strchr(ptr, ' '))) {
	ptr++;
	if ((cp0 = strchr(ptr, '-')) || (cp0 = strchr(ptr, ' '))) {
	    *cp0 = '\0';
	    snprintf(showbuf, sizeof(showbuf), "|%s|", ptr);
	    STRDUP(g.osvers, showbuf);
	}
    }
    readFile("/proc/cpuinfo", buffer);
    ptr = buffer;
    while ((ptr = strstr(ptr, "vendor_id"))) {
	g.ncpu++;
	ptr++;
    }
    readFile("/proc/uptime", buffer);
    if (sscanf(buffer, "%lf", &uptime) == 1)
	g.boottime = (timenow - uptime);
#else	/* (__linux__) */
    struct timeval boottime;
    int mib[2], i, j, k;
    size_t len;

    bzero(&fresh, sizeof(struct data));
    mib[0] = CTL_KERN;
    mib[1] = KERN_OSTYPE;
    len = sizeof(showbuf);
    if (sysctl(mib, 2, &buffer, &len, NULL, 0) == -1)
	snprintf(buffer, sizeof(buffer), "Unknown|OS");
    snprintf(showbuf, sizeof(showbuf), "|%s|", buffer);
    STRDUP(g.ostype, showbuf);
    mib[0] = CTL_KERN;
    mib[1] = KERN_OSRELEASE;
    len = sizeof(showbuf);
    if (sysctl(mib, 2, &buffer, &len, NULL, 0) == -1) {
	snprintf(buffer, sizeof(buffer), "Unknown|VS");
    } else {
	j = strlen(buffer);
	k = 0;
	for (i = 0; i < j; i++) {
	    if (buffer[i] == DASH)
		buffer[i] = PIPE;
	    else if (k)
		buffer[i] = tolower((int)buffer[i]);
	    else if (buffer[i] != tolower((int)buffer[i]))
		k = 1;
	}
    }
    snprintf(showbuf, sizeof(showbuf), "|%s|", buffer);
    STRDUP(g.osvers, showbuf);
    mib[0] = CTL_HW;
    mib[1] = HW_NCPU;
    len = sizeof(int);
    sysctl(mib, 2, &g.ncpu, &len, NULL, 0);
    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    len = sizeof(boottime);
    sysctl(mib, 2, &boottime, &len, NULL, 0);
    g.boottime = boottime.tv_sec;
#endif	/* !(__linux__) */
}

void getLoads() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    double loads[3];
    int i;

    if (timenow >= (lasttime + g.refresh)) {
	bzero(fresh.loads, sizeof(fresh.loads));
	if (getloadavg(loads, 3) == 3) {
	    for (i = 0; i < 3; i++)
		fresh.loads[i] = loads[i];
	}
	lasttime = timenow;
    }
}

void getUptime() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);

    if (timenow >= (lasttime + g.refresh)) {
	if (g.boottime)
	    fresh.uptime = timenow - g.boottime;
	else
	    fresh.uptime = 0;
	lasttime = timenow;
    }
}

void getHostNet() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    char smalbuf[SMALBUF], *ptr;
#if defined (__linux__)
    struct addrinfo hints, *res=NULL;
#endif	/* (__linux__) */

    if (timenow >= lasttime + g.refresh) {
	STRDUP(g.hostname, "Unknown|Host");
	STRDUP(g.network, "Unknown|Net");
	if (!gethostname(smalbuf, sizeof(smalbuf))) {
	    smalbuf[sizeof(smalbuf) - 1] = '\0';
#if defined (__linux__)
	    bzero(&hints, sizeof(hints));
	    hints.ai_flags |= AI_CANONNAME;
	    if (!getaddrinfo(smalbuf, NULL, &hints, &res)) {
		snprintf(smalbuf, sizeof(smalbuf), "%s", res->ai_canonname);
		freeaddrinfo(res);
	    }
#endif	/* (__linux__) */
	    if ((ptr = strchr(smalbuf, '.'))) {
		*ptr++ = '\0';
		STRDUP(g.hostname, smalbuf);
		STRDUP(g.network, ptr);
	    }
	}
	lasttime = timenow;
    }
}

#if defined(__NetBSD__) || defined(__OpenBSD__)
extern int pointless[];
#endif

void getVolume() {
    static time_t lasttime=0;
    time_t timenow=time(NULL);
    char *ptrl=NULL, *ptrr=NULL;
    FILE *fd;
#if defined(__NetBSD__) || defined(__OpenBSD__)
    int i, j;
#endif

    if (timenow >= (lasttime + g.refresh)) {
#if defined(__FreeBSD__)
	if ((fd = popen(g.mixer, "r"))) {
	    while (fgets(buffer, sizeof(buffer), fd)) {
		if (strstr(buffer, "vol"))
		    break;
	    }
	    pclose(fd);
	    ptrl = strrchr(buffer, ' ');
	    ptrr = strrchr(buffer, ':');
	    *ptrr++ = '\0';
	    fresh.volume[0] = parseStrtol(ptrl, TRUE, "getVolume");
	    fresh.volume[1] = parseStrtol(ptrr, TRUE, "getVolume");
	}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
	snprintf(buffer, BUFPLUS, "%s -a", g.mixer);
	if ((fd = popen(buffer, "r"))) {
	    while (fgets(buffer, sizeof(buffer), fd)) {
		if (strstr(buffer, "outputs.master"))
		    break;
	    }
	    pclose(fd);
	    if ((ptrl = strchr(buffer, '\n')))
		*ptrl = '\0';
	    ptrl = strrchr(buffer, '=') + 1;
	    ptrr = strrchr(buffer, ',');
	    *ptrr++ = '\0';
	    j = parseStrtol(ptrl, TRUE, "getVolume");
	    for (i = 0;; i++) {
		if (pointless[i] == j) {
		    if (i <= 2)
			i = 0;
		    else if (i >= 95)
			i = 100;
		    fresh.volume[0] = i;
		    break;
		}
	    }
	    j = parseStrtol(ptrr, TRUE, "getVolume");
	    for (i = 0;; i++) {
		if (pointless[i] == j) {
		    if (i <= 2)
			i = 0;
		    else if (i >= 95)
			i = 100;
		    fresh.volume[1] = i;
		    break;
		}
	    }
	}
#elif defined(__linux__)
	snprintf(buffer, BUFPLUS, "%s -q", g.mixer);
	if ((fd = popen(buffer, "r"))) {
	    while (fgets(buffer, sizeof(buffer), fd)) {
		if (strstr(buffer, "vol"))
		    break;
	    }
	    pclose(fd);
	    ptrl = strchr(buffer, ' ');
	    ptrr = strrchr(buffer, ',');
	    *ptrr = '\0';	/* second comma */
	    ptrr = strchr(buffer, ',');
	    *ptrr++ = '\0';
	    fresh.volume[0] = parseStrtol(ptrl, TRUE, "getVolume");
	    fresh.volume[1] = parseStrtol(ptrr, TRUE, "getVolume");
	}
#endif
	lasttime = timenow;
    }
}

void setColor(struct lineopts *line, int i) {

    FREE(line->buffer);
    if (line->setting)
	snprintf(showbuf, sizeof(showbuf), "%s| ", line->setting);
    else
	snprintf(showbuf, sizeof(showbuf), "%s| ", line->argument);
    if (!i) {
	if (line->color3) {
	    line->color = line->color3;
	} else {
	    showbuf[strlen(showbuf) - 1] = '?';
	    STRDUP(line->buffer, showbuf);
	}
    } else if (i == 1) {
	if (line->color2) {
	    line->color = line->color2;
	} else {
	    showbuf[strlen(showbuf) - 1] = DSCEN;
	    STRDUP(line->buffer, showbuf);
	}
    } else {
	if (line->color1) {
	    line->color = line->color1;
	} else {
	    showbuf[strlen(showbuf) - 1] = ASCEN;
	    STRDUP(line->buffer, showbuf);
	}
    }
}

void devDevice(struct lineopts *line) {
    struct stat fstat;
    int i=0;

    if (!stat(line->argument, &fstat))
	i = 2;
    setColor(line, i);
}

/* line->status is used in checkEvents() to
 * determine the un/mounted status of the fs
 * line->status = "0" if fs is not in /etc/fstab
 * line->status = "1" if fs is not mounted
 * line->status = "2" if fs is mounted
 * i=0, 1 or 2 is for setColor() to
 * set the line->color or ? ^ or v
 */
void mntPoint(struct lineopts *line) {
    struct fstab *ent;
    struct lineopts *l;
    char smalbuf[SMALBUF], *ptr;
    int i=0;
#if defined (__linux__)
    struct mntent *mntent;
    FILE *fd;
#else
#if defined(__NetBSD__)
    struct statvfs *statfs;
#else
    struct statfs *statfs;
#endif	/* (__NetBSD__) */
    int j, mounted;
#endif	/* (__linux__) */

    if (!line->value) {
	if (!line->setting && (ptr = strrchr(line->argument, SLASH))) {
	    STRDUP(line->setting, ptr);
	}
	/* This only happens once. */
	STRDUP(line->value, "0");
	while ((ent = getfsent())) {
	    if (!strcmp(ent->fs_file, line->argument)) {
		snprintf(smalbuf, SMALBUF, "-o %s -t %s %s %s", ent->fs_mntops,
			 ent->fs_vfstype, ent->fs_spec, ent->fs_file);
		STRDUP(line->value, smalbuf);
		if (!strcmp(ent->fs_vfstype, "nfs")) {
		    /* We don`t want to call u/mount on this fs if the host
		     * is not responding.  Splice another line into the
		     * linelist and set it to monitor the status of the
		     * remote host.
		     */
		    if ((ptr = strchr(ent->fs_spec, ':')))
			*ptr = '\0';
		    else
			gdayMate("mntPoint() network file system is not resolvable", ent->fs_spec);
		    CALLOC(l, 1, sizeof(struct lineopts), "mntPoint");
		    STRDUP(l->type, "remotehost");
		    l->index = getIndex(l->type);
		    l->upper = l->lower = l->left = l->right = 999;
		    STRDUP(l->argument, ent->fs_spec);
		    remoteHost(l);
		    l->next = line->next;
		    line->next = l;
		}
		break;
	    }
	}
	endfsent();
    }
    if (strcmp(line->value, "0")) {
	/* line->value is set to mntopts if
	 * line->argument is in /etc/fstab
	 */
	STRDUP(line->status, "1");
	i = 1;
#if defined (__linux__)
	if ((fd = fopen("/etc/mtab", "r"))) {
	    while ((mntent = getmntent(fd))) {
		if (!strcmp(line->argument, mntent->mnt_dir)) {
		    STRDUP(line->status, "2");
		    i++;
		    break;
		}
	    }
	    endmntent(fd);
	}
#else
	mounted = getmntinfo(&statfs, MNT_NOWAIT);
	for (j = mounted; j > 0; j--) {
	    if (!strcmp(line->argument, statfs[j - 1].f_mntonname)) {
		STRDUP(line->status, "2");
		i++;
		break;
	    }
	}
#endif	/* (__linux__) */
    } else {
	STRDUP(line->status, "0");
    }
    setColor(line, i);
}

int interFace(struct lineopts *line) {
    struct ifaddrs *ifaddr, *ifa;
    int i=0, yes=0;
#if !defined(__linux__)
    struct ifmediareq ifmreq;
    int j;
#endif	/* !(__linux__) */

    STRDUP(line->status, "0");
    if (!getifaddrs(&ifaddr)) {
	for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
	    if (!ifa->ifa_addr)
		continue;
	    if (!strcmp(line->argument, ifa->ifa_name)) {
		if (ifa->ifa_flags & IFF_UP) {
		    STRDUP(line->status, "1");
		    i = 1;
#if defined(__linux__)
		    if (ifa->ifa_flags & IFF_RUNNING) {
			STRDUP(line->status, "2");
			i++;
		    }
#else
		    if ((j = socket(AF_INET, SOCK_DGRAM, 0)) > 0) {
			bzero(&ifmreq, sizeof(ifmreq));
			stringcpy(ifmreq.ifm_name, ifa->ifa_name, sizeof(ifmreq.ifm_name));
			if (ioctl(j, SIOCGIFMEDIA, (caddr_t)&ifmreq) >= 0) {
			    if (ifmreq.ifm_status & IFM_ACTIVE) {
				STRDUP(line->status, "2");
				i++;
			    }
			}
			close(j);
		    }
#endif	/* (__linux__) */
		}
		yes = 1;	/* Device looks like an interface. */
		break;
	    }
	}
	freeifaddrs(ifaddr);
    }
    setColor(line, i);
    return yes;
}

int remoteHost(struct lineopts *line) {
    struct addrinfo hints, *res=NULL;
    int i=0, pingcount, yes=0;
    char showbuf[SHOWBUF], *ptr;

    if (!line->value) {
	/* This only happens the first time through for a line.
	 * line->value is the current ping count for this line.
	 * line->status is the time to wait for a response in
	 * seconds clamped at 10 to 150 seconds.
	 */
	if ((ptr = strchr(line->argument, ','))) {
	    *ptr++ = '\0';
	    snprintf(showbuf, sizeof(showbuf), "%s", line->argument);
	    i = parseStrtol(ptr, TRUE, "remoteHost");
	    if (i < 10)
		i = 10;
	    else if (i > 150)
		i = 150;
	    STRDUP(line->argument, showbuf);
	} else {
	    i = 60;
	}
	snprintf(showbuf, sizeof(showbuf), "%d", i);
	STRDUP(line->status, showbuf);
	STRDUP(line->value, "0");
    }
    bzero(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_RAW;
    hints.ai_protocol = IPPROTO_UDP;
    pingcount = parseStrtol(line->value, TRUE, "remoteHost");
    if (!(getaddrinfo(line->argument, NULL, &hints, &res))) {
	freeaddrinfo(res);
	i = 1;
	if (g.pingsock > 0) {
	    if (pingcount < 10) {
		if (ping(line) > 0)
		    i = 2;
		pingcount++;
		if (pingcount == 10)
		    pingcount = 69;
	    } else {
		pingcount--;
		if (pingcount == 9)
		    pingcount = 0;
	    }
	}
	snprintf(showbuf, sizeof(showbuf), "%d", pingcount);
	STRDUP(line->value, showbuf);
	yes = 1;	/* Device resolves as a remote computer. */
    }
    setColor(line, i);
    return yes;
}

int devInfo(struct lineopts *line) {
#if defined(__FreeBSD__)
    struct devinfo_dev *device;
    int i=0, devinfo, yes=0;

    if ((!(devinfo = devinfo_init())) && (device = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE))) {
	i = devinfo_foreach_device_child(device, search, (void *)line->argument);
	if (i)
	    yes = 1;
	if (i == 40)
	    i = 2;
	else if (i)
	    i = 1;
    }
    if (!devinfo)
	devinfo_free();
    setColor(line, i);
    return yes;
#else
    return 0;
#endif	/* (__FreeBSD__) */
}
* * o * *