slstatus

My fork of https://tools.suckless.org/slstatus/
git clone https://git.inz.fi/slstatus
Log | Files | Refs | README | LICENSE

util.c (2548B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <X11/Xlib.h>
      3 #include <errno.h>
      4 #include <stdarg.h>
      5 #include <stdint.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include "util.h"
     11 
     12 char *argv0;
     13 static Display *dpy = NULL;
     14 
     15 static void
     16 verr(const char *fmt, va_list ap)
     17 {
     18 	if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
     19 		fprintf(stderr, "%s: ", argv0);
     20 	}
     21 
     22 	vfprintf(stderr, fmt, ap);
     23 
     24 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
     25 		fputc(' ', stderr);
     26 		perror(NULL);
     27 	} else {
     28 		fputc('\n', stderr);
     29 	}
     30 }
     31 
     32 void
     33 warn(const char *fmt, ...)
     34 {
     35 	va_list ap;
     36 
     37 	va_start(ap, fmt);
     38 	verr(fmt, ap);
     39 	va_end(ap);
     40 }
     41 
     42 void
     43 die(const char *fmt, ...)
     44 {
     45 	va_list ap;
     46 
     47 	va_start(ap, fmt);
     48 	verr(fmt, ap);
     49 	va_end(ap);
     50 
     51 	exit(1);
     52 }
     53 
     54 int
     55 evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
     56 {
     57 	int ret;
     58 
     59 	ret = vsnprintf(str, size, fmt, ap);
     60 
     61 	if (ret < 0) {
     62 		warn("vsnprintf:");
     63 		return -1;
     64 	} else if ((size_t)ret >= size) {
     65 		warn("vsnprintf: Output truncated");
     66 		return -1;
     67 	}
     68 
     69 	return ret;
     70 }
     71 
     72 int
     73 esnprintf(char *str, size_t size, const char *fmt, ...)
     74 {
     75 	va_list ap;
     76 	int ret;
     77 
     78 	va_start(ap, fmt);
     79 	ret = evsnprintf(str, size, fmt, ap);
     80 	va_end(ap);
     81 
     82 	return ret;
     83 }
     84 
     85 const char *
     86 bprintf(const char *fmt, ...)
     87 {
     88 	va_list ap;
     89 	int ret;
     90 
     91 	va_start(ap, fmt);
     92 	ret = evsnprintf(buf, sizeof(buf), fmt, ap);
     93 	va_end(ap);
     94 
     95 	return (ret < 0) ? NULL : buf;
     96 }
     97 
     98 const char *
     99 fmt_human(uintmax_t num, int base)
    100 {
    101 	double scaled;
    102 	size_t i, prefixlen;
    103 	const char **prefix;
    104 	const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z",
    105 	                              "Y" };
    106 	const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei",
    107 	                              "Zi", "Yi" };
    108 
    109 	switch (base) {
    110 	case 1000:
    111 		prefix = prefix_1000;
    112 		prefixlen = LEN(prefix_1000);
    113 		break;
    114 	case 1024:
    115 		prefix = prefix_1024;
    116 		prefixlen = LEN(prefix_1024);
    117 		break;
    118 	default:
    119 		warn("fmt_human: Invalid base");
    120 		return NULL;
    121 	}
    122 
    123 	scaled = num;
    124 	for (i = 0; i < prefixlen && scaled >= base; i++) {
    125 		scaled /= base;
    126 	}
    127 
    128 	return bprintf("%.1f %s", scaled, prefix[i]);
    129 }
    130 
    131 int
    132 pscanf(const char *path, const char *fmt, ...)
    133 {
    134 	FILE *fp;
    135 	va_list ap;
    136 	int n;
    137 
    138 	if (!(fp = fopen(path, "r"))) {
    139 		warn("fopen '%s':", path);
    140 		return -1;
    141 	}
    142 	va_start(ap, fmt);
    143 	n = vfscanf(fp, fmt, ap);
    144 	va_end(ap);
    145 	fclose(fp);
    146 
    147 	return (n == EOF) ? -1 : n;
    148 }
    149 
    150 Display *
    151 getdisplay(void)
    152 {
    153 	if (dpy)
    154 		return dpy;
    155 	return dpy = XOpenDisplay(NULL);
    156 }
    157 
    158 void
    159 closedisplay(void)
    160 {
    161 	if (dpy)
    162 		XCloseDisplay(dpy);
    163 	dpy = NULL;
    164 }