* dwmstatus for OpenBSD
       
   URI git clone git://git.codevoid.de/dwmstatus-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
       dwmstatus.c (6770B)
       ---
            1 // Copy me if you can.
            2 // by 20h
            3 
            4 #define _BSD_SOURCE
            5 #include <unistd.h>
            6 #include <stdio.h>
            7 #include <stdlib.h>
            8 #include <stdarg.h>
            9 #include <string.h>
           10 #include <sys/time.h>
           11 #include <sys/sysctl.h>
           12 #include <sys/ioctl.h>
           13 #include <sys/types.h>
           14 #include <sys/socket.h>
           15 #include <ifaddrs.h>
           16 #include <fcntl.h>
           17 #include <X11/Xlib.h>
           18 #include <sys/param.h>
           19 #include <sys/mount.h>
           20 #ifdef __linux__
           21 #include <sys/statfs.h>
           22 #include <time.h>
           23 #else
           24 #include <sys/sensors.h>
           25 #include <sys/audioio.h>
           26 #include <machine/apmvar.h>
           27 
           28 #endif
           29 
           30 // configuration
           31 #define UPDATE_INTERVAL 10
           32 
           33 // conversation presets
           34 #define ZEROCTOC(x) ((x)-2731) / 10
           35 #define BTOMB(x) ((x)*1048576
           36 #define BTOGB(x) ((x)*1073741824
           37 
           38     static Display *dpy;
           39     char *tzlocal = "Europe/Berlin";
           40 
           41     char * smprintf(char *fmt, ...) {
           42     va_list fmtargs;
           43     char *ret;
           44     int len;
           45 
           46     va_start(fmtargs, fmt);
           47     len = vsnprintf(NULL, 0, fmt, fmtargs);
           48     va_end(fmtargs);
           49 
           50     ret = malloc(++len);
           51     if (ret == NULL) {
           52     perror("malloc");
           53     exit(1);
           54     }
           55 
           56     va_start(fmtargs, fmt);
           57     vsnprintf(ret, len, fmt, fmtargs);
           58     va_end(fmtargs);
           59 
           60     return ret;
           61     }
           62 
           63 char * getfreespace(const char *path) {
           64     struct statfs vfs;
           65     statfs(path, &vfs);
           66     return smprintf("%ld", (vfs.f_bavail * vfs.f_bsize) / 1024 / 1024);
           67 }
           68 
           69 #ifdef __OpenBSD__
           70 char * getcputemp() {
           71     struct sensor sensor;
           72     size_t slen = sizeof(sensor);
           73     int mib[5] = { CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0 }; // Lenovo x230
           74     if (sysctl(mib, 5, &sensor, &slen, NULL, 0) != -1)
           75         return smprintf("%.0f", (sensor.value  - 273150000) / 1000000.0);
           76     return smprintf("err");
           77 }
           78 #endif
           79 
           80 #ifdef __OpenBSD__
           81 char * getfan() {
           82     struct sensor sensor;
           83     size_t slen = sizeof(sensor);
           84     int mib[5] = { CTL_HW, HW_SENSORS, 5, SENSOR_FANRPM, 0 }; // Lenovo x230
           85     if (sysctl(mib, 5, &sensor, &slen, NULL, 0) != -1)
           86         return smprintf("%i", sensor.value);
           87     return smprintf("err");
           88 }
           89 #endif
           90 
           91 #ifdef __OpenBSD__
           92 char * getvolume() {
           93     static int                        cls = -1, fd, v;
           94     static struct mixer_devinfo        mdi;
           95     static struct mixer_ctrl        mc;
           96 
           97     if ((fd = open("/dev/mixer", O_RDONLY)) == -1)
           98         return smprintf("NOMIXER");
           99 
          100     for (mdi.index = 0; cls == -1; ++mdi.index) {
          101         if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mdi) == -1)
          102             goto fail;
          103         if (mdi.type == AUDIO_MIXER_CLASS &&
          104                 strcmp(mdi.label.name, AudioCoutputs) == 0)
          105             cls = mdi.index;
          106     }
          107     for (mdi.index = 0, v = -1; v == -1; ++mdi.index) {
          108         if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mdi) == -1)
          109             goto fail;
          110         if (mdi.type == AUDIO_MIXER_VALUE &&
          111                 mdi.prev == AUDIO_MIXER_LAST &&
          112                 mdi.mixer_class == cls &&
          113                 strcmp(mdi.label.name, AudioNmaster) == 0) {
          114             mc.dev = mdi.index;
          115             if (ioctl(fd, AUDIO_MIXER_READ, &mc) == -1)
          116                 goto fail;
          117             v = MAX(mc.un.value.level[AUDIO_MIXER_LEVEL_MONO],
          118                     mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
          119         }
          120     }
          121 
          122     if (v == -1 || close(fd) == -1)
          123         return smprintf("NOCHAN");
          124 
          125     return smprintf("%i", v * 100 / 255);
          126 
          127 fail:
          128     (void)close(fd);
          129     return smprintf("FAILED");
          130 }
          131 #endif 
          132 
          133 void settz(char *tzname) {
          134     setenv("TZ", tzname, 1);
          135 }
          136 
          137 char * mktimes(char *fmt, char *tzname) {
          138     char buf[129];
          139     time_t tim;
          140     struct tm *timtm;
          141 
          142     settz(tzname);
          143     tim = time(NULL);
          144     timtm = localtime(&tim);
          145     if (timtm == NULL)
          146         return smprintf("");
          147 
          148     if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) {
          149         fprintf(stderr, "strftime == 0\n");
          150         return smprintf("");
          151     }
          152 
          153     return smprintf("%s", buf);
          154 }
          155 
          156 void setstatus(char *str) {
          157     XStoreName(dpy, DefaultRootWindow(dpy), str);
          158     XSync(dpy, False);
          159 }
          160 
          161 char * loadavg(int i) {
          162     double avgs[3];
          163 
          164     if (getloadavg(avgs, 3) < 0)
          165         return smprintf("");
          166 
          167     //return smprintf("%.2f|%.2f|%.2f", avgs[0], avgs[1], avgs[2]);
          168     return smprintf("%.2f", avgs[i]);
          169 }
          170 
          171 char * readfile(char *base, char *file) {
          172     char *path, line[513];
          173     FILE *fd;
          174 
          175     memset(line, 0, sizeof(line));
          176 
          177     path = smprintf("%s/%s", base, file);
          178     fd = fopen(path, "r");
          179     free(path);
          180     if (fd == NULL)
          181         return NULL;
          182 
          183     if (fgets(line, sizeof(line)-1, fd) == NULL)
          184         return NULL;
          185     fclose(fd);
          186 
          187     return smprintf("%s", line);
          188 }
          189 
          190 #ifdef __OpenBSD__
          191 char * getbattery()
          192 {
          193     int        fd;
          194     struct apm_power_info pi;
          195 
          196     if ((fd = open("/dev/apm", O_RDONLY)) == -1 ||
          197             ioctl(fd, APM_IOC_GETPOWER, &pi) == -1 ||
          198             close(fd) == -1)
          199         return smprintf("battery");
          200 
          201     if (pi.battery_state == APM_BATT_UNKNOWN ||
          202             pi.battery_state == APM_BATTERY_ABSENT)
          203         return smprintf("no battery");
          204 
          205     return smprintf("%i", pi.battery_life);
          206 }
          207 #endif
          208 
          209 char * getifaddr(char * intf)
          210 {
          211     struct ifaddrs *addrs;
          212     getifaddrs(&addrs);
          213 
          214     while (addrs)
          215     {
          216         if (addrs->ifa_addr && strcmp(addrs->ifa_name,intf)
          217                 && addrs->ifa_addr->sa_family == AF_INET)
          218         {
          219             struct sockaddr * myaddr = addrs->ifa_addr;
          220             return smprintf("%x", myaddr);
          221         }
          222         addrs = addrs->ifa_next;
          223     }
          224     freeifaddrs(addrs);
          225     return smprintf("n/a");
          226 }
          227 
          228 // update all values and print statusbar
          229 void update() {
          230 
          231     // date and time (local)
          232     char *time = mktimes("%H:%M", tzlocal);
          233     char *date = mktimes("%a %Y-%m-%d", tzlocal);
          234 
          235     // display status
          236 #ifdef __linux__
          237     char *freehomespace = getfreespace("/home");
          238     setstatus(smprintf(
          239                 "SPACE: %.2fG | LOAD: %s | %s %s",
          240                 (float)atoi(freehomespace) / 1024, loadavg(0), date, time));
          241     free(freehomespace);
          242 #else
          243     char *freehomespace = getfreespace("/home");
          244     char *freedataspace = getfreespace("/data");
          245     setstatus(smprintf(
          246                 "H:%.2fG D:%.2fG šŸ”Œ %s%% šŸ”Š %s%% šŸ”„ %sĀ°C šŸ”ƒ %sRPM šŸ“ˆ %s @ %s",
          247                 (float)atoi(freehomespace) / 1024, (float)atoi(freedataspace) / 1024,
          248                 getbattery(), getvolume(), getcputemp(), getfan(), loadavg(0), time));
          249     free(freehomespace);
          250     free(freedataspace);
          251 #endif
          252     free(time);
          253     free(date);
          254 
          255     // free everything up
          256 }
          257 
          258 void sig_handler(int signo) {
          259     if (signo == SIGUSR1)
          260         update();
          261     usleep(50000);
          262 }
          263 
          264 int main(void) {
          265 
          266     if (!(dpy = XOpenDisplay(NULL))) {
          267         fprintf(stderr, "dwmstatus: cannot open display.\n");
          268         return 1;
          269     }
          270 
          271     // register signal handler
          272     if (signal(SIGUSR1, sig_handler) == SIG_ERR) {
          273         fprintf(stderr, "Err: can't register update signal (SIGUSR1)\n");
          274         return 1;
          275     }
          276 
          277     // update status
          278     for (;;sleep(UPDATE_INTERVAL)) {
          279         update();
          280     }
          281 
          282     XCloseDisplay(dpy);
          283 
          284     return 0;
          285 }