quark

quark web server
git clone git://git.suckless.org/quark
Log | Files | Refs | LICENSE

util.c (2390B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <errno.h>
      3 #include <limits.h>
      4 #include <stdarg.h>
      5 #include <stdint.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <sys/types.h>
     10 #include <time.h>
     11 
     12 #include "util.h"
     13 
     14 char *argv0;
     15 struct server s;
     16 
     17 static void
     18 verr(const char *fmt, va_list ap)
     19 {
     20 	if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
     21 		fprintf(stderr, "%s: ", argv0);
     22 	}
     23 
     24 	vfprintf(stderr, fmt, ap);
     25 
     26 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
     27 		fputc(' ', stderr);
     28 		perror(NULL);
     29 	} else {
     30 		fputc('\n', stderr);
     31 	}
     32 }
     33 
     34 void
     35 warn(const char *fmt, ...)
     36 {
     37 	va_list ap;
     38 
     39 	va_start(ap, fmt);
     40 	verr(fmt, ap);
     41 	va_end(ap);
     42 }
     43 
     44 void
     45 die(const char *fmt, ...)
     46 {
     47 	va_list ap;
     48 
     49 	va_start(ap, fmt);
     50 	verr(fmt, ap);
     51 	va_end(ap);
     52 
     53 	exit(1);
     54 }
     55 
     56 char *
     57 timestamp(time_t t, char buf[TIMESTAMP_LEN])
     58 {
     59 	strftime(buf, TIMESTAMP_LEN, "%a, %d %b %Y %T GMT", gmtime(&t));
     60 
     61 	return buf;
     62 }
     63 
     64 int
     65 esnprintf(char *str, size_t size, const char *fmt, ...)
     66 {
     67 	va_list ap;
     68 	int ret;
     69 
     70 	va_start(ap, fmt);
     71 	ret = vsnprintf(str, size, fmt, ap);
     72 	va_end(ap);
     73 
     74 	return (ret < 0 || (size_t)ret >= size);
     75 }
     76 
     77 #define	INVALID  1
     78 #define	TOOSMALL 2
     79 #define	TOOLARGE 3
     80 
     81 long long
     82 strtonum(const char *numstr, long long minval, long long maxval,
     83          const char **errstrp)
     84 {
     85 	long long ll = 0;
     86 	int error = 0;
     87 	char *ep;
     88 	struct errval {
     89 		const char *errstr;
     90 		int err;
     91 	} ev[4] = {
     92 		{ NULL,		0 },
     93 		{ "invalid",	EINVAL },
     94 		{ "too small",	ERANGE },
     95 		{ "too large",	ERANGE },
     96 	};
     97 
     98 	ev[0].err = errno;
     99 	errno = 0;
    100 	if (minval > maxval) {
    101 		error = INVALID;
    102 	} else {
    103 		ll = strtoll(numstr, &ep, 10);
    104 		if (numstr == ep || *ep != '\0')
    105 			error = INVALID;
    106 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
    107 			error = TOOSMALL;
    108 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
    109 			error = TOOLARGE;
    110 	}
    111 	if (errstrp != NULL)
    112 		*errstrp = ev[error].errstr;
    113 	errno = ev[error].err;
    114 	if (error)
    115 		ll = 0;
    116 
    117 	return ll;
    118 }
    119 
    120 /*
    121  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
    122  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
    123  */
    124 #define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
    125 
    126 void *
    127 reallocarray(void *optr, size_t nmemb, size_t size)
    128 {
    129 	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
    130 	    nmemb > 0 && SIZE_MAX / nmemb < size) {
    131 		errno = ENOMEM;
    132 		return NULL;
    133 	}
    134 	return realloc(optr, size * nmemb);
    135 }