util.c - slstatus - status monitor | |
git clone git://git.suckless.org/slstatus | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
util.c (2238B) | |
--- | |
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", … | |
99 "Y" }; | |
100 const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", … | |
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 | |
124 int | |
125 pscanf(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 } |