util.c (2301B)
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 if (num < (uintmax_t)base) 118 return bprintf("%d", (int)num); 119 120 scaled = num; 121 for (i = 0; i < prefixlen && scaled >= base; i++) 122 scaled /= base; 123 124 return bprintf("%.1f %s", scaled, prefix[i]); 125 } 126 127 int 128 pscanf(const char *path, const char *fmt, ...) 129 { 130 FILE *fp; 131 va_list ap; 132 int n; 133 134 if (!(fp = fopen(path, "r"))) { 135 warn("fopen '%s':", path); 136 return -1; 137 } 138 va_start(ap, fmt); 139 n = vfscanf(fp, fmt, ap); 140 va_end(ap); 141 fclose(fp); 142 143 return (n == EOF) ? -1 : n; 144 }