util.c (2341B)
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 if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { 17 fprintf(stderr, "%s: ", argv0); 18 } 19 20 vfprintf(stderr, fmt, ap); 21 22 if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { 23 fputc(' ', stderr); 24 perror(NULL); 25 } else { 26 fputc('\n', stderr); 27 } 28 } 29 30 void 31 warn(const char *fmt, ...) 32 { 33 va_list ap; 34 35 va_start(ap, fmt); 36 verr(fmt, ap); 37 va_end(ap); 38 } 39 40 void 41 die(const char *fmt, ...) 42 { 43 va_list ap; 44 45 va_start(ap, fmt); 46 verr(fmt, ap); 47 va_end(ap); 48 49 exit(1); 50 } 51 52 static int 53 evsnprintf(char *str, size_t size, const char *fmt, va_list ap) 54 { 55 int ret; 56 57 ret = vsnprintf(str, size, fmt, ap); 58 59 if (ret < 0) { 60 warn("vsnprintf:"); 61 return -1; 62 } else if ((size_t)ret >= size) { 63 warn("vsnprintf: Output truncated"); 64 return -1; 65 } 66 67 return ret; 68 } 69 70 int 71 esnprintf(char *str, size_t size, const char *fmt, ...) 72 { 73 va_list ap; 74 int ret; 75 76 va_start(ap, fmt); 77 ret = evsnprintf(str, size, fmt, ap); 78 va_end(ap); 79 80 return ret; 81 } 82 83 const char * 84 bprintf(const char *fmt, ...) 85 { 86 va_list ap; 87 int ret; 88 89 va_start(ap, fmt); 90 ret = evsnprintf(buf, sizeof(buf), fmt, ap); 91 va_end(ap); 92 93 return (ret < 0) ? NULL : buf; 94 } 95 96 const char * 97 fmt_human(uintmax_t num, int base) 98 { 99 double scaled; 100 size_t i, prefixlen; 101 const char **prefix; 102 const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", 103 "Y" }; 104 const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", 105 "Zi", "Yi" }; 106 107 switch (base) { 108 case 1000: 109 prefix = prefix_1000; 110 prefixlen = LEN(prefix_1000); 111 break; 112 case 1024: 113 prefix = prefix_1024; 114 prefixlen = LEN(prefix_1024); 115 break; 116 default: 117 warn("fmt_human: Invalid base"); 118 return NULL; 119 } 120 121 scaled = num; 122 for (i = 0; i < prefixlen && scaled >= base; i++) { 123 scaled /= base; 124 } 125 126 return bprintf("%.1f %s", scaled, prefix[i]); 127 } 128 129 int 130 pscanf(const char *path, const char *fmt, ...) 131 { 132 FILE *fp; 133 va_list ap; 134 int n; 135 136 if (!(fp = fopen(path, "r"))) { 137 warn("fopen '%s':", path); 138 return -1; 139 } 140 va_start(ap, fmt); 141 n = vfscanf(fp, fmt, ap); 142 va_end(ap); 143 fclose(fp); 144 145 return (n == EOF) ? -1 : n; 146 }