1*00bf802cStnn /* $NetBSD: efun.c,v 1.12 2019/10/03 20:29:19 tnn Exp $ */
26e90deb9Schristos
36e90deb9Schristos /*-
46e90deb9Schristos * Copyright (c) 2006 The NetBSD Foundation, Inc.
56e90deb9Schristos * All rights reserved.
66e90deb9Schristos *
76e90deb9Schristos * This code is derived from software contributed to The NetBSD Foundation
86e90deb9Schristos * by Christos Zoulas.
96e90deb9Schristos *
106e90deb9Schristos * Redistribution and use in source and binary forms, with or without
116e90deb9Schristos * modification, are permitted provided that the following conditions
126e90deb9Schristos * are met:
136e90deb9Schristos * 1. Redistributions of source code must retain the above copyright
146e90deb9Schristos * notice, this list of conditions and the following disclaimer.
156e90deb9Schristos * 2. Redistributions in binary form must reproduce the above copyright
166e90deb9Schristos * notice, this list of conditions and the following disclaimer in the
176e90deb9Schristos * documentation and/or other materials provided with the distribution.
186e90deb9Schristos *
196e90deb9Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206e90deb9Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216e90deb9Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226e90deb9Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236e90deb9Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246e90deb9Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256e90deb9Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266e90deb9Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276e90deb9Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286e90deb9Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296e90deb9Schristos * POSSIBILITY OF SUCH DAMAGE.
306e90deb9Schristos */
316e90deb9Schristos
32ec0bdc95Schristos #if HAVE_NBTOOL_CONFIG_H
33ec0bdc95Schristos #include "nbtool_config.h"
34ec0bdc95Schristos #endif
35ec0bdc95Schristos
366e90deb9Schristos #include <sys/cdefs.h>
37568f6f6fSchristos #ifdef __RCSID
38*00bf802cStnn __RCSID("$NetBSD: efun.c,v 1.12 2019/10/03 20:29:19 tnn Exp $");
39568f6f6fSchristos #endif
406e90deb9Schristos
416e90deb9Schristos #include <err.h>
426e90deb9Schristos #include <errno.h>
4357b77f77Schristos #include <inttypes.h>
446e90deb9Schristos #include <string.h>
456e90deb9Schristos #include <stdlib.h>
466e90deb9Schristos #include <stdio.h>
476e90deb9Schristos #include <stdarg.h>
486e90deb9Schristos #include <util.h>
496e90deb9Schristos
506e90deb9Schristos static void (*efunc)(int, const char *, ...) = err;
516e90deb9Schristos
52*00bf802cStnn static void __dead
eexit(int e,const char * fmt __unused,...)535c84fc8dSchristos eexit(int e, const char *fmt __unused, ...)
545c84fc8dSchristos {
555c84fc8dSchristos exit(e);
565c84fc8dSchristos }
575c84fc8dSchristos
586e90deb9Schristos void (*
esetfunc(void (* ef)(int,const char *,...))596e90deb9Schristos esetfunc(void (*ef)(int, const char *, ...)))(int, const char *, ...)
606e90deb9Schristos {
616e90deb9Schristos void (*of)(int, const char *, ...) = efunc;
625c84fc8dSchristos efunc = ef == NULL ? eexit : ef;
636e90deb9Schristos return of;
646e90deb9Schristos }
656e90deb9Schristos
666e90deb9Schristos size_t
estrlcpy(char * dst,const char * src,size_t len)676e90deb9Schristos estrlcpy(char *dst, const char *src, size_t len)
686e90deb9Schristos {
696e90deb9Schristos size_t rv;
706e90deb9Schristos if ((rv = strlcpy(dst, src, len)) >= len) {
716e90deb9Schristos errno = ENAMETOOLONG;
726e90deb9Schristos (*efunc)(1,
736e90deb9Schristos "Cannot copy string; %zu chars needed %zu provided",
746e90deb9Schristos rv, len);
756e90deb9Schristos }
766e90deb9Schristos return rv;
776e90deb9Schristos }
786e90deb9Schristos
796e90deb9Schristos size_t
estrlcat(char * dst,const char * src,size_t len)806e90deb9Schristos estrlcat(char *dst, const char *src, size_t len)
816e90deb9Schristos {
826e90deb9Schristos size_t rv;
836e90deb9Schristos if ((rv = strlcat(dst, src, len)) >= len) {
846e90deb9Schristos errno = ENAMETOOLONG;
856e90deb9Schristos (*efunc)(1,
866e90deb9Schristos "Cannot append to string; %zu chars needed %zu provided",
876e90deb9Schristos rv, len);
886e90deb9Schristos }
896e90deb9Schristos return rv;
906e90deb9Schristos }
916e90deb9Schristos
926e90deb9Schristos char *
estrdup(const char * s)936e90deb9Schristos estrdup(const char *s)
946e90deb9Schristos {
956e90deb9Schristos char *d = strdup(s);
966e90deb9Schristos if (d == NULL)
976e90deb9Schristos (*efunc)(1, "Cannot copy string");
986e90deb9Schristos return d;
996e90deb9Schristos }
1006e90deb9Schristos
101060d8639Spooka char *
estrndup(const char * s,size_t len)102060d8639Spooka estrndup(const char *s, size_t len)
103060d8639Spooka {
104060d8639Spooka char *d = strndup(s, len);
105060d8639Spooka if (d == NULL)
106060d8639Spooka (*efunc)(1, "Cannot copy string");
107060d8639Spooka return d;
108060d8639Spooka }
109060d8639Spooka
1106e90deb9Schristos void *
emalloc(size_t n)1116e90deb9Schristos emalloc(size_t n)
1126e90deb9Schristos {
1136e90deb9Schristos void *p = malloc(n);
1141e653dd9Sdholland if (p == NULL && n != 0)
1156e90deb9Schristos (*efunc)(1, "Cannot allocate %zu bytes", n);
1166e90deb9Schristos return p;
1176e90deb9Schristos }
1186e90deb9Schristos
1196e90deb9Schristos void *
ecalloc(size_t n,size_t s)1206e90deb9Schristos ecalloc(size_t n, size_t s)
1216e90deb9Schristos {
1226e90deb9Schristos void *p = calloc(n, s);
1231e653dd9Sdholland if (p == NULL && n != 0 && s != 0)
124cd3306d1Sdholland (*efunc)(1, "Cannot allocate %zu blocks of size %zu", n, s);
1255863dc6eSchristos return p;
1266e90deb9Schristos }
1276e90deb9Schristos
1286e90deb9Schristos void *
erealloc(void * p,size_t n)1296e90deb9Schristos erealloc(void *p, size_t n)
1306e90deb9Schristos {
1316e90deb9Schristos void *q = realloc(p, n);
1321e653dd9Sdholland if (q == NULL && n != 0)
1336e90deb9Schristos (*efunc)(1, "Cannot re-allocate %zu bytes", n);
1346e90deb9Schristos return q;
1356e90deb9Schristos }
1366e90deb9Schristos
1372cf5f6afSkamil void
ereallocarr(void * p,size_t n,size_t s)1382cf5f6afSkamil ereallocarr(void *p, size_t n, size_t s)
1392cf5f6afSkamil {
1402cf5f6afSkamil int rv = reallocarr(p, n, s);
1412cf5f6afSkamil if (rv != 0) {
1422cf5f6afSkamil errno = rv;
1432cf5f6afSkamil (*efunc)(1, "Cannot re-allocate %zu * %zu bytes", n, s);
1442cf5f6afSkamil }
1452cf5f6afSkamil }
1462cf5f6afSkamil
1476e90deb9Schristos FILE *
efopen(const char * p,const char * m)1486e90deb9Schristos efopen(const char *p, const char *m)
1496e90deb9Schristos {
1506e90deb9Schristos FILE *fp = fopen(p, m);
1516e90deb9Schristos if (fp == NULL)
1526e90deb9Schristos (*efunc)(1, "Cannot open `%s'", p);
1536e90deb9Schristos return fp;
1546e90deb9Schristos }
1556e90deb9Schristos
1566e90deb9Schristos int
easprintf(char ** __restrict ret,const char * __restrict format,...)1576e90deb9Schristos easprintf(char ** __restrict ret, const char * __restrict format, ...)
1586e90deb9Schristos {
1596e90deb9Schristos int rv;
1606e90deb9Schristos va_list ap;
1616e90deb9Schristos va_start(ap, format);
1626e90deb9Schristos if ((rv = vasprintf(ret, format, ap)) == -1)
1636e90deb9Schristos (*efunc)(1, "Cannot format string");
1646e90deb9Schristos va_end(ap);
1656e90deb9Schristos return rv;
1666e90deb9Schristos }
1676e90deb9Schristos
1686e90deb9Schristos int
evasprintf(char ** __restrict ret,const char * __restrict format,va_list ap)1696e90deb9Schristos evasprintf(char ** __restrict ret, const char * __restrict format, va_list ap)
1706e90deb9Schristos {
1716e90deb9Schristos int rv;
1726e90deb9Schristos if ((rv = vasprintf(ret, format, ap)) == -1)
1736e90deb9Schristos (*efunc)(1, "Cannot format string");
1746e90deb9Schristos return rv;
1756e90deb9Schristos }
17657b77f77Schristos
17757b77f77Schristos intmax_t
estrtoi(const char * nptr,int base,intmax_t lo,intmax_t hi)17857b77f77Schristos estrtoi(const char * nptr, int base, intmax_t lo, intmax_t hi)
17957b77f77Schristos {
18057b77f77Schristos int e;
18157b77f77Schristos intmax_t rv = strtoi(nptr, NULL, base, lo, hi, &e);
18257b77f77Schristos if (e != 0) {
18357b77f77Schristos errno = e;
18457b77f77Schristos (*efunc)(1,
18557b77f77Schristos "Cannot convert string value '%s' with base %d to a number in range [%jd .. %jd]",
18657b77f77Schristos nptr, base, lo, hi);
18757b77f77Schristos }
18857b77f77Schristos return rv;
18957b77f77Schristos }
19057b77f77Schristos
19157b77f77Schristos uintmax_t
estrtou(const char * nptr,int base,uintmax_t lo,uintmax_t hi)19257b77f77Schristos estrtou(const char * nptr, int base, uintmax_t lo, uintmax_t hi)
19357b77f77Schristos {
19457b77f77Schristos int e;
19557b77f77Schristos uintmax_t rv = strtou(nptr, NULL, base, lo, hi, &e);
19657b77f77Schristos if (e != 0) {
19757b77f77Schristos errno = e;
19857b77f77Schristos (*efunc)(1,
19957b77f77Schristos "Cannot convert string value '%s' with base %d to a number in range [%ju .. %ju]",
20057b77f77Schristos nptr, base, lo, hi);
20157b77f77Schristos }
20257b77f77Schristos return rv;
20357b77f77Schristos }
204