suckless/slstatus

util.c in master
Repositories | Summary | Log | Files | README | LICENSE

util.c (2238B) download


  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
 11char *argv0;
 12
 13static void
 14verr(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
 26void
 27warn(const char *fmt, ...)
 28{
 29	va_list ap;
 30
 31	va_start(ap, fmt);
 32	verr(fmt, ap);
 33	va_end(ap);
 34}
 35
 36void
 37die(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
 48static int
 49evsnprintf(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
 66int
 67esnprintf(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
 79const char *
 80bprintf(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
 92const char *
 93fmt_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	scaled = num;
118	for (i = 0; i < prefixlen && scaled >= base; i++)
119		scaled /= base;
120
121	return bprintf("%.1f %s", scaled, prefix[i]);
122}
123
124int
125pscanf(const char *path, const char *fmt, ...)
126{
127	FILE *fp;
128	va_list ap;
129	int n;
130
131	if (!(fp = fopen(path, "r"))) {
132		warn("fopen '%s':", path);
133		return -1;
134	}
135	va_start(ap, fmt);
136	n = vfscanf(fp, fmt, ap);
137	va_end(ap);
138	fclose(fp);
139
140	return (n == EOF) ? -1 : n;
141}