util.c - slstatus - status monitor
(HTM) git clone git://git.suckless.org/slstatus
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
util.c (2539B)
---
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 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 }
142
143 int
144 lscanf(FILE *fp, const char *key, const char *fmt, void *res)
145 {
146 int n;
147 char line[256];
148
149 n = -1;
150 while (fgets(line, sizeof(line), fp))
151 if (strncmp(line, key, strlen(key)) == 0) {
152 n = sscanf(line + strlen(key), fmt, res);
153 break;
154 }
155
156 rewind(fp);
157 return (n == 1) ? 1 : -1;
158 }