quark

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

util.c (2870B)


      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 #ifdef __OpenBSD__
     13 #include <unistd.h>
     14 #endif /* __OpenBSD__ */
     15 
     16 #include "util.h"
     17 
     18 char *argv0;
     19 struct server s;
     20 
     21 static void
     22 verr(const char *fmt, va_list ap)
     23 {
     24 	if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
     25 		fprintf(stderr, "%s: ", argv0);
     26 	}
     27 
     28 	vfprintf(stderr, fmt, ap);
     29 
     30 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
     31 		fputc(' ', stderr);
     32 		perror(NULL);
     33 	} else {
     34 		fputc('\n', stderr);
     35 	}
     36 }
     37 
     38 void
     39 warn(const char *fmt, ...)
     40 {
     41 	va_list ap;
     42 
     43 	va_start(ap, fmt);
     44 	verr(fmt, ap);
     45 	va_end(ap);
     46 }
     47 
     48 void
     49 die(const char *fmt, ...)
     50 {
     51 	va_list ap;
     52 
     53 	va_start(ap, fmt);
     54 	verr(fmt, ap);
     55 	va_end(ap);
     56 
     57 	exit(1);
     58 }
     59 
     60 void
     61 epledge(const char *promises, const char *execpromises)
     62 {
     63 	(void)promises;
     64 	(void)execpromises;
     65 
     66 #ifdef __OpenBSD__
     67 	if (pledge(promises, execpromises) == -1) {
     68 		die("pledge:");
     69 	}
     70 #endif /* __OpenBSD__ */
     71 }
     72 
     73 void
     74 eunveil(const char *path, const char *permissions)
     75 {
     76 	(void)path;
     77 	(void)permissions;
     78 
     79 #ifdef __OpenBSD__
     80 	if (unveil(path, permissions) == -1) {
     81 		die("unveil:");
     82 	}
     83 #endif /* __OpenBSD__ */
     84 }
     85 
     86 char *
     87 timestamp(time_t t, char buf[TIMESTAMP_LEN])
     88 {
     89 	strftime(buf, TIMESTAMP_LEN, "%a, %d %b %Y %T GMT", gmtime(&t));
     90 
     91 	return buf;
     92 }
     93 
     94 int
     95 esnprintf(char *str, size_t size, const char *fmt, ...)
     96 {
     97 	va_list ap;
     98 	int ret;
     99 
    100 	va_start(ap, fmt);
    101 	ret = vsnprintf(str, size, fmt, ap);
    102 	va_end(ap);
    103 
    104 	return (ret < 0 || (size_t)ret >= size);
    105 }
    106 
    107 #define	INVALID  1
    108 #define	TOOSMALL 2
    109 #define	TOOLARGE 3
    110 
    111 long long
    112 strtonum(const char *numstr, long long minval, long long maxval,
    113          const char **errstrp)
    114 {
    115 	long long ll = 0;
    116 	int error = 0;
    117 	char *ep;
    118 	struct errval {
    119 		const char *errstr;
    120 		int err;
    121 	} ev[4] = {
    122 		{ NULL,		0 },
    123 		{ "invalid",	EINVAL },
    124 		{ "too small",	ERANGE },
    125 		{ "too large",	ERANGE },
    126 	};
    127 
    128 	ev[0].err = errno;
    129 	errno = 0;
    130 	if (minval > maxval) {
    131 		error = INVALID;
    132 	} else {
    133 		ll = strtoll(numstr, &ep, 10);
    134 		if (numstr == ep || *ep != '\0')
    135 			error = INVALID;
    136 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
    137 			error = TOOSMALL;
    138 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
    139 			error = TOOLARGE;
    140 	}
    141 	if (errstrp != NULL)
    142 		*errstrp = ev[error].errstr;
    143 	errno = ev[error].err;
    144 	if (error)
    145 		ll = 0;
    146 
    147 	return ll;
    148 }
    149 
    150 /*
    151  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
    152  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
    153  */
    154 #define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
    155 
    156 void *
    157 reallocarray(void *optr, size_t nmemb, size_t size)
    158 {
    159 	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
    160 	    nmemb > 0 && SIZE_MAX / nmemb < size) {
    161 		errno = ENOMEM;
    162 		return NULL;
    163 	}
    164 	return realloc(optr, size * nmemb);
    165 }