rats

RAdix iniT Suite
git clone https://git.daat.foo/repos/rats.git
Log | Files | Refs | README | LICENSE

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 }