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}