util.c (2548B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <X11/Xlib.h> 3 #include <errno.h> 4 #include <stdarg.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include "util.h" 11 12 char *argv0; 13 static Display *dpy = NULL; 14 15 static void 16 verr(const char *fmt, va_list ap) 17 { 18 if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { 19 fprintf(stderr, "%s: ", argv0); 20 } 21 22 vfprintf(stderr, fmt, ap); 23 24 if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { 25 fputc(' ', stderr); 26 perror(NULL); 27 } else { 28 fputc('\n', stderr); 29 } 30 } 31 32 void 33 warn(const char *fmt, ...) 34 { 35 va_list ap; 36 37 va_start(ap, fmt); 38 verr(fmt, ap); 39 va_end(ap); 40 } 41 42 void 43 die(const char *fmt, ...) 44 { 45 va_list ap; 46 47 va_start(ap, fmt); 48 verr(fmt, ap); 49 va_end(ap); 50 51 exit(1); 52 } 53 54 int 55 evsnprintf(char *str, size_t size, const char *fmt, va_list ap) 56 { 57 int ret; 58 59 ret = vsnprintf(str, size, fmt, ap); 60 61 if (ret < 0) { 62 warn("vsnprintf:"); 63 return -1; 64 } else if ((size_t)ret >= size) { 65 warn("vsnprintf: Output truncated"); 66 return -1; 67 } 68 69 return ret; 70 } 71 72 int 73 esnprintf(char *str, size_t size, const char *fmt, ...) 74 { 75 va_list ap; 76 int ret; 77 78 va_start(ap, fmt); 79 ret = evsnprintf(str, size, fmt, ap); 80 va_end(ap); 81 82 return ret; 83 } 84 85 const char * 86 bprintf(const char *fmt, ...) 87 { 88 va_list ap; 89 int ret; 90 91 va_start(ap, fmt); 92 ret = evsnprintf(buf, sizeof(buf), fmt, ap); 93 va_end(ap); 94 95 return (ret < 0) ? NULL : buf; 96 } 97 98 const char * 99 fmt_human(uintmax_t num, int base) 100 { 101 double scaled; 102 size_t i, prefixlen; 103 const char **prefix; 104 const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", 105 "Y" }; 106 const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", 107 "Zi", "Yi" }; 108 109 switch (base) { 110 case 1000: 111 prefix = prefix_1000; 112 prefixlen = LEN(prefix_1000); 113 break; 114 case 1024: 115 prefix = prefix_1024; 116 prefixlen = LEN(prefix_1024); 117 break; 118 default: 119 warn("fmt_human: Invalid base"); 120 return NULL; 121 } 122 123 scaled = num; 124 for (i = 0; i < prefixlen && scaled >= base; i++) { 125 scaled /= base; 126 } 127 128 return bprintf("%.1f %s", scaled, prefix[i]); 129 } 130 131 int 132 pscanf(const char *path, const char *fmt, ...) 133 { 134 FILE *fp; 135 va_list ap; 136 int n; 137 138 if (!(fp = fopen(path, "r"))) { 139 warn("fopen '%s':", path); 140 return -1; 141 } 142 va_start(ap, fmt); 143 n = vfscanf(fp, fmt, ap); 144 va_end(ap); 145 fclose(fp); 146 147 return (n == EOF) ? -1 : n; 148 } 149 150 Display * 151 getdisplay(void) 152 { 153 if (dpy) 154 return dpy; 155 return dpy = XOpenDisplay(NULL); 156 } 157 158 void 159 closedisplay(void) 160 { 161 if (dpy) 162 XCloseDisplay(dpy); 163 dpy = NULL; 164 }