quark

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

util.c (3689B)


      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 
     20 static void
     21 verr(const char *fmt, va_list ap)
     22 {
     23 	if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
     24 		fprintf(stderr, "%s: ", argv0);
     25 	}
     26 
     27 	vfprintf(stderr, fmt, ap);
     28 
     29 	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
     30 		fputc(' ', stderr);
     31 		perror(NULL);
     32 	} else {
     33 		fputc('\n', stderr);
     34 	}
     35 }
     36 
     37 void
     38 warn(const char *fmt, ...)
     39 {
     40 	va_list ap;
     41 
     42 	va_start(ap, fmt);
     43 	verr(fmt, ap);
     44 	va_end(ap);
     45 }
     46 
     47 void
     48 die(const char *fmt, ...)
     49 {
     50 	va_list ap;
     51 
     52 	va_start(ap, fmt);
     53 	verr(fmt, ap);
     54 	va_end(ap);
     55 
     56 	exit(1);
     57 }
     58 
     59 void
     60 epledge(const char *promises, const char *execpromises)
     61 {
     62 	(void)promises;
     63 	(void)execpromises;
     64 
     65 #ifdef __OpenBSD__
     66 	if (pledge(promises, execpromises) == -1) {
     67 		die("pledge:");
     68 	}
     69 #endif /* __OpenBSD__ */
     70 }
     71 
     72 void
     73 eunveil(const char *path, const char *permissions)
     74 {
     75 	(void)path;
     76 	(void)permissions;
     77 
     78 #ifdef __OpenBSD__
     79 	if (unveil(path, permissions) == -1) {
     80 		die("unveil:");
     81 	}
     82 #endif /* __OpenBSD__ */
     83 }
     84 
     85 int
     86 timestamp(char *buf, size_t len, time_t t)
     87 {
     88 	struct tm tm;
     89 
     90 	if (gmtime_r(&t, &tm) == NULL ||
     91 	    strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
     92 		return 1;
     93 	}
     94 
     95 	return 0;
     96 }
     97 
     98 int
     99 esnprintf(char *str, size_t size, const char *fmt, ...)
    100 {
    101 	va_list ap;
    102 	int ret;
    103 
    104 	va_start(ap, fmt);
    105 	ret = vsnprintf(str, size, fmt, ap);
    106 	va_end(ap);
    107 
    108 	return (ret < 0 || (size_t)ret >= size);
    109 }
    110 
    111 int
    112 prepend(char *str, size_t size, const char *prefix)
    113 {
    114 	size_t len = strlen(str), prefixlen = strlen(prefix);
    115 
    116 	if (len + prefixlen + 1 > size) {
    117 		return 1;
    118 	}
    119 
    120 	memmove(str + prefixlen, str, len + 1);
    121 	memcpy(str, prefix, prefixlen);
    122 
    123 	return 0;
    124 }
    125 
    126 #define	INVALID  1
    127 #define	TOOSMALL 2
    128 #define	TOOLARGE 3
    129 
    130 long long
    131 strtonum(const char *numstr, long long minval, long long maxval,
    132          const char **errstrp)
    133 {
    134 	long long ll = 0;
    135 	int error = 0;
    136 	char *ep;
    137 	struct errval {
    138 		const char *errstr;
    139 		int err;
    140 	} ev[4] = {
    141 		{ NULL,		0 },
    142 		{ "invalid",	EINVAL },
    143 		{ "too small",	ERANGE },
    144 		{ "too large",	ERANGE },
    145 	};
    146 
    147 	ev[0].err = errno;
    148 	errno = 0;
    149 	if (minval > maxval) {
    150 		error = INVALID;
    151 	} else {
    152 		ll = strtoll(numstr, &ep, 10);
    153 		if (numstr == ep || *ep != '\0')
    154 			error = INVALID;
    155 		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
    156 			error = TOOSMALL;
    157 		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
    158 			error = TOOLARGE;
    159 	}
    160 	if (errstrp != NULL)
    161 		*errstrp = ev[error].errstr;
    162 	errno = ev[error].err;
    163 	if (error)
    164 		ll = 0;
    165 
    166 	return ll;
    167 }
    168 
    169 /*
    170  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
    171  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
    172  */
    173 #define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
    174 
    175 void *
    176 reallocarray(void *optr, size_t nmemb, size_t size)
    177 {
    178 	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
    179 	    nmemb > 0 && SIZE_MAX / nmemb < size) {
    180 		errno = ENOMEM;
    181 		return NULL;
    182 	}
    183 	return realloc(optr, size * nmemb);
    184 }
    185 
    186 int
    187 buffer_appendf(struct buffer *buf, const char *suffixfmt, ...)
    188 {
    189 	va_list ap;
    190 	int ret;
    191 
    192 	va_start(ap, suffixfmt);
    193 	ret = vsnprintf(buf->data + buf->len,
    194 	                sizeof(buf->data) - buf->len, suffixfmt, ap);
    195 	va_end(ap);
    196 
    197 	if (ret < 0 || (size_t)ret >= (sizeof(buf->data) - buf->len)) {
    198 		/* truncation occured, discard and error out */
    199 		memset(buf->data + buf->len, 0,
    200 		       sizeof(buf->data) - buf->len);
    201 		return 1;
    202 	}
    203 
    204 	/* increase buffer length by number of bytes written */
    205 	buf->len += ret;
    206 
    207 	return 0;
    208 }