Xinqi Bao's Git

swap_perc: check for division by zero
[slstatus.git] / util.c
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <stdarg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "util.h"
9
10 char *argv0;
11
12 static void
13 verr(const char *fmt, va_list ap)
14 {
15 if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
16 fprintf(stderr, "%s: ", argv0);
17 }
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 int
52 esnprintf(char *str, size_t size, const char *fmt, ...)
53 {
54 va_list ap;
55 int ret;
56
57 va_start(ap, fmt);
58 ret = vsnprintf(str, size, fmt, ap);
59 va_end(ap);
60
61 if (ret < 0) {
62 warn("snprintf:");
63 return -1;
64 } else if ((size_t)ret >= size) {
65 warn("snprintf: Output truncated");
66 return -1;
67 }
68
69 return ret;
70 }
71
72 const char *
73 bprintf(const char *fmt, ...)
74 {
75 va_list ap;
76 int ret;
77
78 va_start(ap, fmt);
79 if ((ret = vsnprintf(buf, sizeof(buf), fmt, ap)) < 0) {
80 warn("vsnprintf:");
81 } else if ((size_t)ret >= sizeof(buf)) {
82 warn("vsnprintf: Output truncated");
83 }
84 va_end(ap);
85
86 return buf;
87 }
88
89 const char *
90 fmt_human_2(size_t num, char *unit)
91 {
92 size_t i;
93 double scaled;
94 const char *prefix[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei",
95 "Zi", "Yi" };
96
97 scaled = num;
98 for (i = 0; i < LEN(prefix) && scaled >= 1024; i++) {
99 scaled /= 1024.0;
100 }
101
102 return bprintf("%.1f%s%s", scaled, prefix[i], unit);
103 }
104
105 const char *
106 fmt_human_10(size_t num, char *unit)
107 {
108 size_t i;
109 double scaled;
110 const char *prefix[] = { "", "K", "M", "G", "T", "P", "E",
111 "Z", "Y" };
112
113 scaled = num;
114 for (i = 0; i < LEN(prefix) && scaled >= 1000; i++) {
115 scaled /= 1000.0;
116 }
117
118 return bprintf("%.1f%s%s", scaled, prefix[i], unit);
119 }
120
121 int
122 pscanf(const char *path, const char *fmt, ...)
123 {
124 FILE *fp;
125 va_list ap;
126 int n;
127
128 if (!(fp = fopen(path, "r"))) {
129 warn("fopen '%s':", path);
130 return -1;
131 }
132 va_start(ap, fmt);
133 n = vfscanf(fp, fmt, ap);
134 va_end(ap);
135 fclose(fp);
136
137 return (n == EOF) ? -1 : n;
138 }