slstatus

Fork of suckless' slstatus with my personal patches
git clone https://git.instinctive.eu/slstatus.git
Log | Files | Refs | README | LICENSE

util.c (2301B)


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