slstatus

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

util.c (2331B)


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