summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.in53
-rw-r--r--src/format.c73
-rw-r--r--src/internal.h2
-rw-r--r--src/io.c51
-rw-r--r--src/libHX.map9
-rw-r--r--src/map.c5
-rw-r--r--src/mc.c29
-rw-r--r--src/opt.c46
-rw-r--r--src/socket.c183
-rw-r--r--src/string.c73
-rw-r--r--src/tc-cast.c9
-rw-r--r--src/tc-dir.c8
-rw-r--r--src/tc-format.c24
-rw-r--r--src/tc-io.c1
-rw-r--r--src/tc-list.c8
-rw-r--r--src/tc-list2.c8
-rw-r--r--src/tc-map.c9
-rw-r--r--src/tc-memmem.c6
-rw-r--r--src/tc-misc.c11
-rw-r--r--src/tc-netio.c8
-rw-r--r--src/tc-option.c7
-rw-r--r--src/tc-proc.c8
-rw-r--r--src/tc-rand.c8
-rw-r--r--src/tc-realpath.c6
-rw-r--r--src/tc-shconfig.c6
-rw-r--r--src/tc-socket.c31
-rw-r--r--src/tc-strchr2.c6
-rw-r--r--src/tc-string.c40
-rw-r--r--src/tc-strquote.c6
-rw-r--r--src/tc-switchuser.c15
-rw-r--r--src/tc-time.c10
-rw-r--r--src/tc-xml.c8
34 files changed, 515 insertions, 260 deletions
diff --git a/src/.gitignore b/src/.gitignore
index 035dc34..89edb97 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -19,6 +19,7 @@
/t?-rand
/t?-realpath
/t?-shconfig
+/t?-socket
/t?-strchr2
/t?-string
/t?-strquote
diff --git a/src/Makefile.am b/src/Makefile.am
index c30b56c..921e6b7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,7 @@ libHX_la_SOURCES = deque.c dl.c format.c io.c map.c \
mc.c misc.c opt.c proc.c \
rand.c socket.c string.c time.c
libHX_la_LIBADD = ${libdl_LIBS} -lm ${libpthread_LIBS} ${librt_LIBS}
-libHX_la_LDFLAGS = -no-undefined -version-info 35:0:3
+libHX_la_LDFLAGS = -no-undefined -version-info 36:0:4
if WITH_GNU_LD
libHX_la_LDFLAGS += -Wl,--version-script=${srcdir}/libHX.map
endif
@@ -36,9 +36,9 @@ EXTRA_DIST = internal.h map_int.h libHX.map
check_PROGRAMS = tc-compile tc-cast tc-deque tc-dir tc-format tc-io \
tc-list tc-list2 tc-map tc-memmem tc-misc tc-netio \
tc-option tc-proc tc-rand tc-realpath \
- tc-shconfig tc-strchr2 tc-string tc-strquote \
+ tc-shconfig tc-socket tc-strchr2 tc-string tc-strquote \
tc-switchuser tc-time
-TESTS = tc-strchr2 tc-strquote
+TESTS = tc-format tc-strchr2 tc-strquote
tc_cast_CFLAGS = ${AM_CFLAGS} -std=gnu99
tc_cast_LDADD = libHX.la -lm
tc_compile_LDADD = libHX.la
@@ -57,6 +57,7 @@ tc_proc_LDADD = libHX.la
tc_rand_LDADD = libHX.la
tc_realpath_LDADD = libHX.la
tc_shconfig_LDADD = libHX.la
+tc_socket_LDADD = libHX.la
tc_strchr2_LDADD = libHX.la
tc_string_LDADD = libHX.la
tc_strquote_LDADD = libHX.la
diff --git a/src/Makefile.in b/src/Makefile.in
index 356dcfe..8257e20 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -101,9 +101,11 @@ check_PROGRAMS = tc-compile$(EXEEXT) tc-cast$(EXEEXT) \
tc-map$(EXEEXT) tc-memmem$(EXEEXT) tc-misc$(EXEEXT) \
tc-netio$(EXEEXT) tc-option$(EXEEXT) tc-proc$(EXEEXT) \
tc-rand$(EXEEXT) tc-realpath$(EXEEXT) tc-shconfig$(EXEEXT) \
- tc-strchr2$(EXEEXT) tc-string$(EXEEXT) tc-strquote$(EXEEXT) \
- tc-switchuser$(EXEEXT) tc-time$(EXEEXT) $(am__EXEEXT_1)
-TESTS = tc-strchr2$(EXEEXT) tc-strquote$(EXEEXT) $(am__EXEEXT_2)
+ tc-socket$(EXEEXT) tc-strchr2$(EXEEXT) tc-string$(EXEEXT) \
+ tc-strquote$(EXEEXT) tc-switchuser$(EXEEXT) tc-time$(EXEEXT) \
+ $(am__EXEEXT_1)
+TESTS = tc-format$(EXEEXT) tc-strchr2$(EXEEXT) tc-strquote$(EXEEXT) \
+ $(am__EXEEXT_2)
@HAVE_CXX_TRUE@am__append_6 = tx-compile tx-cast tx-deque tx-dir \
@HAVE_CXX_TRUE@ tx-intdiff tx-list tx-list2 \
@HAVE_CXX_TRUE@ tx-misc tx-netio \
@@ -244,6 +246,9 @@ tc_realpath_DEPENDENCIES = libHX.la
tc_shconfig_SOURCES = tc-shconfig.c
tc_shconfig_OBJECTS = tc-shconfig.$(OBJEXT)
tc_shconfig_DEPENDENCIES = libHX.la
+tc_socket_SOURCES = tc-socket.c
+tc_socket_OBJECTS = tc-socket.$(OBJEXT)
+tc_socket_DEPENDENCIES = libHX.la
tc_strchr2_SOURCES = tc-strchr2.c
tc_strchr2_OBJECTS = tc-strchr2.$(OBJEXT)
tc_strchr2_DEPENDENCIES = libHX.la
@@ -354,9 +359,10 @@ am__depfiles_remade = ./$(DEPDIR)/deque.Plo ./$(DEPDIR)/dl.Plo \
./$(DEPDIR)/tc-netio.Po ./$(DEPDIR)/tc-option.Po \
./$(DEPDIR)/tc-proc.Po ./$(DEPDIR)/tc-rand.Po \
./$(DEPDIR)/tc-realpath.Po ./$(DEPDIR)/tc-shconfig.Po \
- ./$(DEPDIR)/tc-strchr2.Po ./$(DEPDIR)/tc-string.Po \
- ./$(DEPDIR)/tc-strquote.Po ./$(DEPDIR)/tc-switchuser.Po \
- ./$(DEPDIR)/tc-time.Po ./$(DEPDIR)/tc_cast-tc-cast.Po \
+ ./$(DEPDIR)/tc-socket.Po ./$(DEPDIR)/tc-strchr2.Po \
+ ./$(DEPDIR)/tc-string.Po ./$(DEPDIR)/tc-strquote.Po \
+ ./$(DEPDIR)/tc-switchuser.Po ./$(DEPDIR)/tc-time.Po \
+ ./$(DEPDIR)/tc_cast-tc-cast.Po \
./$(DEPDIR)/tc_list2-tc-list2.Po ./$(DEPDIR)/time.Plo \
./$(DEPDIR)/tx-cast.Po ./$(DEPDIR)/tx-compile.Po \
./$(DEPDIR)/tx-deque.Po ./$(DEPDIR)/tx-dir.Po \
@@ -408,19 +414,19 @@ SOURCES = $(libHX_la_SOURCES) $(libHX_rtcheck_la_SOURCES) tc-cast.c \
tc-compile.c tc-deque.c tc-dir.c tc-format.c tc-io.c tc-list.c \
tc-list2.c tc-map.c tc-memmem.c tc-misc.c tc-netio.c \
tc-option.c tc-proc.c tc-rand.c tc-realpath.c tc-shconfig.c \
- tc-strchr2.c tc-string.c tc-strquote.c tc-switchuser.c \
- tc-time.c $(tx_cast_SOURCES) $(tx_compile_SOURCES) \
- $(tx_deque_SOURCES) $(tx_dir_SOURCES) $(tx_intdiff_SOURCES) \
- $(tx_list_SOURCES) $(tx_list2_SOURCES) $(tx_misc_SOURCES) \
- $(tx_netio_SOURCES) $(tx_option_SOURCES) $(tx_proc_SOURCES) \
- $(tx_rand_SOURCES) $(tx_strchr2_SOURCES) $(tx_string_SOURCES) \
- $(tx_strquote_SOURCES) $(tx_time_SOURCES)
+ tc-socket.c tc-strchr2.c tc-string.c tc-strquote.c \
+ tc-switchuser.c tc-time.c $(tx_cast_SOURCES) \
+ $(tx_compile_SOURCES) $(tx_deque_SOURCES) $(tx_dir_SOURCES) \
+ $(tx_intdiff_SOURCES) $(tx_list_SOURCES) $(tx_list2_SOURCES) \
+ $(tx_misc_SOURCES) $(tx_netio_SOURCES) $(tx_option_SOURCES) \
+ $(tx_proc_SOURCES) $(tx_rand_SOURCES) $(tx_strchr2_SOURCES) \
+ $(tx_string_SOURCES) $(tx_strquote_SOURCES) $(tx_time_SOURCES)
DIST_SOURCES = $(am__libHX_la_SOURCES_DIST) \
$(libHX_rtcheck_la_SOURCES) tc-cast.c tc-compile.c tc-deque.c \
tc-dir.c tc-format.c tc-io.c tc-list.c tc-list2.c tc-map.c \
tc-memmem.c tc-misc.c tc-netio.c tc-option.c tc-proc.c \
- tc-rand.c tc-realpath.c tc-shconfig.c tc-strchr2.c tc-string.c \
- tc-strquote.c tc-switchuser.c tc-time.c \
+ tc-rand.c tc-realpath.c tc-shconfig.c tc-socket.c tc-strchr2.c \
+ tc-string.c tc-strquote.c tc-switchuser.c tc-time.c \
$(am__tx_cast_SOURCES_DIST) $(am__tx_compile_SOURCES_DIST) \
$(am__tx_deque_SOURCES_DIST) $(am__tx_dir_SOURCES_DIST) \
$(am__tx_intdiff_SOURCES_DIST) $(am__tx_list_SOURCES_DIST) \
@@ -774,7 +780,7 @@ libHX_la_SOURCES = deque.c dl.c format.c io.c map.c mc.c misc.c opt.c \
proc.c rand.c socket.c string.c time.c $(am__append_3)
libHX_la_LIBADD = ${libdl_LIBS} -lm ${libpthread_LIBS} ${librt_LIBS} \
$(am__append_4)
-libHX_la_LDFLAGS = -no-undefined -version-info 35:0:3 $(am__append_2)
+libHX_la_LDFLAGS = -no-undefined -version-info 36:0:4 $(am__append_2)
EXTRA_libHX_la_DEPENDENCIES = libHX.map
libHX_rtcheck_la_SOURCES = rtcheck.c
libHX_rtcheck_la_LIBADD = ${libdl_LIBS}
@@ -799,6 +805,7 @@ tc_proc_LDADD = libHX.la
tc_rand_LDADD = libHX.la
tc_realpath_LDADD = libHX.la
tc_shconfig_LDADD = libHX.la
+tc_socket_LDADD = libHX.la
tc_strchr2_LDADD = libHX.la
tc_string_LDADD = libHX.la
tc_strquote_LDADD = libHX.la
@@ -987,6 +994,10 @@ tc-shconfig$(EXEEXT): $(tc_shconfig_OBJECTS) $(tc_shconfig_DEPENDENCIES) $(EXTRA
@rm -f tc-shconfig$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tc_shconfig_OBJECTS) $(tc_shconfig_LDADD) $(LIBS)
+tc-socket$(EXEEXT): $(tc_socket_OBJECTS) $(tc_socket_DEPENDENCIES) $(EXTRA_tc_socket_DEPENDENCIES)
+ @rm -f tc-socket$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(tc_socket_OBJECTS) $(tc_socket_LDADD) $(LIBS)
+
tc-strchr2$(EXEEXT): $(tc_strchr2_OBJECTS) $(tc_strchr2_DEPENDENCIES) $(EXTRA_tc_strchr2_DEPENDENCIES)
@rm -f tc-strchr2$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(tc_strchr2_OBJECTS) $(tc_strchr2_LDADD) $(LIBS)
@@ -1105,6 +1116,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-rand.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-realpath.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-shconfig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-socket.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-strchr2.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-string.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-strquote.Po@am__quote@ # am--include-marker
@@ -1427,6 +1439,13 @@ recheck: all $(check_PROGRAMS)
am__force_recheck=am--force-recheck \
TEST_LOGS="$$log_list"; \
exit $$?
+tc-format.log: tc-format$(EXEEXT)
+ @p='tc-format$(EXEEXT)'; \
+ b='tc-format'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
tc-strchr2.log: tc-strchr2$(EXEEXT)
@p='tc-strchr2$(EXEEXT)'; \
b='tc-strchr2'; \
@@ -1580,6 +1599,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/tc-rand.Po
-rm -f ./$(DEPDIR)/tc-realpath.Po
-rm -f ./$(DEPDIR)/tc-shconfig.Po
+ -rm -f ./$(DEPDIR)/tc-socket.Po
-rm -f ./$(DEPDIR)/tc-strchr2.Po
-rm -f ./$(DEPDIR)/tc-string.Po
-rm -f ./$(DEPDIR)/tc-strquote.Po
@@ -1679,6 +1699,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/tc-rand.Po
-rm -f ./$(DEPDIR)/tc-realpath.Po
-rm -f ./$(DEPDIR)/tc-shconfig.Po
+ -rm -f ./$(DEPDIR)/tc-socket.Po
-rm -f ./$(DEPDIR)/tc-strchr2.Po
-rm -f ./$(DEPDIR)/tc-string.Po
-rm -f ./$(DEPDIR)/tc-strquote.Po
diff --git a/src/format.c b/src/format.c
index b691dc7..25c09d6 100644
--- a/src/format.c
+++ b/src/format.c
@@ -16,6 +16,12 @@
#include <unistd.h>
#include <libHX.h>
#include "internal.h"
+#undef HXformat_aprintf
+#undef HXformat_fprintf
+#undef HXformat_sprintf
+extern int HXformat_aprintf(const struct HXformat_map *, hxmc_t **, const char *);
+extern int HXformat_sprintf(const struct HXformat_map *, char *, size_t, const char *);
+extern int HXformat_fprintf(const struct HXformat_map *, FILE *, const char *);
/* To make it easier on the highlighter */
#define C_OPEN '('
@@ -97,6 +103,7 @@ static void *func_entry_clone(const void *data, size_t size)
static const struct HXmap_ops func_entry_ops = {
.d_clone = func_entry_clone,
+ .d_free = free,
};
EXPORT_SYMBOL void HXformat_free(struct HXformat_map *blk)
@@ -297,7 +304,6 @@ static hxmc_t *HXformat2_snl(int argc, const hxmc_t *const *argv,
static hxmc_t *HXformat2_substr(int argc, const hxmc_t *const *argv,
const struct HXformat_map *blk)
{
- ssize_t offset, length, z;
hxmc_t *ret;
char *end;
@@ -306,44 +312,27 @@ static hxmc_t *HXformat2_substr(int argc, const hxmc_t *const *argv,
return &HXformat2_nexp;
}
- offset = strtoll(argv[1], &end, 0);
+ long w = LONG_MAX, v = strtol(argv[1], &end, 0);
if (*end != '\0') {
fprintf(stderr, "HXformat2-substr: found garbage in "
"offset specification\n");
return &HXformat2_nexp;
}
-
- z = strlen(argv[0]);
- if (offset < 0)
- offset = z + offset;
- if (offset >= z)
- return &HXformat2_nexp;
-
- if (argc == 2) {
- if (offset < 0)
- offset = 0;
- length = z - offset;
- } else {
- length = strtoll(argv[2], &end, 0);
+ if (argc >= 3) {
+ w = strtol(argv[2], &end, 0);
if (*end != '\0') {
fprintf(stderr, "HXformat2-substr; found garbage in "
"length specification\n");
return &HXformat2_nexp;
}
- if (length < 0)
- length/*end*/ = z + length;
- else
- length/*end*/ = offset + length;
- if (offset < 0)
- offset = 0;
}
- if (length <= 0)
+ size_t start = 0, tocopy = HX_substr_helper(strlen(argv[0]), v, w, &start);
+ if (tocopy == 0)
return &HXformat2_nexp;
-
- ret = HXmc_meminit(NULL, length);
+ ret = HXmc_meminit(NULL, tocopy);
if (ret == NULL)
return &HXformat2_nexp;
- if (HXmc_memcpy(&ret, &argv[0][offset], length) == NULL) {
+ if (HXmc_memcpy(&ret, &argv[0][start], tocopy) == NULL) {
HXmc_free(ret);
return &HXformat2_nexp;
}
@@ -643,6 +632,13 @@ EXPORT_SYMBOL struct HXformat_map *HXformat_init(void)
EXPORT_SYMBOL int HXformat_aprintf(const struct HXformat_map *blk,
hxmc_t **resultp, const char *fmt)
{
+ ssize_t ret = HXformat3_aprintf(blk, resultp, fmt);
+ return ret > INT_MAX ? INT_MAX : ret;
+}
+
+EXPORT_SYMBOL ssize_t HXformat3_aprintf(const struct HXformat_map *blk,
+ hxmc_t **resultp, const char *fmt)
+{
hxmc_t *ex, *ts, *out;
const char *current;
int ret = 0;
@@ -679,7 +675,8 @@ EXPORT_SYMBOL int HXformat_aprintf(const struct HXformat_map *blk,
}
*resultp = out;
- return HXmc_length(out);
+ size_t xl = HXmc_length(out);
+ return xl > SSIZE_MAX ? SSIZE_MAX : xl;
out:
ret = -errno;
@@ -690,10 +687,17 @@ EXPORT_SYMBOL int HXformat_aprintf(const struct HXformat_map *blk,
EXPORT_SYMBOL int HXformat_fprintf(const struct HXformat_map *ftable,
FILE *filp, const char *fmt)
{
+ ssize_t ret = HXformat3_fprintf(ftable, filp, fmt);
+ return ret > INT_MAX ? INT_MAX : ret;
+}
+
+EXPORT_SYMBOL ssize_t HXformat3_fprintf(const struct HXformat_map *ftable,
+ FILE *filp, const char *fmt)
+{
hxmc_t *str;
- int ret;
+ ssize_t ret;
- if ((ret = HXformat_aprintf(ftable, &str, fmt)) <= 0)
+ if ((ret = HXformat3_aprintf(ftable, &str, fmt)) <= 0)
return ret;
errno = 0;
if (fputs(str, filp) < 0)
@@ -705,8 +709,15 @@ EXPORT_SYMBOL int HXformat_fprintf(const struct HXformat_map *ftable,
EXPORT_SYMBOL int HXformat_sprintf(const struct HXformat_map *ftable,
char *dest, size_t size, const char *fmt)
{
+ ssize_t ret = HXformat3_sprintf(ftable, dest, size, fmt);
+ return ret > INT_MAX ? INT_MAX : ret;
+}
+
+EXPORT_SYMBOL ssize_t HXformat3_sprintf(const struct HXformat_map *ftable,
+ char *dest, size_t size, const char *fmt)
+{
hxmc_t *str;
- int ret;
+ ssize_t ret;
if ((ret = HXformat_aprintf(ftable, &str, fmt)) < 0)
return ret;
@@ -715,7 +726,7 @@ EXPORT_SYMBOL int HXformat_sprintf(const struct HXformat_map *ftable,
return 0;
}
strncpy(dest, str, size);
- ret = HXmc_length(dest);
+ size_t xl = strlen(dest);
HXmc_free(str);
- return ret;
+ return xl > SSIZE_MAX ? SSIZE_MAX : xl;
}
diff --git a/src/internal.h b/src/internal.h
index ec60817..0465d81 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -10,6 +10,7 @@
#define LIBHX_INTERNAL_H 1
#include "config.h"
+#include <stdint.h>
#include <libHX/defs.h>
#include <libHX/string.h>
@@ -56,5 +57,6 @@ struct timespec;
struct timeval;
extern hxmc_t *HXparse_dequote_fmt(const char *, const char *, const char **);
+extern size_t HX_substr_helper(size_t, long, long, size_t *);
#endif /* LIBHX_INTERNAL_H */
diff --git a/src/io.c b/src/io.c
index c797193..720a9c5 100644
--- a/src/io.c
+++ b/src/io.c
@@ -57,22 +57,23 @@ struct HXdir {
static int mkdir_gen(const char *d, unsigned int mode)
{
struct stat sb;
- if (lstat(d, &sb) < 0) {
#if defined(_WIN32)
- if (mkdir(d) < 0)
+ if (mkdir(d) == 0)
#else
- if (mkdir(d, mode) < 0) /* use umask() for permissions */
+ if (mkdir(d, mode) == 0) /* use umask() for permissions */
#endif
- return -errno;
- } else {
+ return 1;
+ if (errno != EEXIST)
+ return -errno;
+ if (lstat(d, &sb) == 0) {
#if defined(_WIN32)
- if ((sb.st_mode & S_IFDIR) != S_IFDIR)
+ if (sb.st_mode & S_IFDIR)
#else
- if (!S_ISDIR(sb.st_mode))
+ if (S_ISDIR(sb.st_mode))
#endif
- return -errno;
+ return 0;
}
- return 1;
+ return -EEXIST;
}
EXPORT_SYMBOL struct HXdir *HXdir_open(const char *s)
@@ -204,6 +205,8 @@ EXPORT_SYMBOL int HX_copy_file(const char *src, const char *dest,
unlink(dest);
close(dstfd);
close(srcfd);
+ free(buf);
+ va_end(argp);
return -(errno = saved_errno);
}
uid = sb.st_uid;
@@ -216,6 +219,8 @@ EXPORT_SYMBOL int HX_copy_file(const char *src, const char *dest,
unlink(dest);
close(dstfd);
close(srcfd);
+ free(buf);
+ va_end(argp);
return -(errno = saved_errno);
}
va_end(argp);
@@ -229,6 +234,7 @@ EXPORT_SYMBOL int HX_copy_file(const char *src, const char *dest,
int saved_errno = errno;
close(srcfd);
close(dstfd);
+ free(buf);
return -(errno = saved_errno);
}
}
@@ -264,8 +270,8 @@ EXPORT_SYMBOL int HX_copy_dir(const char *src, const char *dest,
continue;
snprintf(fsrc, MAXFNLEN, "%s/%s", src, fn);
snprintf(fdest, MAXFNLEN, "%s/%s", dest, fn);
-
- lstat(fsrc, &sb);
+ if (lstat(fsrc, &sb) < 0)
+ continue;
sb.st_mode &= 0777; /* clear SUID/GUID/Sticky bits */
if (S_ISREG(sb.st_mode)) {
@@ -278,17 +284,20 @@ EXPORT_SYMBOL int HX_copy_dir(const char *src, const char *dest,
memset(pt, '\0', MAXFNLEN);
if (readlink(fsrc, pt, MAXFNLEN - 1) < MAXFNLEN - 1)
if (symlink(pt, fdest) < 0)
- {};
+ /* ignore */;
} else if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
- mknod(fdest, sb.st_mode, sb.st_dev);
+ if (mknod(fdest, sb.st_mode, sb.st_dev) < 0)
+ /* ignore */;
} else if (S_ISFIFO(sb.st_mode)) {
- mkfifo(fdest, sb.st_mode);
+ if (mkfifo(fdest, sb.st_mode) < 0)
+ /* ignore */;
}
if (lchown(fdest, uid, gid) < 0)
- {};
+ /* ignore */;
if (!S_ISLNK(sb.st_mode))
- chmod(fdest, sb.st_mode);
+ if (chmod(fdest, sb.st_mode) < 0)
+ /* ignore */;
}
HXdir_close(dt);
@@ -321,12 +330,12 @@ EXPORT_SYMBOL int HX_mkdir(const char *idir, unsigned int mode)
if (dir[i] == '/') {
strncpy(buf, dir, i);
buf[i] = '\0';
- if ((v = mkdir_gen(buf, mode)) <= 0)
+ if ((v = mkdir_gen(buf, mode)) < 0)
return v;
} else if (i == len - 1) {
strncpy(buf, dir, len);
buf[len] = '\0';
- if ((v = mkdir_gen(buf, mode)) <= 0)
+ if ((v = mkdir_gen(buf, mode)) < 0)
return v;
}
}
@@ -358,7 +367,8 @@ EXPORT_SYMBOL int HX_readlink(hxmc_t **target, const char *path)
return -(errno = saved_errno);
}
if (static_cast(size_t, ret) < linkbuf_size) {
- HXmc_setlen(target, ret);
+ (*target)[ret] = '\0'; // please cov-scan
+ HXmc_setlen(target, ret); // \0 set here anyway
return ret;
}
linkbuf_size *= 2;
@@ -500,7 +510,7 @@ EXPORT_SYMBOL int HX_realpath(hxmc_t **dest_pptr, const char *path,
ret = HX_realpath_symres(&state, path);
if (ret == -EINVAL)
continue;
- else if (ret < 0)
+ else if (ret <= 0)
goto out;
path = state.path;
}
@@ -668,6 +678,7 @@ static ssize_t HX_sendfile_rw(int dst, int src, size_t count)
xferd += ret;
count -= ret;
}
+ free(buf);
if (xferd > 0)
return xferd;
if (ret < 0)
diff --git a/src/libHX.map b/src/libHX.map
index 085b74f..c4cef55 100644
--- a/src/libHX.map
+++ b/src/libHX.map
@@ -150,3 +150,12 @@ global:
HX_unit_seconds;
HX_strtoull_sec;
} LIBHX_4.2;
+
+LIBHX_4.9 {
+global:
+ HXformat3_aprintf;
+ HXformat3_fprintf;
+ HXformat3_sprintf;
+ HX_ipaddr_is_local;
+ HX_sockaddr_is_local;
+} LIBHX_4.3;
diff --git a/src/map.c b/src/map.c
index a90a731..40f376c 100644
--- a/src/map.c
+++ b/src/map.c
@@ -1304,11 +1304,12 @@ static struct HXrbnode *HXrbtrav_rewalk(struct HXrbtrav *trav)
trav->current = trav->path[--trav->depth];
if (trav->current == NULL)
fprintf(stderr, "btrav_rewalk: problem: current==NULL\n");
- HXrbtrav_checkpoint(trav, trav->current);
+ else
+ HXrbtrav_checkpoint(trav, trav->current);
}
trav->tid = btree->tid;
- if (go_next)
+ if (trav->current != nullptr && go_next)
return HXrbtrav_next(trav);
else
return trav->current;
diff --git a/src/mc.c b/src/mc.c
index d16dcbb..8bf1d95 100644
--- a/src/mc.c
+++ b/src/mc.c
@@ -8,6 +8,7 @@
* either version 2.1 or (at your option) any later version.
*/
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -20,10 +21,12 @@ static __inline__ size_t __HXmc_request(size_t len)
return sizeof(struct memcont) + len + 1;
}
-static __inline__ void HXmc_check(const struct memcont *c)
+static __inline__ int HXmc_check(const struct memcont *c)
{
- if (c->id != HXMC_IDENT)
+ int err = c->id != HXMC_IDENT;
+ if (err != 0)
fprintf(stderr, "libHX-mc error: not a hxmc object!\n");
+ return err;
}
static __inline__ struct memcont *HXmc_base(const hxmc_t *p)
@@ -61,7 +64,8 @@ EXPORT_SYMBOL hxmc_t *HXmc_memcpy(hxmc_t **vp, const void *ptr, size_t len)
struct memcont *ctx;
if (*vp != NULL) {
ctx = HXmc_base(*vp);
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return nullptr;
if (ctx->alloc < len) {
ctx = realloc(ctx, __HXmc_request(len));
if (ctx == NULL)
@@ -96,7 +100,8 @@ EXPORT_SYMBOL size_t HXmc_length(const hxmc_t *vp)
if (vp == NULL)
return 0;
ctx = HXmc_base(vp);
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return SIZE_MAX;
return ctx->length;
}
@@ -115,7 +120,8 @@ EXPORT_SYMBOL hxmc_t *HXmc_trunc(hxmc_t **vp, size_t len)
{
struct memcont *ctx = HXmc_base(*vp);
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return nullptr;
if (len > ctx->alloc) {
ctx = realloc(ctx, __HXmc_request(len));
if (ctx == NULL)
@@ -141,7 +147,8 @@ EXPORT_SYMBOL hxmc_t *HXmc_memcat(hxmc_t **vp, const void *ptr, size_t len)
struct memcont *ctx = HXmc_base(*vp);
size_t nl = ctx->length + len;
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return nullptr;
if (nl > ctx->alloc) {
ctx = realloc(ctx, __HXmc_request(nl));
if (ctx == NULL)
@@ -191,7 +198,8 @@ EXPORT_SYMBOL hxmc_t *HXmc_memins(hxmc_t **vp, size_t pos, const void *ptr,
struct memcont *ctx = HXmc_base(*vp);
size_t nl = ctx->length + len;
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return nullptr;
if (ctx->alloc < nl) {
ctx = realloc(ctx, __HXmc_request(nl));
if (ctx == NULL)
@@ -212,8 +220,8 @@ EXPORT_SYMBOL hxmc_t *HXmc_memins(hxmc_t **vp, size_t pos, const void *ptr,
EXPORT_SYMBOL hxmc_t *HXmc_memdel(hxmc_t *vp, size_t pos, size_t len)
{
struct memcont *ctx = HXmc_base(vp);
- HXmc_check(ctx);
-
+ if (HXmc_check(ctx) != 0)
+ return nullptr;
if (pos + len > ctx->length)
len = ctx->length - pos;
@@ -230,7 +238,8 @@ EXPORT_SYMBOL void HXmc_free(hxmc_t *vp)
if (vp == NULL)
return;
ctx = HXmc_base(vp);
- HXmc_check(ctx);
+ if (HXmc_check(ctx) != 0)
+ return;
free(ctx);
}
diff --git a/src/opt.c b/src/opt.c
index fe2bff3..f91785d 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -547,8 +547,12 @@ static int HX_getopt_long(const char *cur, struct HX_getopt_vars *par)
key = HX_strdup(cur);
if (key == NULL)
return -errno;
-
value = strchr(key, '=');
+ if (value == nullptr) {
+ /* Cannot happen because state is always !S_TWOLONG */
+ free(key);
+ return -EINVAL;
+ }
*value++ = '\0';
par->cbi.current = lookup_long_pfx(par->cbi.table, key + 2);
if (par->cbi.current == &HXopt_ambig_prefix) {
@@ -699,14 +703,16 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
struct HX_getopt_vars ps;
const char **opt = *argv;
int state = HXOPT_S_NORMAL;
- int ret = HXOPT_ERR_SUCCESS;
+ int ret = -ENOMEM;
unsigned int argk;
const char *cur;
memset(&ps, 0, sizeof(ps));
ps.remaining = HXdeque_init();
- if (ps.remaining == NULL)
+ if (ps.remaining == NULL) {
+ ret = -errno;
goto out;
+ }
ps.flags = flags;
ps.arg0 = **argv;
ps.cbi.table = table;
@@ -714,17 +720,19 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
if (*opt != NULL) {
/* put argv[0] back */
char *arg = HX_strdup(*opt++);
- if (arg == NULL)
- goto out_errno;
+ if (arg == NULL) {
+ ret = -errno;
+ goto out;
+ }
if (HXdeque_push(ps.remaining, arg) == NULL) {
free(arg);
- goto out_errno;
+ ret = -errno;
+ goto out;
}
}
if (posix_me_harder())
ps.flags |= HXOPT_RQ_ORDER;
-
for (cur = *opt; cur != NULL; ) {
if (state == HXOPT_S_TWOLONG)
state = HX_getopt_twolong(opt, &ps);
@@ -739,11 +747,11 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
if (state < 0) {
ret = state;
- break;
+ goto out;
}
if (state & HXOPT_I_ERROR) {
ret = state & ~HXOPT_I_ERROR;
- break;
+ goto out;
}
if (state & HXOPT_I_ASSIGN)
do_assign(&ps.cbi, ps.arg0);
@@ -756,13 +764,13 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
state &= ~HXOPT_I_MASK;
}
- out:
- if (ret == HXOPT_ERR_SUCCESS) {
- if (!(ps.flags & HXOPT_KEEP_ARGV)) {
+ if (!(ps.flags & HXOPT_KEEP_ARGV)) {
const char **nvec = reinterpret_cast(const char **,
HXdeque_to_vec(ps.remaining, &argk));
- if (nvec == NULL)
- goto out_errno;
+ if (nvec == NULL) {
+ ret = -errno;
+ goto out;
+ }
if (ps.flags & HXOPT_DESTROY_OLD)
/*
* Only the "true, original" argv is stored on the
@@ -780,7 +788,11 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
/* pointers are owned by nvec/argv now */
HXdeque_free(ps.remaining);
ps.remaining = nullptr;
- }
+ }
+ ret = HXOPT_ERR_SUCCESS;
+
+ out:
+ if (ret == HXOPT_ERR_SUCCESS) {
} else if (ret < 0) {
if (!(ps.flags & HXOPT_QUIET))
fprintf(stderr, "%s: %s\n", __func__, strerror(errno));
@@ -794,10 +806,6 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc,
if (ps.remaining != nullptr)
HXdeque_genocide2(ps.remaining, free);
return ret;
-
- out_errno:
- ret = -errno;
- goto out;
}
EXPORT_SYMBOL void HX_getopt_help(const struct HXoptcb *cbi, FILE *nfp)
diff --git a/src/socket.c b/src/socket.c
index 45f4053..ced884a 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -17,8 +17,19 @@
#ifdef _WIN32
# include <ws2tcpip.h>
#else
-# include <sys/socket.h>
# include <netdb.h>
+# include <unistd.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+#ifdef __linux__
+# include <linux/rtnetlink.h>
+#endif
+#ifdef __OpenBSD__
+# include <net/route.h>
#endif
#include <libHX/proc.h>
#include <libHX/socket.h>
@@ -31,6 +42,9 @@
#if defined(__sunos__) && !defined(SO_PROTOCOL)
# define SO_PROTOCOL SO_PROTOTYPE
#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
static int try_sk_from_env(int fd, const struct addrinfo *ai, const char *intf)
{
@@ -122,3 +136,170 @@ EXPORT_SYMBOL int HX_socket_from_env(const struct addrinfo *ai, const char *intf
errno = ENOENT;
return -1;
}
+
+#ifdef __linux__
+static int linux_sockaddr_local3(int sk, const void *buf, size_t bufsize)
+{
+ if (send(sk, buf, bufsize, 0) < 0)
+ return -errno;
+ char rsp[4096];
+ ssize_t ret = recv(sk, rsp, sizeof(rsp), 0);
+ if (ret < 0)
+ return -errno;
+ else if (static_cast(size_t, ret) < sizeof(struct nlmsghdr))
+ return -EIO;
+ struct nlmsghdr nlh;
+ memcpy(&nlh, rsp, sizeof(nlh));
+ if (!NLMSG_OK(&nlh, ret))
+ return -EIO;
+ const struct rtmsg *rtm = static_cast(void *, rsp + NLMSG_HDRLEN);
+ return rtm->rtm_type == RTN_LOCAL;
+}
+
+static int linux_sockaddr_local2(const struct sockaddr *sa, socklen_t sl)
+{
+ int sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ if (sk < 0)
+ return -errno;
+ struct {
+ struct nlmsghdr nh;
+ struct rtmsg rth;
+ char attrbuf[4096];
+ } req;
+ memset(&req, 0, sizeof(req));
+ req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rth));
+ req.nh.nlmsg_flags = NLM_F_REQUEST;
+ req.nh.nlmsg_type = RTM_GETROUTE;
+ req.rth.rtm_family = sa->sa_family;
+ req.rth.rtm_protocol = RTPROT_UNSPEC;
+ req.rth.rtm_type = RTN_UNSPEC;
+ req.rth.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.rth.rtm_table = RT_TABLE_UNSPEC;
+ struct rtattr *rta = reinterpret_cast(struct rtattr *,
+ reinterpret_cast(char *, &req) + NLMSG_ALIGN(req.nh.nlmsg_len));
+ rta->rta_type = RTA_DST;
+
+ int ret = -ENODATA;
+ if (sa->sa_family == AF_INET6) {
+ const struct in6_addr *ad = &reinterpret_cast(const struct sockaddr_in6 *, sa)->sin6_addr;
+ req.rth.rtm_dst_len = 16;
+ rta->rta_len = RTA_LENGTH(16);
+ req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
+ memcpy(RTA_DATA(rta), ad, 16);
+ } else if (sa->sa_family == AF_INET) {
+ struct in_addr ad = reinterpret_cast(const struct sockaddr_in *, sa)->sin_addr;
+ req.rth.rtm_dst_len = 4;
+ rta->rta_len = RTA_LENGTH(4);
+ req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
+ memcpy(RTA_DATA(rta), &ad, 4);
+ }
+ ret = linux_sockaddr_local3(sk, &req, req.nh.nlmsg_len);
+ close(sk);
+ return ret;
+}
+#endif
+
+#ifdef __OpenBSD__
+static int openbsd_sockaddr_local3(int rsk, const void *buf, size_t bufsize)
+{
+ ssize_t ret = send(rsk, buf, bufsize, 0);
+ if (ret < 0)
+ return -errno;
+ else if (ret != bufsize)
+ return -EIO;
+ struct rt_msghdr rsp;
+ do {
+ ret = recv(rsk, &rsp, sizeof(rsp), 0);
+ } while (ret > 0 && (rsp.rtm_version != RTM_VERSION ||
+ rsp.rtm_seq != 1 || rsp.rtm_pid != getpid()));
+ return rsp.rtm_flags & RTF_LOCAL;
+}
+
+static int openbsd_sockaddr_local2(const struct sockaddr *sa, socklen_t sl)
+{
+ int sk = socket(AF_ROUTE, SOCK_RAW, AF_UNSPEC);
+ if (sk < 0)
+ return -errno;
+ struct {
+ struct rt_msghdr rtm;
+ char ab[512];
+ } req;
+ memset(&req, 0, sizeof(req));
+ req.rtm.rtm_type = RTM_GET;
+ req.rtm.rtm_version = RTM_VERSION;
+ req.rtm.rtm_flags = RTF_STATIC | RTF_UP | RTF_HOST | RTF_GATEWAY;
+ req.rtm.rtm_seq = 1;
+ req.rtm.rtm_addrs = /*RTA_IFP |*/ RTA_DST;
+ req.rtm.rtm_tableid = getrtable();
+ req.rtm.rtm_hdrlen = sizeof(req.rtm);
+ memcpy(req.ab, sa, sl);
+ req.rtm.rtm_msglen = sizeof(req.rtm) + sl;
+ int ret = openbsd_sockaddr_local3(sk, &req, req.rtm.rtm_msglen);
+ close(sk);
+ return ret;
+}
+#endif
+
+EXPORT_SYMBOL int HX_sockaddr_is_local(const struct sockaddr *sa, socklen_t sl,
+ unsigned int flags)
+{
+ struct sockaddr_in xl = {};
+
+ if (sa->sa_family == AF_INET6) {
+ if (sl < sizeof(struct sockaddr_in6))
+ return -EINVAL;
+ } else if (sa->sa_family == AF_INET) {
+ if (sl < sizeof(struct sockaddr_in))
+ return -EINVAL;
+ }
+#ifdef HAVE_SYS_UN_H
+ else if (sa->sa_family == AF_UNIX) {
+ if (sl < sizeof(struct sockaddr_un))
+ return 1;
+ }
+#endif
+ else {
+ return -EPROTONOSUPPORT;
+ }
+ if (flags & AI_V4MAPPED && sa->sa_family == AF_INET6) {
+ /*
+ * Preprocess mapped addresses, becuase kernel interfaces do
+ * not support them.
+ */
+ const struct in6_addr *ad = &reinterpret_cast(const struct sockaddr_in6 *, sa)->sin6_addr;
+ static const uint8_t mappedv4[] = {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff};
+ if (memcmp(ad, mappedv4, 12) == 0) {
+ xl.sin_family = AF_INET;
+ memcpy(&xl.sin_addr, &ad->s6_addr[12], 4);
+ sa = reinterpret_cast(struct sockaddr *, &xl);
+ sl = sizeof(xl);
+ }
+ }
+#if defined(__linux__)
+ return linux_sockaddr_local2(sa, sl);
+#elif defined(__OpenBSD__)
+ return openbsd_sockaddr_local2(sa, sl);
+#else
+ if (sa->sa_family == AF_INET) {
+ struct in_addr a = reinterpret_cast(const struct sockaddr_in *, sa)->sin_addr;
+ return ntohl(a.s_addr) >> 24 == 127;
+ } else if (sa->sa_family == AF_INET6) {
+ return IN6_IS_ADDR_LOOPBACK(&reinterpret_cast(const struct sockaddr_in6 *, sa)->sin6_addr);
+ }
+#endif
+ return -EPROTONOSUPPORT;
+}
+
+EXPORT_SYMBOL int HX_ipaddr_is_local(const char *addr, unsigned int flags)
+{
+ struct addrinfo hints = {.ai_flags = flags & AI_V4MAPPED};
+ struct addrinfo *r = nullptr;
+ int err = getaddrinfo(addr, nullptr, &hints, &r);
+ if (err != 0) {
+ freeaddrinfo(r);
+ return 0;
+ }
+ int lcl = HX_sockaddr_is_local(r->ai_addr, r->ai_addrlen, hints.ai_flags);
+ freeaddrinfo(r);
+ return lcl;
+}
diff --git a/src/string.c b/src/string.c
index c14f1b5..ae19271 100644
--- a/src/string.c
+++ b/src/string.c
@@ -27,6 +27,7 @@
* all others pass through
*/
enum HX_quote_selector {
+ HXQUOTE_ALWAYS,
HXQUOTE_ACCEPT,
HXQUOTE_REJECT,
};
@@ -211,6 +212,8 @@ EXPORT_SYMBOL char **HX_split(const char *str, const char *delim,
*cp = max;
ret = malloc(sizeof(char *) * (*cp + 1));
+ if (ret == nullptr)
+ return nullptr;
ret[*cp] = NULL;
{
@@ -378,20 +381,48 @@ EXPORT_SYMBOL char *HX_stpltrim(const char *p)
return const_cast1(char *, p);
}
+/**
+ * Helper for substr() function for dealing with negative off/len values
+ * @z: total length of string
+ * @offset: n>=0 specifies offset from the start,
+ * n<0 specifies offset from the end
+ * @len: "length"; n>=0 specifies length to copy (from @offset),
+ * n<0 specifies the byte relative to the end at which to stop
+ *
+ * @abstart: (result) absolute start
+ * @retval: (result) absolute length to copy (from *@abstart)
+ */
+size_t HX_substr_helper(size_t z, long offset, long len, size_t *start)
+{
+ if (offset >= 0)
+ *start = offset;
+ else if (offset == LONG_MIN)
+ *start = z + -static_cast(size_t, LONG_MIN);
+ else
+ *start = z >= static_cast(unsigned long, -offset) ? z + offset : z;
+
+ size_t end;
+ if (len >= 0)
+ end = *start < SIZE_MAX - len ? *start + len : SIZE_MAX;
+ else if (len == LONG_MIN)
+ end = z + -static_cast(unsigned long, LONG_MIN);
+ else
+ end = z >= static_cast(unsigned long, -len) ? z + len : 0;
+ if (end > z)
+ end = z;
+ return end > *start ? end - *start : 0;
+}
+
/* supports negative offsets like scripting languages */
EXPORT_SYMBOL char *HX_strmid(const char *expr, long offset, long length)
{
- char *buffer;
-
- if (offset < 0)
- offset = strlen(expr) + offset;
- if (length < 0)
- length = strlen(expr) - offset + length;
- if ((buffer = malloc(length + 1)) == NULL)
+ size_t start = 0, tocopy = HX_substr_helper(strlen(expr), offset, length, &start);
+ char *buffer = malloc(tocopy + 1);
+ if (buffer == nullptr)
return NULL;
-
- expr += offset;
- return HX_strlcpy(buffer, expr, length + 1);
+ memcpy(buffer, &expr[start], tocopy);
+ buffer[tocopy] = '\0';
+ return buffer;
}
EXPORT_SYMBOL char *HX_strndup(const char *src, size_t size)
@@ -773,7 +804,7 @@ static size_t HX_quoted_size(const char *s, unsigned int type)
EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type,
char **free_me)
{
- const struct HX_quote_rule *rule;
+ const struct HX_quote_rule *rule = nullptr;
bool do_quote;
char *tmp;
@@ -782,15 +813,19 @@ EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type,
return NULL;
}
/* If quote_chars is NULL, it is clear all chars are to be encoded. */
- rule = &HX_quote_rules[type];
- if (type >= ARRAY_SIZE(HX_quote_rules) || rule->chars == NULL)
+ if (type >= ARRAY_SIZE(HX_quote_rules)) {
do_quote = true;
- else if (rule->selector == HXQUOTE_REJECT)
- do_quote = strpbrk(src, rule->chars) != NULL;
- else if (rule->selector == HXQUOTE_ACCEPT)
- do_quote = HX_strchr2(src, rule->chars) != NULL;
- else
- do_quote = false;
+ } else {
+ rule = &HX_quote_rules[type];
+ if (rule->selector == HXQUOTE_ALWAYS)
+ do_quote = true;
+ else if (rule->selector == HXQUOTE_REJECT)
+ do_quote = strpbrk(src, rule->chars) != NULL;
+ else if (rule->selector == HXQUOTE_ACCEPT)
+ do_quote = HX_strchr2(src, rule->chars) != NULL;
+ else
+ do_quote = false;
+ }
/*
* free_me == NULL implies that we always allocate, even if
* there is nothing to quote.
diff --git a/src/tc-cast.c b/src/tc-cast.c
index 422054c..2c58805 100644
--- a/src/tc-cast.c
+++ b/src/tc-cast.c
@@ -1,11 +1,4 @@
-/*
- * Testing for compile error in the cast helpers
- * written by Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <math.h>
#include <stdint.h>
#include <stdio.h>
diff --git a/src/tc-dir.c b/src/tc-dir.c
index d2e3885..12cbacd 100644
--- a/src/tc-dir.c
+++ b/src/tc-dir.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifndef __cplusplus
# include <stdio.h>
# include <stdlib.h>
diff --git a/src/tc-format.c b/src/tc-format.c
index ad067ee..ed8e6d4 100644
--- a/src/tc-format.c
+++ b/src/tc-format.c
@@ -1,11 +1,4 @@
-/*
- * formatter test program
- * Copyright by Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -55,7 +48,7 @@ static const char *const fmt2_strings[] = {
NULL,
};
-static void t_format(int argc)
+static int t_format(int argc)
{
struct HXformat_map *fmt = HXformat_init();
const char *const *s;
@@ -70,9 +63,14 @@ static void t_format(int argc)
HXformat_add(fmt, "TWOARG", "a, b", HXTYPE_STRING | HXFORMAT_IMMED);
++argc;
printf("# HXformat2\n");
- for (s = fmt2_strings; *s != NULL; ++s)
- HXformat_fprintf(fmt, stdout, *s);
+ for (s = fmt2_strings; *s != NULL; ++s) {
+ char buf[80];
+ if (HXformat_sprintf(fmt, buf, ARRAY_SIZE(buf), *s) < 0 ||
+ HXformat_fprintf(fmt, stdout, *s) < 0)
+ return EXIT_FAILURE;
+ }
HXformat_free(fmt);
+ return EXIT_SUCCESS;
}
int main(int argc, const char **argv)
@@ -84,7 +82,7 @@ int main(int argc, const char **argv)
fprintf(stderr, "HX_init: %s\n", strerror(-ret));
return EXIT_FAILURE;
}
- t_format(argc);
+ ret = t_format(argc);
HX_exit();
- return EXIT_SUCCESS;
+ return ret;
}
diff --git a/src/tc-io.c b/src/tc-io.c
index 1e95e65..639ebcc 100644
--- a/src/tc-io.c
+++ b/src/tc-io.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
diff --git a/src/tc-list.c b/src/tc-list.c
index 751f462..e0087e3 100644
--- a/src/tc-list.c
+++ b/src/tc-list.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifdef __cplusplus
# include <cstdio>
# include <cstdlib>
diff --git a/src/tc-list2.c b/src/tc-list2.c
index f41861b..d70ada2 100644
--- a/src/tc-list2.c
+++ b/src/tc-list2.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <stdlib.h>
#include <libHX/list.h>
diff --git a/src/tc-map.c b/src/tc-map.c
index ce55688..0037c83 100644
--- a/src/tc-map.c
+++ b/src/tc-map.c
@@ -1,11 +1,4 @@
-/*
- * Test for libHX's maps
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include "config.h"
#include <errno.h>
#include <math.h>
diff --git a/src/tc-memmem.c b/src/tc-memmem.c
index 3b62ef1..a4f272e 100644
--- a/src/tc-memmem.c
+++ b/src/tc-memmem.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
* speed test HX_memmem
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
diff --git a/src/tc-misc.c b/src/tc-misc.c
index cb985a3..5b043d4 100644
--- a/src/tc-misc.c
+++ b/src/tc-misc.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifndef __cplusplus
# include <stdlib.h>
#else
@@ -38,7 +32,8 @@ int main(int argc, const char **argv)
if (stat(argv[1], &sa) < 0 ||
stat(argv[2], &sb) < 0)
perror("stat");
- printf("Difference: %ld\n", HX_time_compare(&sa, &sb, 'm'));
+ else
+ printf("Difference: %ld\n", HX_time_compare(&sa, &sb, 'm'));
}
HX_exit();
diff --git a/src/tc-netio.c b/src/tc-netio.c
index 45a6efc..5d3c22e 100644
--- a/src/tc-netio.c
+++ b/src/tc-netio.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#define WIN32_LEAN_AND_MEAN 1
#ifdef __cplusplus
# include <cstdlib>
diff --git a/src/tc-option.c b/src/tc-option.c
index aa6f12c..db3d3f4 100644
--- a/src/tc-option.c
+++ b/src/tc-option.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2022 Jan Engelhardt
/*
* option parser test program
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <errno.h>
#include <stdio.h>
diff --git a/src/tc-proc.c b/src/tc-proc.c
index 904c450..19c8b18 100644
--- a/src/tc-proc.c
+++ b/src/tc-proc.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifdef __cplusplus
# include <cerrno>
# include <cstdio>
diff --git a/src/tc-rand.c b/src/tc-rand.c
index 3af45d0..149f18e 100644
--- a/src/tc-rand.c
+++ b/src/tc-rand.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
diff --git a/src/tc-realpath.c b/src/tc-realpath.c
index c2ef15a..23609ca 100644
--- a/src/tc-realpath.c
+++ b/src/tc-realpath.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
* Test utility for libHX's realpath
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <stdbool.h>
#include <stdio.h>
diff --git a/src/tc-shconfig.c b/src/tc-shconfig.c
index 8a31c45..556f90f 100644
--- a/src/tc-shconfig.c
+++ b/src/tc-shconfig.c
@@ -1,13 +1,9 @@
/*
A=b;C="d" ; E="F;" ; F= G=Z
*/
+// SPDX-License-Identifier: MIT
/*
* shconfig test program
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <errno.h>
#include <stdio.h>
diff --git a/src/tc-socket.c b/src/tc-socket.c
new file mode 100644
index 0000000..9c73d24
--- /dev/null
+++ b/src/tc-socket.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libHX/defs.h>
+#include <libHX/socket.h>
+#ifndef _WIN32
+# include <netdb.h>
+#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
+
+int main(void)
+{
+ static const char *addrs[] = {
+ "::1", "::2", "::ffff:127.0.0.1", "::",
+ "127.0.0.1", "127.0.0.2", "1.1.1.1", "255.255.255.255",
+ };
+ for (size_t i = 0; i < ARRAY_SIZE(addrs); ++i) {
+ printf("%-16s\t", addrs[i]);
+ int lcl = HX_ipaddr_is_local(addrs[i], AI_V4MAPPED);
+ if (lcl < 0) {
+ printf("%s\n", strerror(-lcl));
+ return EXIT_FAILURE;
+ }
+ printf("%d\n", lcl);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/tc-strchr2.c b/src/tc-strchr2.c
index 6e0eaad..ad37f37 100644
--- a/src/tc-strchr2.c
+++ b/src/tc-strchr2.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
* Behavior Correctness Test for HX_strchr2
- * Copyright Jan Engelhardt, 2013
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <libHX/string.h>
diff --git a/src/tc-string.c b/src/tc-string.c
index db242a3..77235c2 100644
--- a/src/tc-string.c
+++ b/src/tc-string.c
@@ -1,11 +1,5 @@
/* long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing long line for testing */
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifndef __cplusplus
# include <assert.h>
# include <errno.h>
@@ -480,6 +474,35 @@ static void t_time_strto(void)
}
}
+static int t_strmid(void)
+{
+#define T(spar,opar,lpar,xpar) do { \
+ char *s = HX_strmid((spar), (opar), (lpar)); \
+ if (s == nullptr) \
+ return EXIT_FAILURE; \
+ int ret = strcmp(s, (xpar)); \
+ if (ret != 0) { \
+ fprintf(stderr, "Faillure: substr %s,%d,%d = %s\n", \
+ (spar), static_cast(int, (opar)), static_cast(int, (lpar)), s); \
+ free(s); \
+ return ret; \
+ } \
+ free(s); \
+ } while (false)
+
+ T("Hello World", -12, 5, "");
+ T("bark", -3, -1, "ar");
+ T("cake", -3, -3, "");
+ T("cake", -3, -4, "");
+ T("fun", 0, 0, "");
+ T("bark", 0, 1, "b");
+ T("bark", 0, 5, "bark");
+ T("bark", -4, 1, "b");
+ T("bark", -4, 5, "bark");
+ return EXIT_SUCCESS;
+#undef T
+}
+
int main(int argc, const char **argv)
{
hxmc_t *tx = NULL;
@@ -488,6 +511,9 @@ int main(int argc, const char **argv)
if (HX_init() <= 0)
abort();
+ int ret = t_strmid();
+ if (ret != EXIT_SUCCESS)
+ return EXIT_FAILURE;
fp = fopen(file, "r");
if (fp == NULL) {
diff --git a/src/tc-strquote.c b/src/tc-strquote.c
index fab305e..ef357d1 100644
--- a/src/tc-strquote.c
+++ b/src/tc-strquote.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
* Behavior Correctness Test for HX_strquote
- * Copyright Jan Engelhardt, 2013
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
*/
#include <stdbool.h>
#include <stdio.h>
diff --git a/src/tc-switchuser.c b/src/tc-switchuser.c
index 3bb3fe9..1763527 100644
--- a/src/tc-switchuser.c
+++ b/src/tc-switchuser.c
@@ -1,14 +1,7 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#if defined(HAVE_INITGROUPS)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,6 +10,7 @@
#include <libHX/defs.h>
#include <libHX/option.h>
#include <libHX/proc.h>
+#if defined(HAVE_INITGROUPS)
static char *user_name, *group_name;
static const struct HXoption options_table[] = {
@@ -70,4 +64,9 @@ int main(int argc, const char **argv)
}
return EXIT_SUCCESS;
}
+#else
+int main(void)
+{
+ return EXIT_SUCCESS;
+}
#endif
diff --git a/src/tc-time.c b/src/tc-time.c
index e86ed67..5097cde 100644
--- a/src/tc-time.c
+++ b/src/tc-time.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt, 2012
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <assert.h>
#include <math.h>
#include <stdio.h>
@@ -27,7 +21,7 @@ static const int NANOSECOND = 1000000000;
static const long long NANOSECOND_LL = 1000000000;
static const unsigned int clock_id = CLOCK_THREAD_CPUTIME_ID;
static const unsigned int step = 1000;
-static const unsigned int step_mul = 10000000;
+static const long step_mul = 10000000;
static const struct timespec pairs[] = {
{-1, 700000000}, {-1, 400000000}, {-1, 0},
diff --git a/src/tc-xml.c b/src/tc-xml.c
index 07cf3b3..49b24ad 100644
--- a/src/tc-xml.c
+++ b/src/tc-xml.c
@@ -1,10 +1,4 @@
-/*
- * Copyright Jan Engelhardt
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the WTF Public License version 2 or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: MIT
#include <stdbool.h>
#include <stdio.h>
#include <libxml/parser.h>