util.c (5518B)
1 /* Repackaged small subset of libutil/%.c to one util.c */ 2 3 #ifndef _POSIX_C_SOURCE 4 #define _POSIX_C_SOURCE 200809L 5 #endif 6 7 #include "util.h" 8 9 #include <errno.h> 10 #include <limits.h> 11 #include <stdarg.h> 12 #include <stdint.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 18 char *argv0 = "origo"; 19 20 void 21 xvprintf(const char *fmt, va_list ap) 22 { 23 if (argv0 && strncmp(fmt, "usage", strlen("usage"))) 24 fprintf(stderr, "%s: ", argv0); 25 26 vfprintf(stderr, fmt, ap); 27 28 if (fmt[0] && fmt[strlen(fmt)-1] == ':') { 29 fputc(' ', stderr); 30 perror(NULL); 31 } 32 } 33 34 void 35 eprintf(const char *fmt, ...) 36 { 37 va_list ap; 38 39 va_start(ap, fmt); 40 xvprintf(fmt, ap); 41 va_end(ap); 42 43 exit(1); 44 } 45 46 void 47 weprintf(const char *fmt, ...) 48 { 49 va_list ap; 50 51 va_start(ap, fmt); 52 xvprintf(fmt, ap); 53 va_end(ap); 54 } 55 56 void 57 enprintf(int status, const char *fmt, ...) 58 { 59 va_list ap; 60 61 va_start(ap, fmt); 62 xvprintf(fmt, ap); 63 va_end(ap); 64 65 exit(status); 66 } 67 68 69 void * 70 enmalloc(int status, size_t size) 71 { 72 void *p; 73 74 p = malloc(size); 75 if (!p) 76 enprintf(status, "malloc: out of memory\n"); 77 return p; 78 } 79 80 void * 81 emalloc(size_t size) 82 { 83 return enmalloc(1, size); 84 } 85 86 void * 87 encalloc(int status, size_t nmemb, size_t size) 88 { 89 void *p; 90 91 p = calloc(nmemb, size); 92 if (!p) 93 enprintf(status, "calloc: out of memory\n"); 94 return p; 95 } 96 97 void * 98 ecalloc(size_t nmemb, size_t size) 99 { 100 return encalloc(1, nmemb, size); 101 } 102 103 void * 104 enrealloc(int status, void *p, size_t size) 105 { 106 p = realloc(p, size); 107 if (!p) 108 enprintf(status, "realloc: out of memory\n"); 109 return p; 110 } 111 112 void * 113 reallocarray(void *optr, size_t nmemb, size_t size) 114 { 115 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && 116 nmemb > 0 && SIZE_MAX / nmemb < size) { 117 errno = ENOMEM; 118 return NULL; 119 } 120 return realloc(optr, size * nmemb); 121 } 122 123 void * 124 erealloc(void *p, size_t size) 125 { 126 return enrealloc(1, p, size); 127 } 128 129 void * 130 enreallocarray(int status, void *optr, size_t nmemb, size_t size) 131 { 132 void *p; 133 134 if (!(p = reallocarray(optr, nmemb, size))) 135 enprintf(status, "reallocarray: out of memory\n"); 136 137 return p; 138 } 139 140 void * 141 ereallocarray(void *optr, size_t nmemb, size_t size) 142 { 143 return enreallocarray(1, optr, nmemb, size); 144 } 145 146 char * 147 enstrdup(int status, const char *s) 148 { 149 char *p; 150 151 p = strdup(s); 152 if (!p) 153 enprintf(status, "strdup: out of memory\n"); 154 return p; 155 } 156 157 char * 158 estrdup(const char *s) 159 { 160 return enstrdup(1, s); 161 } 162 163 char * 164 enstrndup(int status, const char *s, size_t n) 165 { 166 char *p; 167 168 p = strndup(s, n); 169 if (!p) 170 enprintf(status, "strndup: out of memory\n"); 171 return p; 172 } 173 174 size_t 175 strlcpy(char *dst, const char *src, size_t siz) 176 { 177 char *d = dst; 178 const char *s = src; 179 size_t n = siz; 180 /* Copy as many bytes as will fit */ 181 if (n != 0) { 182 while (--n != 0) { 183 if ((*d++ = *s++) == '\0') 184 break; 185 } 186 } 187 if (n == 0) { 188 if (siz != 0) 189 *d = '\0'; /* NUL-terminate dst */ 190 while (*s++) 191 ; 192 } 193 return(s - src - 1); /* count does not include NUL */ 194 } 195 196 197 size_t 198 strlcat(char *dst, const char *src, size_t siz) 199 { 200 char *d = dst; 201 const char *s = src; 202 size_t n = siz; 203 size_t dlen; 204 /* Find the end of dst and adjust bytes left but don't go past end */ 205 while (n-- != 0 && *d != '\0') 206 d++; 207 dlen = d - dst; 208 n = siz - dlen; 209 if (n == 0) 210 return(dlen + strlen(s)); 211 while (*s != '\0') { 212 if (n != 1) { 213 *d++ = *s; 214 n--; 215 } 216 s++; 217 } 218 *d = '\0'; 219 return(dlen + (s - src)); /* count does not include NUL */ 220 } 221 222 #define INVALID 1 223 #define TOOSMALL 2 224 #define TOOLARGE 3 225 226 long long 227 strtonum(const char *numstr, long long minval, long long maxval, 228 const char **errstrp) 229 { 230 long long ll = 0; 231 int error = 0; 232 char *ep; 233 struct errval { 234 const char *errstr; 235 int err; 236 } ev[4] = { 237 { NULL, 0 }, 238 { "invalid", EINVAL }, 239 { "too small", ERANGE }, 240 { "too large", ERANGE }, 241 }; 242 243 ev[0].err = errno; 244 errno = 0; 245 if (minval > maxval) { 246 error = INVALID; 247 } else { 248 ll = strtoll(numstr, &ep, 10); 249 if (numstr == ep || *ep != '\0') 250 error = INVALID; 251 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) 252 error = TOOSMALL; 253 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) 254 error = TOOLARGE; 255 } 256 if (errstrp != NULL) 257 *errstrp = ev[error].errstr; 258 errno = ev[error].err; 259 if (error) 260 ll = 0; 261 262 return (ll); 263 } 264 265 long long 266 enstrtonum(int status, const char *numstr, long long minval, long long maxval) 267 { 268 const char *errstr; 269 long long ll; 270 271 ll = strtonum(numstr, minval, maxval, &errstr); 272 if (errstr) 273 enprintf(status, "strtonum %s: %s\n", numstr, errstr); 274 return ll; 275 } 276 277 long long 278 estrtonum(const char *numstr, long long minval, long long maxval) 279 { 280 return enstrtonum(1, numstr, minval, maxval); 281 } 282 283 ssize_t 284 writeall(int fd, const void *buf, size_t len) 285 { 286 const char *p = buf; 287 ssize_t n; 288 289 while (len) { 290 n = write(fd, p, len); 291 if (n < 0 && errno == EINTR) 292 continue; 293 if (n <= 0) 294 return n; 295 p += n; 296 len -= n; 297 } 298 299 return p - (const char *)buf; 300 } 301 302 int 303 fshut(FILE *fp, const char *fname) 304 { 305 int ret = 0; 306 307 /* fflush() is undefined for input streams by ISO C, 308 * but not POSIX 2008 if you ignore ISO C overrides. 309 * Leave it unchecked and rely on the following 310 * functions to detect errors. 311 */ 312 fflush(fp); 313 314 if (ferror(fp) && !ret) { 315 weprintf("ferror %s:", fname); 316 ret = 1; 317 } 318 319 if (fclose(fp) && !ret) { 320 weprintf("fclose %s:", fname); 321 ret = 1; 322 } 323 324 return ret; 325 }