slstatus

status monitor
git clone git://git.suckless.org/slstatus
Log | Files | Refs | README | LICENSE

util.c (2341B)


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