diff options
Diffstat (limited to 'src')
41 files changed, 2121 insertions, 724 deletions
diff --git a/src/.gitignore b/src/.gitignore index 5658aee..89edb97 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -4,6 +4,8 @@ /t?-deque /t?-dir /t?-format +/t?-intdiff +/t?-io /t?-link /t?-list /t?-list2 @@ -17,9 +19,11 @@ /t?-rand /t?-realpath /t?-shconfig +/t?-socket /t?-strchr2 /t?-string /t?-strquote +/t?-switchuser /t?-time # automake tests diff --git a/src/Makefile.am b/src/Makefile.am index 73a6bdb..921e6b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,10 +10,10 @@ lib_LTLIBRARIES += libHX_rtcheck.la endif libHX_la_SOURCES = deque.c dl.c format.c io.c map.c \ - mc.c misc.c opt.c \ - rand.c string.c time.c -libHX_la_LIBADD = ${libdl_LIBS} ${libpthread_LIBS} ${librt_LIBS} -libHX_la_LDFLAGS = -no-undefined -version-info 32:0:0 + 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 36:0:4 if WITH_GNU_LD libHX_la_LDFLAGS += -Wl,--version-script=${srcdir}/libHX.map endif @@ -21,9 +21,7 @@ EXTRA_libHX_la_DEPENDENCIES = libHX.map if MINGW32 libHX_la_SOURCES += ux-file.c ux-mmap.c -endif -if B_PROC -libHX_la_SOURCES += proc.c +libHX_la_LIBADD += -lws2_32 endif libHX_rtcheck_la_SOURCES = rtcheck.c @@ -35,17 +33,18 @@ endif EXTRA_DIST = internal.h map_int.h libHX.map -check_PROGRAMS = tc-compile tc-cast tc-deque tc-dir tc-format tc-link \ +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-time -TESTS = tc-strchr2 tc-strquote + tc-shconfig tc-socket tc-strchr2 tc-string tc-strquote \ + tc-switchuser tc-time +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 tc_dir_LDADD = libHX.la tc_format_LDADD = libHX.la -tc_link_LDADD = libHX.la +tc_io_LDADD = libHX.la tc_list_LDADD = libHX.la tc_list2_LDADD = libHX.la tc_list2_CFLAGS = ${AM_CFLAGS} -O2 -fstrict-aliasing @@ -58,25 +57,28 @@ 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 +tc_switchuser_LDADD = libHX.la tc_time_LDADD = libHX.la if HAVE_CXX -check_PROGRAMS += tx-compile tx-cast tx-deque tx-dir tx-list tx-list2 \ +check_PROGRAMS += tx-compile tx-cast tx-deque tx-dir \ + tx-intdiff tx-list tx-list2 \ tx-misc tx-netio \ tx-option tx-proc tx-rand tx-strchr2 tx-string \ tx-strquote tx-time TESTS += tx-strchr2 tx-strquote tx_cast_SOURCES = tx-cast.cpp -tx_cast_CXXFLAGS = ${AM_CXXFLAGS} -std=c++98 tx_cast_LDADD = libHX.la -lm tx_compile_SOURCES = tx-compile.cpp tx_compile_LDADD = libHX.la tx_deque_SOURCES = tx-deque.cpp tx_dir_SOURCES = tx-dir.cpp tx_dir_LDADD = libHX.la +tx_intdiff_SOURCES = tx-intdiff.cpp tx_list_SOURCES = tx-list.cpp tx_list_LDADD = libHX.la tx_list2_SOURCES = tx-list2.cpp diff --git a/src/Makefile.in b/src/Makefile.in index 632d4ab..8257e20 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15.1 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -93,18 +93,21 @@ host_triplet = @host@ @HAVE_DLFCN_H_TRUE@am__append_1 = libHX_rtcheck.la @WITH_GNU_LD_TRUE@am__append_2 = -Wl,--version-script=${srcdir}/libHX.map @MINGW32_TRUE@am__append_3 = ux-file.c ux-mmap.c -@B_PROC_TRUE@am__append_4 = proc.c +@MINGW32_TRUE@am__append_4 = -lws2_32 @WITH_GNU_LD_TRUE@am__append_5 = -Wl,--version-script=${srcdir}/libHX.map check_PROGRAMS = tc-compile$(EXEEXT) tc-cast$(EXEEXT) \ tc-deque$(EXEEXT) tc-dir$(EXEEXT) tc-format$(EXEEXT) \ - tc-link$(EXEEXT) tc-list$(EXEEXT) tc-list2$(EXEEXT) \ + tc-io$(EXEEXT) tc-list$(EXEEXT) tc-list2$(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-time$(EXEEXT) $(am__EXEEXT_1) -TESTS = tc-strchr2$(EXEEXT) tc-strquote$(EXEEXT) $(am__EXEEXT_2) -@HAVE_CXX_TRUE@am__append_6 = tx-compile tx-cast tx-deque tx-dir tx-list tx-list2 \ + 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 \ @HAVE_CXX_TRUE@ tx-option tx-proc tx-rand tx-strchr2 tx-string \ @HAVE_CXX_TRUE@ tx-strquote tx-time @@ -123,6 +126,14 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = +@HAVE_CXX_TRUE@am__EXEEXT_1 = tx-compile$(EXEEXT) tx-cast$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-deque$(EXEEXT) tx-dir$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-intdiff$(EXEEXT) tx-list$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-list2$(EXEEXT) tx-misc$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-netio$(EXEEXT) tx-option$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-proc$(EXEEXT) tx-rand$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-strchr2$(EXEEXT) tx-string$(EXEEXT) \ +@HAVE_CXX_TRUE@ tx-strquote$(EXEEXT) tx-time$(EXEEXT) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -154,14 +165,14 @@ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libHX_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__libHX_la_SOURCES_DIST = deque.c dl.c format.c io.c map.c mc.c \ - misc.c opt.c rand.c string.c time.c ux-file.c ux-mmap.c proc.c + misc.c opt.c proc.c rand.c socket.c string.c time.c ux-file.c \ + ux-mmap.c @MINGW32_TRUE@am__objects_1 = ux-file.lo ux-mmap.lo -@B_PROC_TRUE@am__objects_2 = proc.lo am_libHX_la_OBJECTS = deque.lo dl.lo format.lo io.lo map.lo mc.lo \ - misc.lo opt.lo rand.lo string.lo time.lo $(am__objects_1) \ - $(am__objects_2) + misc.lo opt.lo proc.lo rand.lo socket.lo string.lo time.lo \ + $(am__objects_1) libHX_la_OBJECTS = $(am_libHX_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -178,14 +189,6 @@ libHX_rtcheck_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_CFLAGS) $(CFLAGS) $(libHX_rtcheck_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_DLFCN_H_TRUE@am_libHX_rtcheck_la_rpath = -rpath $(libdir) -@HAVE_CXX_TRUE@am__EXEEXT_1 = tx-compile$(EXEEXT) tx-cast$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-deque$(EXEEXT) tx-dir$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-list$(EXEEXT) tx-list2$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-misc$(EXEEXT) tx-netio$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-option$(EXEEXT) tx-proc$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-rand$(EXEEXT) tx-strchr2$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-string$(EXEEXT) tx-strquote$(EXEEXT) \ -@HAVE_CXX_TRUE@ tx-time$(EXEEXT) tc_cast_SOURCES = tc-cast.c tc_cast_OBJECTS = tc_cast-tc-cast.$(OBJEXT) tc_cast_DEPENDENCIES = libHX.la @@ -204,9 +207,9 @@ tc_dir_DEPENDENCIES = libHX.la tc_format_SOURCES = tc-format.c tc_format_OBJECTS = tc-format.$(OBJEXT) tc_format_DEPENDENCIES = libHX.la -tc_link_SOURCES = tc-link.c -tc_link_OBJECTS = tc-link.$(OBJEXT) -tc_link_DEPENDENCIES = libHX.la +tc_io_SOURCES = tc-io.c +tc_io_OBJECTS = tc-io.$(OBJEXT) +tc_io_DEPENDENCIES = libHX.la tc_list_SOURCES = tc-list.c tc_list_OBJECTS = tc-list.$(OBJEXT) tc_list_DEPENDENCIES = libHX.la @@ -243,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 @@ -252,16 +258,16 @@ tc_string_DEPENDENCIES = libHX.la tc_strquote_SOURCES = tc-strquote.c tc_strquote_OBJECTS = tc-strquote.$(OBJEXT) tc_strquote_DEPENDENCIES = libHX.la +tc_switchuser_SOURCES = tc-switchuser.c +tc_switchuser_OBJECTS = tc-switchuser.$(OBJEXT) +tc_switchuser_DEPENDENCIES = libHX.la tc_time_SOURCES = tc-time.c tc_time_OBJECTS = tc-time.$(OBJEXT) tc_time_DEPENDENCIES = libHX.la am__tx_cast_SOURCES_DIST = tx-cast.cpp -@HAVE_CXX_TRUE@am_tx_cast_OBJECTS = tx_cast-tx-cast.$(OBJEXT) +@HAVE_CXX_TRUE@am_tx_cast_OBJECTS = tx-cast.$(OBJEXT) tx_cast_OBJECTS = $(am_tx_cast_OBJECTS) @HAVE_CXX_TRUE@tx_cast_DEPENDENCIES = libHX.la -tx_cast_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(tx_cast_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ am__tx_compile_SOURCES_DIST = tx-compile.cpp @HAVE_CXX_TRUE@am_tx_compile_OBJECTS = tx-compile.$(OBJEXT) tx_compile_OBJECTS = $(am_tx_compile_OBJECTS) @@ -274,6 +280,10 @@ am__tx_dir_SOURCES_DIST = tx-dir.cpp @HAVE_CXX_TRUE@am_tx_dir_OBJECTS = tx-dir.$(OBJEXT) tx_dir_OBJECTS = $(am_tx_dir_OBJECTS) @HAVE_CXX_TRUE@tx_dir_DEPENDENCIES = libHX.la +am__tx_intdiff_SOURCES_DIST = tx-intdiff.cpp +@HAVE_CXX_TRUE@am_tx_intdiff_OBJECTS = tx-intdiff.$(OBJEXT) +tx_intdiff_OBJECTS = $(am_tx_intdiff_OBJECTS) +tx_intdiff_LDADD = $(LDADD) am__tx_list_SOURCES_DIST = tx-list.cpp @HAVE_CXX_TRUE@am_tx_list_OBJECTS = tx-list.$(OBJEXT) tx_list_OBJECTS = $(am_tx_list_OBJECTS) @@ -335,7 +345,34 @@ am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/deque.Plo ./$(DEPDIR)/dl.Plo \ + ./$(DEPDIR)/format.Plo ./$(DEPDIR)/io.Plo ./$(DEPDIR)/map.Plo \ + ./$(DEPDIR)/mc.Plo ./$(DEPDIR)/misc.Plo ./$(DEPDIR)/opt.Plo \ + ./$(DEPDIR)/proc.Plo ./$(DEPDIR)/rand.Plo \ + ./$(DEPDIR)/rtcheck.Plo ./$(DEPDIR)/socket.Plo \ + ./$(DEPDIR)/string.Plo ./$(DEPDIR)/tc-compile.Po \ + ./$(DEPDIR)/tc-deque.Po ./$(DEPDIR)/tc-dir.Po \ + ./$(DEPDIR)/tc-format.Po ./$(DEPDIR)/tc-io.Po \ + ./$(DEPDIR)/tc-list.Po ./$(DEPDIR)/tc-map.Po \ + ./$(DEPDIR)/tc-memmem.Po ./$(DEPDIR)/tc-misc.Po \ + ./$(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-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 \ + ./$(DEPDIR)/tx-intdiff.Po ./$(DEPDIR)/tx-list.Po \ + ./$(DEPDIR)/tx-misc.Po ./$(DEPDIR)/tx-netio.Po \ + ./$(DEPDIR)/tx-option.Po ./$(DEPDIR)/tx-proc.Po \ + ./$(DEPDIR)/tx-rand.Po ./$(DEPDIR)/tx-strchr2.Po \ + ./$(DEPDIR)/tx-string.Po ./$(DEPDIR)/tx-strquote.Po \ + ./$(DEPDIR)/tx-time.Po ./$(DEPDIR)/tx_list2-tx-list2.Po \ + ./$(DEPDIR)/ux-file.Plo ./$(DEPDIR)/ux-mmap.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -374,23 +411,25 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libHX_la_SOURCES) $(libHX_rtcheck_la_SOURCES) tc-cast.c \ - tc-compile.c tc-deque.c tc-dir.c tc-format.c tc-link.c \ - tc-list.c tc-list2.c tc-map.c tc-memmem.c tc-misc.c tc-netio.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-time.c \ - $(tx_cast_SOURCES) $(tx_compile_SOURCES) $(tx_deque_SOURCES) \ - $(tx_dir_SOURCES) $(tx_list_SOURCES) $(tx_list2_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-link.c tc-list.c tc-list2.c tc-map.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-time.c $(am__tx_cast_SOURCES_DIST) \ - $(am__tx_compile_SOURCES_DIST) $(am__tx_deque_SOURCES_DIST) \ - $(am__tx_dir_SOURCES_DIST) $(am__tx_list_SOURCES_DIST) \ + 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) \ $(am__tx_list2_SOURCES_DIST) $(am__tx_misc_SOURCES_DIST) \ $(am__tx_netio_SOURCES_DIST) $(am__tx_option_SOURCES_DIST) \ $(am__tx_proc_SOURCES_DIST) $(am__tx_rand_SOURCES_DIST) \ @@ -418,8 +457,6 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no @@ -575,6 +612,7 @@ am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck @HAVE_CXX_TRUE@am__EXEEXT_2 = tx-strchr2$(EXEEXT) tx-strquote$(EXEEXT) @@ -613,8 +651,9 @@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ @@ -629,8 +668,10 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FILECMD = @FILECMD@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -646,7 +687,6 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -LYX = @LYX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -723,6 +763,7 @@ psdir = @psdir@ regular_CFLAGS = @regular_CFLAGS@ regular_CPPFLAGS = @regular_CPPFLAGS@ regular_CXXFLAGS = @regular_CXXFLAGS@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -736,9 +777,10 @@ AM_CFLAGS = ${regular_CFLAGS} AM_CXXFLAGS = ${regular_CXXFLAGS} lib_LTLIBRARIES = libHX.la $(am__append_1) libHX_la_SOURCES = deque.c dl.c format.c io.c map.c mc.c misc.c opt.c \ - rand.c string.c time.c $(am__append_3) $(am__append_4) -libHX_la_LIBADD = ${libdl_LIBS} ${libpthread_LIBS} ${librt_LIBS} -libHX_la_LDFLAGS = -no-undefined -version-info 32:0:0 $(am__append_2) + 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 36:0:4 $(am__append_2) EXTRA_libHX_la_DEPENDENCIES = libHX.map libHX_rtcheck_la_SOURCES = rtcheck.c libHX_rtcheck_la_LIBADD = ${libdl_LIBS} @@ -750,7 +792,7 @@ tc_cast_LDADD = libHX.la -lm tc_compile_LDADD = libHX.la tc_dir_LDADD = libHX.la tc_format_LDADD = libHX.la -tc_link_LDADD = libHX.la +tc_io_LDADD = libHX.la tc_list_LDADD = libHX.la tc_list2_LDADD = libHX.la tc_list2_CFLAGS = ${AM_CFLAGS} -O2 -fstrict-aliasing @@ -763,18 +805,20 @@ 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 +tc_switchuser_LDADD = libHX.la tc_time_LDADD = libHX.la @HAVE_CXX_TRUE@tx_cast_SOURCES = tx-cast.cpp -@HAVE_CXX_TRUE@tx_cast_CXXFLAGS = ${AM_CXXFLAGS} -std=c++98 @HAVE_CXX_TRUE@tx_cast_LDADD = libHX.la -lm @HAVE_CXX_TRUE@tx_compile_SOURCES = tx-compile.cpp @HAVE_CXX_TRUE@tx_compile_LDADD = libHX.la @HAVE_CXX_TRUE@tx_deque_SOURCES = tx-deque.cpp @HAVE_CXX_TRUE@tx_dir_SOURCES = tx-dir.cpp @HAVE_CXX_TRUE@tx_dir_LDADD = libHX.la +@HAVE_CXX_TRUE@tx_intdiff_SOURCES = tx-intdiff.cpp @HAVE_CXX_TRUE@tx_list_SOURCES = tx-list.cpp @HAVE_CXX_TRUE@tx_list_LDADD = libHX.la @HAVE_CXX_TRUE@tx_list2_SOURCES = tx-list2.cpp @@ -819,8 +863,8 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -832,6 +876,15 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ @@ -873,15 +926,6 @@ libHX.la: $(libHX_la_OBJECTS) $(libHX_la_DEPENDENCIES) $(EXTRA_libHX_la_DEPENDEN libHX_rtcheck.la: $(libHX_rtcheck_la_OBJECTS) $(libHX_rtcheck_la_DEPENDENCIES) $(EXTRA_libHX_rtcheck_la_DEPENDENCIES) $(AM_V_CCLD)$(libHX_rtcheck_la_LINK) $(am_libHX_rtcheck_la_rpath) $(libHX_rtcheck_la_OBJECTS) $(libHX_rtcheck_la_LIBADD) $(LIBS) -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list - tc-cast$(EXEEXT): $(tc_cast_OBJECTS) $(tc_cast_DEPENDENCIES) $(EXTRA_tc_cast_DEPENDENCIES) @rm -f tc-cast$(EXEEXT) $(AM_V_CCLD)$(tc_cast_LINK) $(tc_cast_OBJECTS) $(tc_cast_LDADD) $(LIBS) @@ -902,9 +946,9 @@ tc-format$(EXEEXT): $(tc_format_OBJECTS) $(tc_format_DEPENDENCIES) $(EXTRA_tc_fo @rm -f tc-format$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tc_format_OBJECTS) $(tc_format_LDADD) $(LIBS) -tc-link$(EXEEXT): $(tc_link_OBJECTS) $(tc_link_DEPENDENCIES) $(EXTRA_tc_link_DEPENDENCIES) - @rm -f tc-link$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(tc_link_OBJECTS) $(tc_link_LDADD) $(LIBS) +tc-io$(EXEEXT): $(tc_io_OBJECTS) $(tc_io_DEPENDENCIES) $(EXTRA_tc_io_DEPENDENCIES) + @rm -f tc-io$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tc_io_OBJECTS) $(tc_io_LDADD) $(LIBS) tc-list$(EXEEXT): $(tc_list_OBJECTS) $(tc_list_DEPENDENCIES) $(EXTRA_tc_list_DEPENDENCIES) @rm -f tc-list$(EXEEXT) @@ -950,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) @@ -962,13 +1010,17 @@ tc-strquote$(EXEEXT): $(tc_strquote_OBJECTS) $(tc_strquote_DEPENDENCIES) $(EXTRA @rm -f tc-strquote$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tc_strquote_OBJECTS) $(tc_strquote_LDADD) $(LIBS) +tc-switchuser$(EXEEXT): $(tc_switchuser_OBJECTS) $(tc_switchuser_DEPENDENCIES) $(EXTRA_tc_switchuser_DEPENDENCIES) + @rm -f tc-switchuser$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tc_switchuser_OBJECTS) $(tc_switchuser_LDADD) $(LIBS) + tc-time$(EXEEXT): $(tc_time_OBJECTS) $(tc_time_DEPENDENCIES) $(EXTRA_tc_time_DEPENDENCIES) @rm -f tc-time$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tc_time_OBJECTS) $(tc_time_LDADD) $(LIBS) tx-cast$(EXEEXT): $(tx_cast_OBJECTS) $(tx_cast_DEPENDENCIES) $(EXTRA_tx_cast_DEPENDENCIES) @rm -f tx-cast$(EXEEXT) - $(AM_V_CXXLD)$(tx_cast_LINK) $(tx_cast_OBJECTS) $(tx_cast_LDADD) $(LIBS) + $(AM_V_CXXLD)$(CXXLINK) $(tx_cast_OBJECTS) $(tx_cast_LDADD) $(LIBS) tx-compile$(EXEEXT): $(tx_compile_OBJECTS) $(tx_compile_DEPENDENCIES) $(EXTRA_tx_compile_DEPENDENCIES) @rm -f tx-compile$(EXEEXT) @@ -982,6 +1034,10 @@ tx-dir$(EXEEXT): $(tx_dir_OBJECTS) $(tx_dir_DEPENDENCIES) $(EXTRA_tx_dir_DEPENDE @rm -f tx-dir$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tx_dir_OBJECTS) $(tx_dir_LDADD) $(LIBS) +tx-intdiff$(EXEEXT): $(tx_intdiff_OBJECTS) $(tx_intdiff_DEPENDENCIES) $(EXTRA_tx_intdiff_DEPENDENCIES) + @rm -f tx-intdiff$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(tx_intdiff_OBJECTS) $(tx_intdiff_LDADD) $(LIBS) + tx-list$(EXEEXT): $(tx_list_OBJECTS) $(tx_list_DEPENDENCIES) $(EXTRA_tx_list_DEPENDENCIES) @rm -f tx-list$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(tx_list_OBJECTS) $(tx_list_LDADD) $(LIBS) @@ -1032,57 +1088,67 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deque.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rand.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtcheck.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-compile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-deque.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-dir.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-format.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-link.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-map.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-memmem.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-netio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-option.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-proc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-rand.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-realpath.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-shconfig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-strchr2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-string.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-strquote.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-time.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc_cast-tc-cast.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc_list2-tc-list2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-compile.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-deque.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-dir.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-netio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-option.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-proc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-rand.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-strchr2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-string.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-strquote.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-time.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx_cast-tx-cast.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx_list2-tx-list2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ux-file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ux-mmap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deque.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/format.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rand.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtcheck.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-compile.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-deque.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-dir.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-format.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-io.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-map.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-memmem.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-misc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-netio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-option.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-proc.Po@am__quote@ # am--include-marker +@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 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-switchuser.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-time.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc_cast-tc-cast.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc_list2-tc-list2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-cast.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-compile.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-deque.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-dir.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-intdiff.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-misc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-netio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-option.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-proc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-rand.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-strchr2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-string.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-strquote.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx-time.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tx_list2-tx-list2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ux-file.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ux-mmap.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -1160,20 +1226,6 @@ tc_list2-tc-list2.obj: tc-list2.c @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< -tx_cast-tx-cast.o: tx-cast.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tx_cast_CXXFLAGS) $(CXXFLAGS) -MT tx_cast-tx-cast.o -MD -MP -MF $(DEPDIR)/tx_cast-tx-cast.Tpo -c -o tx_cast-tx-cast.o `test -f 'tx-cast.cpp' || echo '$(srcdir)/'`tx-cast.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tx_cast-tx-cast.Tpo $(DEPDIR)/tx_cast-tx-cast.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tx-cast.cpp' object='tx_cast-tx-cast.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tx_cast_CXXFLAGS) $(CXXFLAGS) -c -o tx_cast-tx-cast.o `test -f 'tx-cast.cpp' || echo '$(srcdir)/'`tx-cast.cpp - -tx_cast-tx-cast.obj: tx-cast.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tx_cast_CXXFLAGS) $(CXXFLAGS) -MT tx_cast-tx-cast.obj -MD -MP -MF $(DEPDIR)/tx_cast-tx-cast.Tpo -c -o tx_cast-tx-cast.obj `if test -f 'tx-cast.cpp'; then $(CYGPATH_W) 'tx-cast.cpp'; else $(CYGPATH_W) '$(srcdir)/tx-cast.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tx_cast-tx-cast.Tpo $(DEPDIR)/tx_cast-tx-cast.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='tx-cast.cpp' object='tx_cast-tx-cast.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tx_cast_CXXFLAGS) $(CXXFLAGS) -c -o tx_cast-tx-cast.obj `if test -f 'tx-cast.cpp'; then $(CYGPATH_W) 'tx-cast.cpp'; else $(CYGPATH_W) '$(srcdir)/tx-cast.cpp'; fi` - tx_list2-tx-list2.o: tx-list2.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tx_list2_CXXFLAGS) $(CXXFLAGS) -MT tx_list2-tx-list2.o -MD -MP -MF $(DEPDIR)/tx_list2-tx-list2.Tpo -c -o tx_list2-tx-list2.o `test -f 'tx-list2.cpp' || echo '$(srcdir)/'`tx-list2.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tx_list2-tx-list2.Tpo $(DEPDIR)/tx_list2-tx-list2.Po @@ -1353,7 +1405,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ - echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ @@ -1366,7 +1418,7 @@ $(TEST_SUITE_LOG): $(TEST_LOGS) fi; \ $$success || exit 1 -check-TESTS: +check-TESTS: $(check_PROGRAMS) @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @@ -1387,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'; \ @@ -1429,8 +1488,10 @@ tx-strquote.log: tx-strquote$(EXEEXT) @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am -distdir: $(DISTFILES) +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -1465,6 +1526,8 @@ check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) +install-checkPROGRAMS: install-libLTLIBRARIES + installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ @@ -1508,7 +1571,61 @@ clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/deque.Plo + -rm -f ./$(DEPDIR)/dl.Plo + -rm -f ./$(DEPDIR)/format.Plo + -rm -f ./$(DEPDIR)/io.Plo + -rm -f ./$(DEPDIR)/map.Plo + -rm -f ./$(DEPDIR)/mc.Plo + -rm -f ./$(DEPDIR)/misc.Plo + -rm -f ./$(DEPDIR)/opt.Plo + -rm -f ./$(DEPDIR)/proc.Plo + -rm -f ./$(DEPDIR)/rand.Plo + -rm -f ./$(DEPDIR)/rtcheck.Plo + -rm -f ./$(DEPDIR)/socket.Plo + -rm -f ./$(DEPDIR)/string.Plo + -rm -f ./$(DEPDIR)/tc-compile.Po + -rm -f ./$(DEPDIR)/tc-deque.Po + -rm -f ./$(DEPDIR)/tc-dir.Po + -rm -f ./$(DEPDIR)/tc-format.Po + -rm -f ./$(DEPDIR)/tc-io.Po + -rm -f ./$(DEPDIR)/tc-list.Po + -rm -f ./$(DEPDIR)/tc-map.Po + -rm -f ./$(DEPDIR)/tc-memmem.Po + -rm -f ./$(DEPDIR)/tc-misc.Po + -rm -f ./$(DEPDIR)/tc-netio.Po + -rm -f ./$(DEPDIR)/tc-option.Po + -rm -f ./$(DEPDIR)/tc-proc.Po + -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 + -rm -f ./$(DEPDIR)/tc-switchuser.Po + -rm -f ./$(DEPDIR)/tc-time.Po + -rm -f ./$(DEPDIR)/tc_cast-tc-cast.Po + -rm -f ./$(DEPDIR)/tc_list2-tc-list2.Po + -rm -f ./$(DEPDIR)/time.Plo + -rm -f ./$(DEPDIR)/tx-cast.Po + -rm -f ./$(DEPDIR)/tx-compile.Po + -rm -f ./$(DEPDIR)/tx-deque.Po + -rm -f ./$(DEPDIR)/tx-dir.Po + -rm -f ./$(DEPDIR)/tx-intdiff.Po + -rm -f ./$(DEPDIR)/tx-list.Po + -rm -f ./$(DEPDIR)/tx-misc.Po + -rm -f ./$(DEPDIR)/tx-netio.Po + -rm -f ./$(DEPDIR)/tx-option.Po + -rm -f ./$(DEPDIR)/tx-proc.Po + -rm -f ./$(DEPDIR)/tx-rand.Po + -rm -f ./$(DEPDIR)/tx-strchr2.Po + -rm -f ./$(DEPDIR)/tx-string.Po + -rm -f ./$(DEPDIR)/tx-strquote.Po + -rm -f ./$(DEPDIR)/tx-time.Po + -rm -f ./$(DEPDIR)/tx_list2-tx-list2.Po + -rm -f ./$(DEPDIR)/ux-file.Plo + -rm -f ./$(DEPDIR)/ux-mmap.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1554,7 +1671,61 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/deque.Plo + -rm -f ./$(DEPDIR)/dl.Plo + -rm -f ./$(DEPDIR)/format.Plo + -rm -f ./$(DEPDIR)/io.Plo + -rm -f ./$(DEPDIR)/map.Plo + -rm -f ./$(DEPDIR)/mc.Plo + -rm -f ./$(DEPDIR)/misc.Plo + -rm -f ./$(DEPDIR)/opt.Plo + -rm -f ./$(DEPDIR)/proc.Plo + -rm -f ./$(DEPDIR)/rand.Plo + -rm -f ./$(DEPDIR)/rtcheck.Plo + -rm -f ./$(DEPDIR)/socket.Plo + -rm -f ./$(DEPDIR)/string.Plo + -rm -f ./$(DEPDIR)/tc-compile.Po + -rm -f ./$(DEPDIR)/tc-deque.Po + -rm -f ./$(DEPDIR)/tc-dir.Po + -rm -f ./$(DEPDIR)/tc-format.Po + -rm -f ./$(DEPDIR)/tc-io.Po + -rm -f ./$(DEPDIR)/tc-list.Po + -rm -f ./$(DEPDIR)/tc-map.Po + -rm -f ./$(DEPDIR)/tc-memmem.Po + -rm -f ./$(DEPDIR)/tc-misc.Po + -rm -f ./$(DEPDIR)/tc-netio.Po + -rm -f ./$(DEPDIR)/tc-option.Po + -rm -f ./$(DEPDIR)/tc-proc.Po + -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 + -rm -f ./$(DEPDIR)/tc-switchuser.Po + -rm -f ./$(DEPDIR)/tc-time.Po + -rm -f ./$(DEPDIR)/tc_cast-tc-cast.Po + -rm -f ./$(DEPDIR)/tc_list2-tc-list2.Po + -rm -f ./$(DEPDIR)/time.Plo + -rm -f ./$(DEPDIR)/tx-cast.Po + -rm -f ./$(DEPDIR)/tx-compile.Po + -rm -f ./$(DEPDIR)/tx-deque.Po + -rm -f ./$(DEPDIR)/tx-dir.Po + -rm -f ./$(DEPDIR)/tx-intdiff.Po + -rm -f ./$(DEPDIR)/tx-list.Po + -rm -f ./$(DEPDIR)/tx-misc.Po + -rm -f ./$(DEPDIR)/tx-netio.Po + -rm -f ./$(DEPDIR)/tx-option.Po + -rm -f ./$(DEPDIR)/tx-proc.Po + -rm -f ./$(DEPDIR)/tx-rand.Po + -rm -f ./$(DEPDIR)/tx-strchr2.Po + -rm -f ./$(DEPDIR)/tx-string.Po + -rm -f ./$(DEPDIR)/tx-strquote.Po + -rm -f ./$(DEPDIR)/tx-time.Po + -rm -f ./$(DEPDIR)/tx_list2-tx-list2.Po + -rm -f ./$(DEPDIR)/ux-file.Plo + -rm -f ./$(DEPDIR)/ux-mmap.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -1575,17 +1746,17 @@ uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ - clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool cscopelist-am ctags ctags-am distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am \ - install-libLTLIBRARIES install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ diff --git a/src/deque.c b/src/deque.c index 3ff7dc9..bc39e0e 100644 --- a/src/deque.c +++ b/src/deque.c @@ -122,6 +122,8 @@ EXPORT_SYMBOL void *HXdeque_del(struct HXdeque_node *node) EXPORT_SYMBOL void HXdeque_free(struct HXdeque *dq) { + if (dq == NULL) + return; struct HXdeque_node *node, *next; for (node = dq->first; node != NULL; node = next) { next = node->next; diff --git a/src/format.c b/src/format.c index 0c463b0..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,10 +103,13 @@ 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) { + if (blk == NULL) + return; HXmap_free(blk->vars); HXmap_free(blk->funcs); free(blk); @@ -295,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; @@ -304,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; } @@ -641,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; @@ -677,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; @@ -688,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) @@ -703,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; @@ -713,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 d348520..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> @@ -42,6 +43,9 @@ #define MAXLNLEN 1024 /* max length for usual line */ #define HXMC_IDENT 0x200571AF +#if !defined(__cplusplus) +# define nullptr NULL +#endif struct memcont { size_t alloc, length; @@ -53,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 */ @@ -7,6 +7,9 @@ * General Public License as published by the Free Software Foundation; * either version 2.1 or (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include <sys/stat.h> #include <errno.h> #include <fcntl.h> @@ -14,6 +17,7 @@ #include <stdarg.h> #include <stdbool.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -25,12 +29,18 @@ # include <dirent.h> # include <unistd.h> #endif +#if __linux__ +# include <sys/sendfile.h> +#endif #include <libHX/ctype_helper.h> #include <libHX/defs.h> #include <libHX/io.h> #include <libHX/misc.h> #include <libHX/string.h> #include "internal.h" +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif struct HXdir { #if defined _WIN32 @@ -47,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) @@ -159,46 +170,77 @@ EXPORT_SYMBOL void HXdir_close(struct HXdir *d) EXPORT_SYMBOL int HX_copy_file(const char *src, const char *dest, unsigned int opts, ...) { - char buf[MAXLNLEN]; + static const size_t bufsize = 0x10000; + void *buf; unsigned int extra_flags = 0; - int dd, eax = 0, sd, l; + int srcfd, dstfd; - if ((sd = open(src, O_RDONLY | O_BINARY)) < 0) + buf = malloc(bufsize); + if (buf == nullptr) + return -errno; + srcfd = open(src, O_RDONLY | O_BINARY); + if (srcfd < 0) { + free(buf); return -errno; + } if (opts & HXF_KEEP) extra_flags = O_EXCL; - dd = open(dest, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | - extra_flags, S_IRUGO | S_IWUGO); - if (dd < 0) { - eax = errno; - close(sd); - errno = eax; - if (extra_flags != 0 && eax == EEXIST) - return 1; - return -errno; + dstfd = open(dest, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | + extra_flags, S_IRUGO | S_IWUGO); + if (dstfd < 0) { + int saved_errno = errno; + free(buf); + close(srcfd); + return -(errno = saved_errno); } - while ((l = read(sd, buf, MAXLNLEN)) > 0 && write(dd, buf, l) > 0) - ; - close(sd); - if (opts & (HXF_UID | HXF_GID)) { struct stat sb; long uid, gid; va_list argp; va_start(argp, opts); - fstat(dd, &sb); + if (fstat(dstfd, &sb) < 0) { + int saved_errno = errno; + unlink(dest); + close(dstfd); + close(srcfd); + free(buf); + va_end(argp); + return -(errno = saved_errno); + } uid = sb.st_uid; gid = sb.st_gid; if (opts & HXF_UID) uid = va_arg(argp, long); if (opts & HXF_GID) gid = va_arg(argp, long); - if (fchown(dd, uid, gid) < 0) - {}; + if (fchown(dstfd, uid, gid) < 0) { + int saved_errno = errno; + unlink(dest); + close(dstfd); + close(srcfd); + free(buf); + va_end(argp); + return -(errno = saved_errno); + } va_end(argp); } - close(dd); + + while (true) { + ssize_t rdret = HX_sendfile(dstfd, srcfd, SIZE_MAX); + if (rdret == 0) + break; + if (rdret < 0 && errno != EINTR) { + int saved_errno = errno; + close(srcfd); + close(dstfd); + free(buf); + return -(errno = saved_errno); + } + } + close(srcfd); + close(dstfd); + free(buf); return 1; } @@ -228,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)) { @@ -242,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); @@ -285,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; } } @@ -300,27 +345,43 @@ EXPORT_SYMBOL int HX_mkdir(const char *idir, unsigned int mode) /* Readlink - with a trailing zero (provided by HXmc) */ EXPORT_SYMBOL int HX_readlink(hxmc_t **target, const char *path) { - bool dnull = *target == NULL; - char *tb; - int ret; + bool allocate = *target == NULL; + size_t linkbuf_size; - if (dnull) { - *target = HXmc_meminit(NULL, PATH_MAX); + if (allocate) { + linkbuf_size = 32; + *target = HXmc_meminit(NULL, 32); if (*target == NULL) return -errno; + } else { + linkbuf_size = HXmc_length(*target); } - tb = *target; - ret = readlink(path, tb, PATH_MAX); - if (ret < 0) { - ret = -errno; - if (!dnull) { - HXmc_free(*target); - *target = NULL; + while (true) { + ssize_t ret = readlink(path, *target, linkbuf_size); + if (ret < 0) { + int saved_errno = errno; + if (allocate) { + HXmc_free(*target); + *target = nullptr; + } + return -(errno = saved_errno); + } + if (static_cast(size_t, ret) < linkbuf_size) { + (*target)[ret] = '\0'; // please cov-scan + HXmc_setlen(target, ret); // \0 set here anyway + return ret; + } + linkbuf_size *= 2; + if (HXmc_setlen(target, linkbuf_size) == NULL) { + int saved_errno = errno; + if (allocate) { + HXmc_free(*target); + *target = nullptr; + } + return -(errno = saved_errno); } - return ret; } - HXmc_setlen(target, ret); - return ret; + return 0; } /** @@ -449,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; } @@ -533,31 +594,185 @@ EXPORT_SYMBOL int HX_rrmdir(const char *dir) EXPORT_SYMBOL ssize_t HXio_fullread(int fd, void *vbuf, size_t size) { char *buf = vbuf; - size_t rem = size; - ssize_t ret; + size_t done = 0; + if (size > SSIZE_MAX) + size = SSIZE_MAX; - while (rem > 0) { - ret = read(fd, buf, rem); + while (done < size) { + ssize_t ret = read(fd, buf, size - done); if (ret < 0) return ret; - rem -= ret; + else if (ret == 0) + break; + done += ret; buf += ret; } - return size; + return done; } EXPORT_SYMBOL ssize_t HXio_fullwrite(int fd, const void *vbuf, size_t size) { const char *buf = vbuf; - size_t rem = size; - ssize_t ret; + size_t done = 0; + if (size > SSIZE_MAX) + size = SSIZE_MAX; - while (rem > 0) { - ret = write(fd, buf, rem); + while (done < size) { + ssize_t ret = write(fd, buf, size - done); if (ret < 0) return ret; - rem -= ret; + else if (ret == 0) + break; + done += ret; buf += ret; } - return size; + return done; +} + +#if __linux__ +static ssize_t HX_sendfile_linux(int dst, int src, size_t count) +{ + long pagesize = sysconf(_SC_PAGE_SIZE); + size_t xfersize; + ssize_t ret, xferd = 0; + + if (pagesize < 0) + pagesize = 4096; + xfersize = SSIZE_MAX - pagesize; + if (count > xfersize) + count = xfersize; + while ((ret = sendfile(dst, src, nullptr, count)) > 0) + xferd += ret; + if (xferd > 0) + return xferd; + if (ret < 0) + return -errno; + return 0; +} +#endif + +static ssize_t HX_sendfile_rw(int dst, int src, size_t count) +{ + static const size_t bufsize = 0x10000; + size_t xferd = 0; + ssize_t ret; + void *buf = malloc(bufsize); + if (buf == nullptr) + return -ENOMEM; + if (count > SSIZE_MAX) + count = SSIZE_MAX; + while (count > 0) { + size_t readsize = bufsize; + if (count < readsize) + readsize = count; + ret = HXio_fullread(src, buf, readsize); + if (ret < 0) { + errno = -ret; + break; + } + ret = HXio_fullwrite(dst, buf, ret); + if (ret < 0) { + errno = -ret; + break; + } + xferd += ret; + count -= ret; + } + free(buf); + if (xferd > 0) + return xferd; + if (ret < 0) + return -errno; + return 0; +} + +EXPORT_SYMBOL ssize_t HX_sendfile(int dst, int src, size_t count) +{ +#if __linux__ + ssize_t ret = HX_sendfile_linux(dst, src, count); + if (ret != -ENOSYS) + return ret; +#endif + return HX_sendfile_rw(dst, src, count); +} + +EXPORT_SYMBOL char *HX_slurp_fd(int fd, size_t *outsize) +{ + struct stat sb; + if (fstat(fd, &sb) < 0) + return NULL; + if (sb.st_size == 0) { + /* e.g. ttys (S_ISCHR) or special procfs files */ + size_t bufsize = 4096, offset = 0; + char *buf = malloc(bufsize); + if (buf == nullptr) + return nullptr; + ssize_t rdret; + while ((rdret = read(fd, buf + offset, bufsize - 1 - offset)) > 0) { + offset += rdret; + /* + * Make it so that the next read call is not called + * with an exceptionally small size. + */ + if (bufsize - offset >= 4095) + continue; + if (bufsize > SSIZE_MAX) + /* No more doubling */ + break; + bufsize *= 2; + void *nbuf = realloc(buf, bufsize + 1); + if (nbuf == nullptr) { + int se = errno; + free(buf); + errno = se; + return nullptr; + } + buf = nbuf; + } + buf[offset] = '\0'; + if (outsize != nullptr) + *outsize = offset; + return buf; + } + size_t fsize = sb.st_size; /* may truncate from loff_t to size_t */ + if (fsize == SIZE_MAX) + --fsize; +#ifdef HAVE_POSIX_FADVISE + if (fsize > 0 && posix_fadvise(fd, 0, fsize, + POSIX_FADV_SEQUENTIAL) != 0) + /* ignore */; +#endif + char *buf = malloc(fsize + 1); + if (buf == NULL) + return NULL; + ssize_t rdret = HXio_fullread(fd, buf, fsize); + if (rdret < 0) { + int se = errno; + free(buf); + errno = se; + return NULL; + } + buf[rdret] = '\0'; + if (outsize != NULL) + *outsize = rdret; + return buf; +} + +EXPORT_SYMBOL char *HX_slurp_file(const char *file, size_t *outsize) +{ + int fd = open(file, O_RDONLY | O_BINARY | O_CLOEXEC); + if (fd < 0) + return NULL; + size_t tmpsize; + if (outsize == NULL) + outsize = &tmpsize; + char *buf = HX_slurp_fd(fd, outsize); + if (buf == NULL) { + int se = errno; + close(fd); + errno = se; + return NULL; + } + close(fd); + return buf; } diff --git a/src/libHX.map b/src/libHX.map index d5ea9c7..c4cef55 100644 --- a/src/libHX.map +++ b/src/libHX.map @@ -126,3 +126,36 @@ global: local: *; }; + +LIBHX_3.27 { +global: + HX_socket_from_env; + HX_slurp_fd; + HX_slurp_file; + HXproc_switch_user; + HXproc_top_fd; +} LIBHX_3.25; + +LIBHX_4.2 { +global: + HX_strtod_unit; + HX_strtoull_unit; + HX_unit_size; + HX_unit_size_cu; +} LIBHX_3.27; + +LIBHX_4.3 { +global: + HX_sendfile; + 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; @@ -102,6 +102,8 @@ static void HXrbtree_free(struct HXrbtree *btree) EXPORT_SYMBOL void HXmap_free(struct HXmap *xmap) { + if (xmap == NULL) + return; void *vmap = xmap; const struct HXmap_private *map = vmap; @@ -1302,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; @@ -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) @@ -79,11 +83,13 @@ EXPORT_SYMBOL hxmc_t *HXmc_memcpy(hxmc_t **vp, const void *ptr, size_t len) if (ptr == NULL) { ctx->length = 0; ctx->data[0] = '\0'; + // coverity[leaked_storage] return *vp = ctx->data; } memcpy(ctx->data, ptr, ctx->length = len); ctx->data[len] = '\0'; + // coverity[leaked_storage] return *vp = ctx->data; } @@ -94,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; } @@ -113,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) @@ -123,6 +131,7 @@ EXPORT_SYMBOL hxmc_t *HXmc_trunc(hxmc_t **vp, size_t len) ctx->data[len] = '\0'; ctx->length = len; } + // coverity[leaked_storage] return *vp = ctx->data; } @@ -138,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) @@ -146,11 +156,13 @@ EXPORT_SYMBOL hxmc_t *HXmc_memcat(hxmc_t **vp, const void *ptr, size_t len) ctx->alloc = nl; } if (ptr == NULL) + // coverity[leaked_storage] return *vp = ctx->data; memcpy(ctx->data + ctx->length, ptr, len); ctx->length = nl; ctx->data[nl] = '\0'; + // coverity[leaked_storage] return *vp = ctx->data; } @@ -186,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) @@ -200,14 +213,15 @@ EXPORT_SYMBOL hxmc_t *HXmc_memins(hxmc_t **vp, size_t pos, const void *ptr, memcpy(ctx->data + pos, ptr, len); ctx->length += len; ctx->data[ctx->length] = '\0'; + // coverity[leaked_storage] return *vp = ctx->data; } 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; @@ -224,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); } @@ -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,12 +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)) { 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 @@ -776,6 +785,14 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, *argv = nvec; if (argc != NULL) *argc = argk; + /* 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)); @@ -786,13 +803,9 @@ EXPORT_SYMBOL int HX_getopt(const struct HXoption *table, int *argc, else if (ps.flags & HXOPT_USAGEONERR) HX_getopt_usage(&ps.cbi, stderr); } - - HXdeque_free(ps.remaining); + 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) @@ -1011,6 +1024,8 @@ EXPORT_SYMBOL int HX_shconfig_pv(const char **path, const char *file, EXPORT_SYMBOL void HX_shconfig_free(const struct HXoption *table) { + if (table == NULL) + return; for (; table->ln != NULL; ++table) { char **ptr = table->ptr; if (table->type == HXTYPE_STRING && @@ -7,42 +7,118 @@ * General Public License as published by the Free Software Foundation; * either version 2.1 or (at your option) any later version. */ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "internal.h" - -#if !defined(HAVE_FORK) || !defined(HAVE_PIPE) || !defined(HAVE_EXECV) || \ - !defined(HAVE_EXECVP) #include <errno.h> +#include <limits.h> +#include <unistd.h> +#ifdef HAVE_SYS_RESOURCE_H +# include <sys/resource.h> +#endif #include <libHX/proc.h> +#ifdef _WIN32 +# include <winsock2.h> +#endif -struct HXproc; +#if defined(HAVE_INITGROUPS) && defined(HAVE_SETGID) +#include <grp.h> +#include <pwd.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> -EXPORT_SYMBOL int HXproc_run_async(const char *const *argv, struct HXproc *p) +static int HXproc_switch_gid(const struct passwd *pw, gid_t gr_gid) { - return -ENOSYS; + bool do_setgid = getgid() != gr_gid || getegid() != gr_gid; + if (do_setgid && setgid(gr_gid) != 0) { + if (errno == 0) + errno = -EINVAL; + return HXPROC_SETGID_FAILED; + } + if (pw == NULL) + return do_setgid ? HXPROC_SU_SUCCESS : HXPROC_SU_NOOP; + + /* pw!=NULL: user switch requested, do initgroups now. */ + + if (geteuid() == pw->pw_uid) { + /* + * Target identity (usually unprivileged) already reached. + * initgroups is unlikely to succeed. + */ + if (initgroups(pw->pw_name, gr_gid) < 0) + /* ignore */; + return do_setgid ? HXPROC_SU_SUCCESS : HXPROC_SU_NOOP; + } + if (initgroups(pw->pw_name, gr_gid) != 0) + return HXPROC_INITGROUPS_FAILED; + return do_setgid ? HXPROC_SU_SUCCESS : HXPROC_SU_NOOP; } -EXPORT_SYMBOL int HXproc_run_sync(const char *const *argv, unsigned int flags) +static int HXproc_switch_group(const struct passwd *pw, const char *group) { - /* Might use system() here... */ - return -ENOSYS; + char *end; + unsigned long gid = strtoul(group, &end, 10); + const struct group *gr = *end == '\0' ? getgrgid(gid) : getgrnam(group); + if (gr == NULL) { + if (errno == 0) + errno = ENOENT; + return HXPROC_GROUP_NOT_FOUND; + } + return HXproc_switch_gid(pw, gr->gr_gid); } -EXPORT_SYMBOL int HXproc_wait(struct HXproc *p) +EXPORT_SYMBOL int HXproc_switch_user(const char *user, const char *group) +{ + const struct passwd *pw = NULL; + if (user != NULL && *user != '\0') { + char *end; + unsigned long uid = strtoul(user, &end, 10); + pw = *end == '\0' ? getpwuid(uid) : getpwnam(user); + if (pw == NULL) { + if (errno == 0) + errno = ENOENT; + return HXPROC_USER_NOT_FOUND; + } + } + int ret = HXPROC_SU_NOOP; + if (group != NULL && *group != '\0') { + ret = HXproc_switch_group(pw, group); + if (ret < 0) + return ret; + } else if (group == NULL && pw != NULL) { + ret = HXproc_switch_gid(pw, pw->pw_gid); + if (ret < 0) + return ret; + } + bool do_setuid = pw != NULL && (getuid() != pw->pw_uid || geteuid() != pw->pw_uid); + if (do_setuid && setuid(pw->pw_uid) != 0) { + if (errno == 0) + errno = -EINVAL; + return HXPROC_SETUID_FAILED; + } + return do_setuid ? HXPROC_SU_SUCCESS : ret; +} + +#else + +EXPORT_SYMBOL int HXproc_switch_user(const char *user, const char *group) { return -ENOSYS; } -#else /* HAVE_FORK, HAVE_PIPE, HAVE_EXECVE */ +#endif /* HAVE_lots */ +#if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_EXECV) && \ + defined(HAVE_EXECVP) #include <sys/wait.h> #include <fcntl.h> -#include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <libHX/defs.h> -#include <libHX/proc.h> #include "internal.h" #ifdef _WIN32 @@ -88,18 +164,20 @@ HXproc_build_pipes(const struct HXproc *proc, int (*p)[2]) */ static void HXproc_close_pipes(int (*p)[2]) { +#define xc(fd) do { close(fd); (fd) = -1; } while (false) if (p[0][0] >= 0) - close(p[0][0]); + xc(p[0][0]); if (p[0][1] >= 0) - close(p[0][1]); + xc(p[0][1]); if (p[1][0] >= 0) - close(p[1][0]); + xc(p[1][0]); if (p[1][1] >= 0) - close(p[1][1]); + xc(p[1][1]); if (p[2][0] >= 0) - close(p[2][0]); + xc(p[2][0]); if (p[2][1] >= 0) - close(p[2][1]); + xc(p[2][1]); +#undef xc } /** @@ -113,29 +191,27 @@ EXPORT_SYMBOL int HXproc_run_async(const char *const *argv, struct HXproc *proc) { int pipes[3][2], nullfd = -1, ret, saved_errno; - unsigned int t; if (argv == NULL || *argv == NULL) return -EFAULT; - - proc->p_stdin = proc->p_stdout = proc->p_stderr = -1; - - t = (proc->p_flags & (HXPROC_STDIN | HXPROC_NULL_STDIN)) == - (HXPROC_STDIN | HXPROC_NULL_STDIN); - t |= (proc->p_flags & (HXPROC_STDOUT | HXPROC_NULL_STDOUT)) == - (HXPROC_STDOUT | HXPROC_NULL_STDOUT); - t |= (proc->p_flags & (HXPROC_STDERR | HXPROC_NULL_STDERR)) == - (HXPROC_STDERR | HXPROC_NULL_STDERR); - if (t > 0) + if ((proc->p_flags & (HXPROC_STDIN | HXPROC_NULL_STDIN)) == + (HXPROC_STDIN | HXPROC_NULL_STDIN)) + return -EINVAL; + if ((proc->p_flags & (HXPROC_STDOUT | HXPROC_NULL_STDOUT)) == + (HXPROC_STDOUT | HXPROC_NULL_STDOUT)) + return -EINVAL; + if ((proc->p_flags & (HXPROC_STDERR | HXPROC_NULL_STDERR)) == + (HXPROC_STDERR | HXPROC_NULL_STDERR)) return -EINVAL; - if (proc->p_flags & (HXPROC_NULL_STDIN | HXPROC_NULL_STDOUT | HXPROC_NULL_STDERR)) { if ((nullfd = open(NULL_DEVICE, O_RDWR)) < 0) return -errno; } + proc->p_stdin = proc->p_stdout = proc->p_stderr = -1; if ((ret = HXproc_build_pipes(proc, pipes)) <= 0) { saved_errno = errno; + HXproc_close_pipes(pipes); if (nullfd >= 0) close(nullfd); errno = saved_errno; @@ -183,17 +259,17 @@ HXproc_run_async(const char *const *argv, struct HXproc *proc) */ HXproc_close_pipes(pipes); if ((proc->p_flags & (HXPROC_STDIN | HXPROC_NULL_STDIN)) && - proc->p_stdin != STDIN_FILENO) { + proc->p_stdin >= 0 && proc->p_stdin != STDIN_FILENO) { dup2(proc->p_stdin, STDIN_FILENO); close(proc->p_stdin); } if ((proc->p_flags & (HXPROC_STDOUT | HXPROC_NULL_STDOUT)) && - proc->p_stdout != STDOUT_FILENO) { + proc->p_stdout >= 0 && proc->p_stdout != STDOUT_FILENO) { dup2(proc->p_stdout, STDOUT_FILENO); close(proc->p_stdout); } if ((proc->p_flags & (HXPROC_STDERR | HXPROC_NULL_STDERR)) && - proc->p_stderr != STDERR_FILENO) { + proc->p_stderr >= 0 && proc->p_stderr != STDERR_FILENO) { dup2(proc->p_stderr, STDERR_FILENO); close(proc->p_stderr); } @@ -223,7 +299,8 @@ HXproc_run_async(const char *const *argv, struct HXproc *proc) close(pipes[2][1]); proc->p_stderr = pipes[2][0]; } - + if (nullfd >= 0) + close(nullfd); return 1; } @@ -266,4 +343,41 @@ EXPORT_SYMBOL int HXproc_wait(struct HXproc *proc) return static_cast(unsigned char, proc->p_status); } +#else + +EXPORT_SYMBOL int HXproc_run_async(const char *const *argv, struct HXproc *p) +{ + return -ENOSYS; +} + +EXPORT_SYMBOL int HXproc_run_sync(const char *const *argv, unsigned int flags) +{ + /* Might use system() here... */ + return -ENOSYS; +} + +EXPORT_SYMBOL int HXproc_wait(struct HXproc *p) +{ + return -ENOSYS; +} + #endif /* HAVE_lots */ + +EXPORT_SYMBOL int HXproc_top_fd(void) +{ +#ifndef _WIN32 + struct rlimit r; + if (getrlimit(RLIMIT_NOFILE, &r) == 0) { + if (r.rlim_max > INT_MAX) + r.rlim_max = INT_MAX; + return r.rlim_max; + } + long v = sysconf(_SC_OPEN_MAX); + if (v >= 0) { + if (v > INT_MAX) + v = INT_MAX; + return v; + } +#endif + return FD_SETSIZE; +} diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..ced884a --- /dev/null +++ b/src/socket.c @@ -0,0 +1,305 @@ +/* + * Socket-related functions + * Copyright Jan Engelhardt, 2021 + * + * This file is part of libHX. libHX is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software Foundation; + * either version 2.1 or (at your option) any later version. + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#ifdef _WIN32 +# include <ws2tcpip.h> +#else +# 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> +#include "internal.h" +#ifdef _WIN32 +# define STUPIDWIN(x) reinterpret_cast(char *, (x)) +#else +# define STUPIDWIN(x) (x) +#endif +#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) +{ + int value = 0; + socklen_t optlen = sizeof(value); + int ret = getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, STUPIDWIN(&value), &optlen); + if (ret < 0 && errno != ENOPROTOOPT) + /* + * E.g. OpenBSD's getsockopt does not recognize this - even + * though the flag with the same name exists and is known. + */ + return -1; + if (ret == 0 && value == 0) + return -1; +#ifdef _WIN32 + WSAPROTOCOL_INFO protinfo; + optlen = sizeof(protinfo); + ret = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, STUPIDWIN(&protinfo), &optlen); + if (ret < 0 || protinfo.iAddressFamily != ai->ai_family || + protinfo.iSocketType != ai->ai_socktype || + protinfo.iProtocol != ai->ai_protocol) + return -1; +#else + optlen = sizeof(value); + ret = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &value, &optlen); + if (ret < 0 || value != ai->ai_family) + return -1; + optlen = sizeof(value); + ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &value, &optlen); + if (ret < 0 || value != ai->ai_socktype) + return -1; + optlen = sizeof(value); + ret = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &value, &optlen); + if (ret < 0 || value != ai->ai_protocol) + return -1; +#endif + struct sockaddr_storage addr; + memset(&addr, 0, sizeof(addr)); + optlen = sizeof(addr); + ret = getsockname(fd, (struct sockaddr *)&addr, &optlen); + if (ret < 0) + return -1; + if (sizeof(addr) < optlen) + optlen = sizeof(addr); + if (optlen != ai->ai_addrlen || memcmp(&addr, ai->ai_addr, optlen) != 0) + return -1; + if (intf == nullptr) + return fd; +#ifdef SO_BINDTODEVICE + char ifname[32]; + optlen = sizeof(ifname); + ret = getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, &optlen); + if (ret < 0) + return -1; + else if (optlen < sizeof(ifname)) + ifname[optlen] = '\0'; + else + ifname[sizeof(ifname)-1] = '\0'; + if (strcmp(intf, ifname) != 0) + return -1; +#endif + return fd; +} + +EXPORT_SYMBOL int HX_socket_from_env(const struct addrinfo *ai, const char *intf) +{ + int top_fd; + const char *env_limit = getenv("LISTEN_FDS"); + if (env_limit != nullptr) { + long x = strtol(env_limit, nullptr, 0); + if (x > INT_MAX - 3) + x = INT_MAX - 3; + top_fd = 3 + x; + } else { + env_limit = getenv("HX_LISTEN_TOP_FD"); + long x; + if (env_limit != nullptr) { + x = strtol(env_limit, nullptr, 0); + if (x > INT_MAX) + x = INT_MAX; + } else { + x = HXproc_top_fd(); + } + top_fd = x; + } + for (int fd = 3; fd < top_fd; ++fd) + if (try_sk_from_env(fd, ai, intf) == fd) + return fd; + 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 354a409..ae19271 100644 --- a/src/string.c +++ b/src/string.c @@ -8,6 +8,8 @@ * either version 2.1 or (at your option) any later version. */ #include <errno.h> +#include <limits.h> +#include <math.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> @@ -25,6 +27,7 @@ * all others pass through */ enum HX_quote_selector { + HXQUOTE_ALWAYS, HXQUOTE_ACCEPT, HXQUOTE_REJECT, }; @@ -40,11 +43,6 @@ struct HX_quote_rule { static const char HX_hexenc[16] = "0123456789ABCDEF"; -static __inline__ unsigned int min_uint(unsigned int a, unsigned int b) -{ - return (a < b) ? a : b; -} - EXPORT_SYMBOL char *HX_basename(const char *s) { const char *p; @@ -214,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; { @@ -381,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) @@ -605,14 +633,16 @@ HX_quote_sqlbackslash(char *dest, const char *src, const char *trm) * Encode @src into BASE-64 according to RFC 4648 and write result to @dest, * which must be of appropriate size, plus one for a trailing NUL. */ -static char *HX_quote_base64(char *d, const char *s) +static char *HX_quote_base64(char *d, const char *s, char x1, char x2) { - static const char a[] = + char a[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; + "abcdefghijklmnopqrstuvwxyz0123456789??"; size_t len = strlen(s); char *ret = d; + a[62] = x1; + a[63] = x2; while (len > 0) { if (len >= 3) { len -= 3; @@ -761,6 +791,8 @@ static size_t HX_quoted_size(const char *s, unsigned int type) case HXQUOTE_LDAPRDN: return HX_qsize_bsr(s, HX_quote_rules[type].chars, 2); case HXQUOTE_BASE64: + case HXQUOTE_BASE64URL: + case HXQUOTE_BASE64IMAP: return (strlen(s) + 2) / 3 * 4; case HXQUOTE_URIENC: return HX_qsize_bsa(s, HX_quote_rules[type].chars, 2); @@ -772,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; @@ -781,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. @@ -819,7 +855,11 @@ EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type, case HXQUOTE_LDAPRDN: return HX_quote_ldap(*free_me, src, rule->chars); case HXQUOTE_BASE64: - return HX_quote_base64(*free_me, src); + return HX_quote_base64(*free_me, src, '+', '/'); + case HXQUOTE_BASE64URL: + return HX_quote_base64(*free_me, src, '-', '_'); + case HXQUOTE_BASE64IMAP: + return HX_quote_base64(*free_me, src, '+', ','); case HXQUOTE_URIENC: return HX_quote_urlenc(*free_me, src); case HXQUOTE_SQLSQUOTE: @@ -836,3 +876,289 @@ EXPORT_SYMBOL char *HX_strupper(char *orig) *expr = HX_toupper(*expr); return orig; } + +EXPORT_SYMBOL char *HX_unit_size(char *buf, size_t bufsize, + unsigned long long size, unsigned int divisor, unsigned int cutoff) +{ + static const char unit_names[] = "\0kMGTPEZYRQ"; + unsigned int unit_idx = 0; + if (divisor == 0) + divisor = 1000; + if (cutoff == 0) { + cutoff = 10000; + if (cutoff < divisor) + cutoff = divisor; + } + while (unit_idx < ARRAY_SIZE(unit_names) - 1 && size >= cutoff) { + ++unit_idx; + size /= divisor; + } + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + return buf; +} + +static inline unsigned long long p_90(unsigned long long x) +{ + /* Perform x*9/10, but without the risk of overflow. */ + return x - x / 10 - !!(x % 10); +} + +EXPORT_SYMBOL char *HX_unit_size_cu(char *buf, size_t bufsize, + unsigned long long orig_size, unsigned int divisor) +{ + /* No floating point. Take that, coreutils! */ + static const char unit_names[] = "\0kMGTPEZYRQ"; + unsigned int unit_idx = 0, last_rem = 0; + unsigned long long size = orig_size, gpow = 1, grand_rem; + if (divisor == 0) + divisor = 1000; + + while (unit_idx < ARRAY_SIZE(unit_names) - 1 && size >= divisor) { + ++unit_idx; + last_rem = size % divisor; + size /= divisor; + gpow *= divisor; + } + if (unit_idx == 0) { + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + return buf; + } + grand_rem = orig_size - size * gpow; + if (grand_rem != 0) { + if (grand_rem > p_90(gpow)) { + ++size; + last_rem = 0; + } else { + last_rem *= 10; + last_rem /= divisor; + ++last_rem; + if (last_rem == 10 || (size >= 10 && last_rem > 0)) { + ++size; + last_rem = 0; + } + } + if (unit_idx < ARRAY_SIZE(unit_names) - 1 && size == divisor) { + /* ++size from above may brought size to @divisor again */ + ++unit_idx; + size /= divisor; + } + } + if (size >= 10 && last_rem == 0) + snprintf(buf, bufsize, "%llu%.1s", size, &unit_names[unit_idx]); + else + snprintf(buf, bufsize, "%llu.%01u%.1s", size, last_rem, &unit_names[unit_idx]); + return buf; +} + +static unsigned int suffix_power(char u) +{ + switch (HX_toupper(u)) { + case 'K': return 1; + case 'M': return 2; + case 'G': return 3; + case 'T': return 4; + case 'P': return 5; + case 'E': return 6; + case 'Z': return 7; + case 'Y': return 8; + case 'R': return 9; + case 'Q': return 10; + default: return 0; + } +} + +EXPORT_SYMBOL double HX_strtod_unit(const char *s, char **out_end, unsigned int exponent) +{ + char *end; + double q; + + while (HX_isspace(*s)) + ++s; + q = strtod(s, &end); + if (exponent == 0) + exponent = 1000; + if (end == s) { + if (out_end != nullptr) + *out_end = end; + return q; + } + while (HX_isspace(*end)) + ++end; + unsigned int pwr = suffix_power(*end); + if (pwr == 0) { + if (out_end != nullptr) + *out_end = const_cast(char *, end); + return q; + } + if (out_end != nullptr) + *out_end = const_cast(char *, end + 1); + return q * pow(exponent, pwr); +} + +EXPORT_SYMBOL unsigned long long HX_strtoull_unit(const char *s, + char **out_end, unsigned int exponent) +{ + char *end; + unsigned long long ipart; + unsigned int pwr = 0; + + while (HX_isspace(*s)) + ++s; + ipart = strtoull(s, &end, 10); + if (*end == '.') { + double q = HX_strtod_unit(s, out_end, exponent); + bool lo_ok = q >= nextafter(-static_cast(double, ULLONG_MAX), 0); + bool hi_ok = q <= nextafter(static_cast(double, ULLONG_MAX), 0); + if (!hi_ok || !lo_ok) + return ULLONG_MAX; + return q; + } + if (exponent == 0) + exponent = 1000; + while (HX_isspace(*end)) + ++end; + pwr = suffix_power(*end); + if (pwr == 0) { + if (out_end != nullptr) + *out_end = end; + return ipart; + } + if (out_end != nullptr) + *out_end = const_cast(char *, end + 1); + while (pwr-- > 0) { + if (ipart >= ULLONG_MAX / exponent) { + errno = ERANGE; + return ULLONG_MAX; + } + ipart *= exponent; + } + return ipart; +} + +#define SECONDS_PER_YEAR 31557600 +#define SECONDS_PER_MONTH 2629800 + +static const struct { + const char name[8]; + unsigned int len; + uint32_t mult; +} time_multiplier[] = { + {"seconds", 7, 1}, + {"second", 6, 1}, + {"sec", 3, 1}, + {"s", 1, 1}, + {"minutes", 7, 60}, + {"minute", 6, 60}, + {"min", 3, 60}, + {"hours", 5, 3600}, + {"hour", 4, 3600}, + {"h", 1, 3600}, + {"days", 4, 86400}, + {"day", 3, 86400}, + {"d", 1, 86400}, + {"weeks", 5, 604800}, + {"week", 4, 604800}, + {"months", 6, SECONDS_PER_MONTH}, + {"month", 5, SECONDS_PER_MONTH}, + {"years", 5, SECONDS_PER_YEAR}, + {"year", 4, SECONDS_PER_YEAR}, + {"y", 1, SECONDS_PER_YEAR}, +}; + +EXPORT_SYMBOL unsigned long long HX_strtoull_sec(const char *s, char **out_end) +{ + unsigned long long seconds = 0; + + while (*s != '\0') { + while (HX_isspace(*s)) + ++s; + if (*s == '-') { + break; + } + char *end = nullptr; + unsigned long long num = strtoull(s, &end, 10); + if (end == s) + break; + s = end; + while (HX_isspace(*s)) + ++s; + if (!HX_isalpha(*s)) { + seconds += num; + continue; + } + unsigned int i; + for (i = 0; i < ARRAY_SIZE(time_multiplier); ++i) + if (strncmp(s, time_multiplier[i].name, + time_multiplier[i].len) == 0 && + !HX_isalpha(s[time_multiplier[i].len])) + break; + if (i == ARRAY_SIZE(time_multiplier)) + break; + seconds += num * time_multiplier[i].mult; + s += time_multiplier[i].len; + } + if (out_end != nullptr) + *out_end = const_cast(char *, s); + return seconds; +} + +EXPORT_SYMBOL char *HX_unit_seconds(char *out, size_t outsize, + unsigned long long secs, unsigned int flags) +{ + unsigned long years = 0, months = 0, weeks = 0, days, hours, mins; + char buf[HXSIZEOF_Z64+4]; + if (flags & HXUNIT_YEARS) { + years = secs / SECONDS_PER_YEAR; + secs %= SECONDS_PER_YEAR; + } + if (flags & HXUNIT_MONTHS) { + months = secs / SECONDS_PER_MONTH; + secs %= SECONDS_PER_MONTH; + } + if (flags & HXUNIT_WEEKS) { + weeks = secs / 604800; + secs %= 604800; + } + days = secs / 86400; + secs %= 86400; + hours = secs / 3600; + secs %= 3600; + mins = secs / 60; + secs %= 60; + *out = '\0'; + if (years > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%luy", years); + HX_strlcat(out, buf, outsize); + } + if (months == 1) { + HX_strlcat(out, "1month", outsize); + } else if (months > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%lumonths", months); + HX_strlcat(out, buf, outsize); + } + if (weeks == 1) { + HX_strlcat(out, "1week", outsize); + } else if (weeks > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%luweeks", weeks); + HX_strlcat(out, buf, outsize); + } + if (days > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%lud", days); + HX_strlcat(out, buf, outsize); + } + if (hours > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%luh", hours); + HX_strlcat(out, buf, outsize); + } + if (mins > 0) { + snprintf(buf, ARRAY_SIZE(buf), "%lumin", mins); + HX_strlcat(out, buf, outsize); + } + if (secs > 0 || + (years == 0 && months == 0 && weeks == 0 && + days == 0 && hours == 0 && mins == 0)) { + snprintf(buf, ARRAY_SIZE(buf), "%llus", secs); + HX_strlcat(out, buf, outsize); + } + return out; +} 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-compile.c b/src/tc-compile.c index 657f4f7..d2b0d09 100644 --- a/src/tc-compile.c +++ b/src/tc-compile.c @@ -10,11 +10,11 @@ int main(void) { - unsigned long long bmllong[HXbitmap_size(unsigned long long, 256)]; - unsigned long bmlong[HXbitmap_size(unsigned long, 256)]; - unsigned int bmint[HXbitmap_size(unsigned int, 256)]; - unsigned short bmshort[HXbitmap_size(unsigned short, 256)]; - unsigned char bmchar[HXbitmap_size(unsigned char, 256)]; + unsigned long long bmllong[HXbitmap_size(unsigned long long, 256)] = {0}; + unsigned long bmlong[HXbitmap_size(unsigned long, 256)] = {0}; + unsigned int bmint[HXbitmap_size(unsigned int, 256)] = {0}; + unsigned short bmshort[HXbitmap_size(unsigned short, 256)] = {0}; + unsigned char bmchar[HXbitmap_size(unsigned char, 256)] = {0}; if (HX_init() <= 0) abort(); 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 new file mode 100644 index 0000000..639ebcc --- /dev/null +++ b/src/tc-io.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <libHX/io.h> +#include "internal.h" + +static void sf(void) +{ + int src = open("tc-io.c", O_RDONLY); + if (src < 0) + return; + int dst = open("/dev/null", O_WRONLY); + if (dst < 0) { + close(src); + return; + } + ssize_t ret = HX_sendfile(dst, src, SIZE_MAX); + printf("sendfile transferred %zd bytes\n", ret); + close(dst); + close(src); +} + +int main(void) +{ + size_t z; + char *s = HX_slurp_file("tc-io.c", &z); + if (s == nullptr) { + fprintf(stderr, "HX_slurp_file: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + printf("%s\n", s); + printf("Dumped %zu bytes\n", z); + free(s); + s = HX_slurp_file("/proc/version", &z); + if (s == nullptr) { + fprintf(stderr, "HX_slurp_file: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + printf(">%s<\n", s); + free(s); + + sf(); + int ret = HX_copy_file("tc-io.c", "tciocopy.txt", 0); + if (ret <= 0) { + fprintf(stderr, "HX_copy_file: %s\n", strerror(errno)); + } else { + fprintf(stderr, "copy_file ok\n"); + unlink("tciocopy.txt"); + } + return 0; +} diff --git a/src/tc-link.c b/src/tc-link.c deleted file mode 100644 index f20bfd7..0000000 --- a/src/tc-link.c +++ /dev/null @@ -1,156 +0,0 @@ -#include <stdlib.h> -#include <libHX.h> -#include "internal.h" - -static void *funcs[] = { - HXdeque_init, - HXdeque_push, - HXdeque_pop, - HXdeque_unshift, - HXdeque_shift, - HXdeque_move, - HXdeque_del, - HXdeque_free, - HXdeque_find, - HXdeque_get, - HXdeque_genocide2, - HXdeque_to_vec, - HX_dlopen, - HX_dlsym, - HX_dlclose, - HX_dlerror, - HXformat_init, - HXformat_free, - HXformat_add, - HXformat_aprintf, - HXformat_fprintf, - HXformat_sprintf, - HXdir_open, - HXdir_read, - HXdir_close, - HX_copy_file, - HX_copy_dir, - HX_mkdir, - HX_readlink, - HX_realpath, - HX_rrmdir, - HXio_fullread, - HXio_fullwrite, - HXmap_free, - HXhash_jlookup3, - HXhash_jlookup3s, - HXhash_djb2, - HXmap_init5, - HXmap_init, - HXmap_find, - HXmap_get, - HXmap_add, - HXmap_del, - HXmap_keysvalues, - HXmap_travinit, - HXmap_traverse, - HXmap_travfree, - HXmap_qfe, - HXmc_strinit, - HXmc_meminit, - HXmc_strcpy, - HXmc_memcpy, - HXmc_length, - HXmc_setlen, - HXmc_trunc, - HXmc_strcat, - HXmc_memcat, - HXmc_strpcat, - HXmc_mempcat, - HXmc_strins, - HXmc_memins, - HXmc_memdel, - HXmc_free, - HXmc_zvecfree, - HX_ffs, - HX_fls, - HX_hexdump, - HX_zvecfree, - HX_getopt, - HX_getopt_help, - HX_getopt_help_cb, - HX_getopt_usage, - HX_getopt_usage_cb, - HX_shconfig, - HX_shconfig_map, - HX_shconfig_pv, - HX_shconfig_free, - HXproc_run_async, - HXproc_run_sync, - HXproc_wait, - HX_init, - HX_exit, - HX_rand, - HX_drand, - HX_irand, - HX_basename, - HX_basename_exact, - HX_chomp, - HX_dirname, - HX_getl, - HX_memmem, - HX_split, - HX_split_fixed, - HX_split_inplace, - HX_stpltrim, - HX_strbchr, - HX_strchr2, - HX_strclone, - HX_strdup, - HX_strlcat, - HX_strlcpy, - HX_strlncat, - HX_strlower, - HX_strltrim, - HX_strmid, - HX_strndup, - HX_strnlen, - HX_strrcspn, - HX_strrev, - HX_strrtrim, - HX_strsep, - HX_strsep2, - HX_strquote, - HX_strupper, - HX_time_compare, -#ifdef HAVE_STRUCT_TIMESPEC_TV_NSEC - HX_timespec_add, - HX_timespec_isneg, - HX_timespec_mul, - HX_timespec_mulf, - HX_timespec_neg, - HX_timespec_sub, -#endif -#ifdef HAVE_STRUCT_TIMEVAL_TV_USEC - HX_timeval_sub, -#endif -#ifdef _WIN32 - chown, - fchmod, - fchown, - lchown, - lstat, - mkfifo, - mknod, - readlink, - symlink, - mmap, - munmap, -#endif -}; - -int main(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(funcs); ++i) - printf("%p ", funcs[i]); - printf("\n"); - printf("There are %" HX_SIZET_FMT "u exported functions\n", ARRAY_SIZE(funcs)); - return EXIT_SUCCESS; -} diff --git a/src/tc-list.c b/src/tc-list.c index c30f5aa..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> @@ -39,6 +33,8 @@ static void l_init(unsigned int max, bool unshift) obj = new struct text_object; #else obj = malloc(sizeof(*obj)); + if (obj == NULL) + abort(); #endif HXlist_init(&obj->list); obj->id[0] = HX_irand('a', 'z'+1); @@ -111,6 +107,8 @@ static void l_empty(void) static void l_shift(void) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" /* Check for -Wshadow warnings */ struct object { int value; @@ -130,6 +128,7 @@ static void l_shift(void) HXclist_push(&clh, &q.anchor); x = p = HXclist_pop(&clh, struct object, anchor); printf("%d\n", p->value); +#pragma GCC diagnostic pop } int main(int argc, const char **argv) 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 8a22259..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> @@ -25,6 +18,7 @@ #include <sys/time.h> #include "internal.h" #include "map_int.h" +#pragma GCC diagnostic ignored "-Wunused-const-variable" union HXpoly { struct HXmap *map; @@ -60,12 +54,14 @@ static void tmap_printf(const char *fmt, ...) va_end(args); } -static void tmap_time(struct timeval *tv) +static void tmap_time(struct timespec *tv) { #ifdef HAVE_SYS_RESOURCE_H struct rusage r; - if (getrusage(RUSAGE_SELF, &r) == 0) - *tv = r.ru_utime; + if (getrusage(RUSAGE_SELF, &r) == 0) { + tv->tv_sec = r.ru_utime.tv_sec; + tv->tv_nsec = r.ru_utime.tv_usec * 1000; + } #else memset(tv, 0, sizeof(*tv)); #endif @@ -134,7 +130,7 @@ static void tmap_flush(struct HXmap *map, bool verbose) static void tmap_add_speed(struct HXmap *map) { - struct timeval start, stop, delta; + struct timespec start, stop, delta; unsigned int threshold; tmap_printf("MAP test 1: Timing add operation\n"); @@ -143,20 +139,20 @@ static void tmap_add_speed(struct HXmap *map) do { tmap_add_rand(map, 1); tmap_time(&stop); - HX_timeval_sub(&delta, &stop, &start); + HX_timespec_sub(&delta, &stop, &start); } while (!(delta.tv_sec >= 1 || map->items >= 1000000)); - tmap_printf("%u elements in " HX_TIMEVAL_FMT + tmap_printf("%u elements in " HX_TIMESPEC_FMT " (plus time measurement overhead)\n", - map->items, HX_TIMEVAL_EXP(&delta)); + map->items, HX_TIMESPEC_EXP(&delta)); threshold = map->items; tmap_flush(map, false); tmap_time(&start); tmap_add_rand(map, threshold); tmap_time(&stop); - HX_timeval_sub(&delta, &stop, &start); - tmap_printf("%u elements in " HX_TIMEVAL_FMT " (w/o overhead)\n", - map->items, HX_TIMEVAL_EXP(&delta)); + HX_timespec_sub(&delta, &stop, &start); + tmap_printf("%u elements in " HX_TIMESPEC_FMT " (w/o overhead)\n", + map->items, HX_TIMESPEC_EXP(&delta)); tmap_ipop(); } @@ -167,7 +163,7 @@ static bool tmap_each_fn(const struct HXmap_node *node, void *arg) static void tmap_trav_speed(struct HXmap *map) { - struct timeval start, stop, delta, delta2; + struct timespec start, stop, delta, delta2; const struct HXmap_node *node; struct HXmap_trav *iter; @@ -178,17 +174,17 @@ static void tmap_trav_speed(struct HXmap *map) while ((node = HXmap_traverse(iter)) != NULL) ; tmap_time(&stop); - HX_timeval_sub(&delta, &stop, &start); + HX_timespec_sub(&delta, &stop, &start); HXmap_travfree(iter); - tmap_printf("Open traversal of %u nodes: " HX_TIMEVAL_FMT "s\n", - map->items, HX_TIMEVAL_EXP(&delta)); + tmap_printf("Open traversal of %u nodes: " HX_TIMESPEC_FMT "s\n", + map->items, HX_TIMESPEC_EXP(&delta)); tmap_time(&start); HXmap_qfe(map, tmap_each_fn, NULL); tmap_time(&stop); - HX_timeval_sub(&delta, &stop, &start); - tmap_printf("QFE traversal of %u nodes: " HX_TIMEVAL_FMT "s\n", - map->items, HX_TIMEVAL_EXP(&delta)); + HX_timespec_sub(&delta, &stop, &start); + tmap_printf("QFE traversal of %u nodes: " HX_TIMESPEC_FMT "s\n", + map->items, HX_TIMESPEC_EXP(&delta)); tmap_ipop(); tmap_printf("MAP test 2a: Timing lookup\n"); @@ -198,14 +194,14 @@ static void tmap_trav_speed(struct HXmap *map) while ((node = HXmap_traverse(iter)) != NULL) HXmap_find(map, node->key); tmap_time(&stop); - HX_timeval_sub(&delta2, &stop, &start); + HX_timespec_sub(&delta2, &stop, &start); HXmap_travfree(iter); /* delta2 includes traversal time */ start = delta; stop = delta2; - HX_timeval_sub(&delta, &stop, &start); - tmap_printf("Lookup of %u nodes: " HX_TIMEVAL_FMT "s\n", - map->items, HX_TIMEVAL_EXP(&delta)); + HX_timespec_sub(&delta, &stop, &start); + tmap_printf("Lookup of %u nodes: " HX_TIMESPEC_FMT "s\n", + map->items, HX_TIMESPEC_EXP(&delta)); tmap_ipop(); } @@ -222,7 +218,7 @@ static void tmap_flat(const struct HXmap *map) abort(); } for (i = 0; i < map->items; ++i) - tmap_printf("%u. %s -> %s\n", i, nodes[i].key, nodes[i].data); + tmap_printf("%u. %s -> %s\n", i, nodes[i].skey, nodes[i].sdata); tmap_ipop(); free(nodes); } diff --git a/src/tc-memmem.c b/src/tc-memmem.c index 342500f..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> @@ -35,6 +31,7 @@ static void long_scan(void) printf("long_scan: filler2=%p p=%p\n", filler2, p); HX_timespec_sub(&delta, &stop, &start); printf("long_scan: " HX_TIMESPEC_FMT "\n", HX_TIMESPEC_EXP(&delta)); + free(filler2); } int main(void) 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 7ec982f..19c8b18 100644 --- a/src/tc-proc.c +++ b/src/tc-proc.c @@ -1,16 +1,12 @@ -/* - * 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> # include <cstdlib> # include <cstring> #else # include <errno.h> +# include <stdio.h> # include <stdlib.h> # include <string.h> #endif @@ -56,6 +52,7 @@ int main(void) { if (HX_init() <= 0) abort(); + printf("top fd: %d\n", HXproc_top_fd()); /* let it fail - test verbosity */ HXproc_run_sync(t_args1 + 2, HXPROC_VERBOSE); 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 5dd9aa2..23609ca 100644 --- a/src/tc-realpath.c +++ b/src/tc-realpath.c @@ -1,16 +1,13 @@ +// 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> #include <stdlib.h> #include <libHX/io.h> #include <libHX/option.h> +#include <libHX/string.h> static unsigned int rp_flags; static unsigned int rp_absolute; @@ -42,6 +39,14 @@ static bool rp_get_options(int *argc, const char ***argv) return true; } +static void t_1(void) +{ + hxmc_t *tmp = HXmc_strinit(""); + /* two components, so that HX_readlink gets called twice */ + HX_realpath(&tmp, "/dev/tty", HX_REALPATH_DEFAULT); + HXmc_free(tmp); +} + int main(int argc, const char **argv) { hxmc_t *res; @@ -49,6 +54,7 @@ int main(int argc, const char **argv) if (!rp_get_options(&argc, &argv)) return EXIT_FAILURE; + t_1(); res = NULL; while (--argc > 0) { 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 6e85f66..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> @@ -90,9 +84,12 @@ static void t_strncat(void) { char data[5] = "DATA"; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation" if (snprintf(data, sizeof(data), "12345678") >= static_cast(ssize_t, sizeof(data))) printf("Not enough space\n"); +#pragma GCC diagnostic pop printf("String: >%s<\n", data); HX_strlcat(data, "pqrstuv__", 2); @@ -271,11 +268,13 @@ static void t_strlcpy(void) HX_timespec_sub(&d2, &stop, &start); HX_timespec_sub(&d3, &d1, &d2); - printf("%4zu->%4zu: %1ld.%09ld (str=%ld.%09ld mem=%ld.%09ld)\n", + printf("%4zu->%4zu: " HX_TIMESPEC_FMT + " (str=" HX_TIMESPEC_FMT + " mem=" HX_TIMESPEC_FMT ")\n", strlen(ibuf), picksizes[opick], - static_cast(long, d3.tv_sec), d3.tv_nsec, - static_cast(long, d1.tv_sec), d1.tv_nsec, - static_cast(long, d2.tv_sec), d2.tv_nsec + HX_TIMESPEC_EXP(&d3), + HX_TIMESPEC_EXP(&d1), + HX_TIMESPEC_EXP(&d2) ); } } @@ -288,6 +287,222 @@ static void t_strlcpy2(void) assert(a[0] == 49 && a[0] == a[1] && a[1] == a[2]); } +static void t_units(void) +{ + static const struct { + unsigned long long num; + const char exp_1024[6], exp_1000[6]; + } vt[] = { + {1023, "1023", "1023"}, + {1024, "1024", "1024"}, + {1945, "1945", "1945"}, + {1946, "1946", "1946"}, + {1022975, "998k", "1022k"}, + {1022976, "999k", "1022k"}, + {1022977, "999k", "1022k"}, + {1047552, "1023k", "1047k"}, + {1047553, "1023k", "1047k"}, + {1992294, "1945k", "1992k"}, + {1992295, "1945k", "1992k"}, + {1072693248, "1023M", "1072M"}, + {1072693249, "1023M", "1072M"}, + {ULLONG_MAX, "15E", "18E"}, + }; + char buf[HXSIZEOF_Z64+3]; + printf("unit_size:\n"); + + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + HX_unit_size(buf, ARRAY_SIZE(buf), vt[i].num, 1024, 9120); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1024) != 0) { + printf("\texpected %s\n", vt[i].exp_1024); + abort(); + } + HX_unit_size(buf, ARRAY_SIZE(buf), vt[i].num, 1000, 9120); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1000) != 0) { + printf("\texpected %s\n", vt[i].exp_1000); + abort(); + } + } +} + +static void t_units_cu(void) +{ + static const struct { + unsigned long long num; + const char exp_1024[6], exp_1000[6]; + } vt[] = { + {1023, "1023", "1.1k"}, + {1024, "1.0k", "1.1k"}, + {1945, "1.9k", "2.0k"}, + {1946, "2.0k", "2.0k"}, + {1022975, "999k", "1.1M"}, + {1022976, "999k", "1.1M"}, + {1022977, "1000k", "1.1M"}, + {1047552, "1023k", "1.1M"}, + {1047553, "1.0M", "1.1M"}, + {1992294, "1.9M", "2.0M"}, + {1992295, "2.0M", "2.0M"}, + {1072693248, "1023M", "1.1G"}, + {1072693249, "1.0G", "1.1G"}, + {ULLONG_MAX, "16E", "19E"}, + }; + char buf[80]; + printf("unit_size_cu:\n"); + + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + HX_unit_size_cu(buf, ARRAY_SIZE(buf), vt[i].num, 1024); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1024) != 0) { + printf("\texpected %s\n", vt[i].exp_1024); + abort(); + } + HX_unit_size_cu(buf, ARRAY_SIZE(buf), vt[i].num, 1000); + printf("\t%llu -> %s\n", vt[i].num, buf); + if (strcmp(buf, vt[i].exp_1000) != 0) { + printf("\texpected %s\n", vt[i].exp_1000); + abort(); + } + } +} + +static void t_units_strto(void) +{ + static const struct { + const char input[24]; + unsigned int exponent; + unsigned long long expect_out; + const char expect_rem[8]; + } vt[] = { + {"-5k", 1000, ULLONG_MAX, "-5k"}, + {" -5.2k", 1000, ULLONG_MAX, "-5.2k"}, + {"1", 9999, 1, ""}, + {"1024", 9999, 1ULL << 10, ""}, + {"1048576", 9999, 1ULL << 20, ""}, + {"1073741824", 9999, 1ULL << 30, ""}, + {"1099511627776", 9999, 1ULL << 40, ""}, + {"1125899906842624", 9999, 1ULL << 50, ""}, + {"1152921504606846976", 9999, 1ULL << 60, ""}, + {"18446744073709551615", 9, ULLONG_MAX, ""}, + {"1k", 1000, 1000ULL, ""}, + {"1M", 1000, 1000000ULL, ""}, + {"1G", 1000, 1000000000ULL, ""}, + {"1T", 1000, 1000000000000ULL, ""}, + {"1P", 1000, 1000000000000000ULL, ""}, + {"1E", 1000, 1000000000000000000ULL, ""}, + {"1k", 1024, 1ULL << 10, ""}, + {"1M", 1024, 1ULL << 20, ""}, + {"1G", 1024, 1ULL << 30, ""}, + {"1T", 1024, 1ULL << 40, ""}, + {"1P", 1024, 1ULL << 50, ""}, + {"1E", 1024, 1ULL << 60, ""}, + {"0", 0, 0, ""}, + {"0k", 0, 0, ""}, + {"0 Z", 0, 0, ""}, + {"0.1k", 1000, 100, ""}, + {"0.1k", 1024, 102, ""}, + {" 0.1k", 1024, 102, ""}, + {"0.00000000000000001E", 1024, 11, ""}, + {"1.525444GiB", 1000, 1525444000, "iB"}, + {"1.525444GiB", 1024, 1637933022, "iB"}, + }; + char *end; + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + unsigned long long q = HX_strtoull_unit(vt[i].input, &end, vt[i].exponent); + printf("%s -> %llu __ %s\n", vt[i].input, q, end); + if (q != vt[i].expect_out || strcmp(end, vt[i].expect_rem) != 0) + printf("BUG\n"); + } +} + +static void t_time_units(void) +{ + static const struct { + unsigned long long input; + unsigned int flags; + const char expect_out[24]; + } vt[] = { + {31536000, 0, "365d"}, + {31622400, 0, "366d"}, + {31622400, HXUNIT_YEARS, "1y18h"}, + {31622400, HXUNIT_MONTHS, "1y"}, + {31622400, HXUNIT_WEEKS, "1y"}, + {31622400, HXUNIT_MONTHS | HXUNIT_WEEKS, "1y"}, + {2678400, HXUNIT_MONTHS, "1month13h30min"}, + {2592000, HXUNIT_MONTHS, "30d"}, + {608400, HXUNIT_WEEKS, "1week1h"}, + {90061, 0, "1d1h1min1s"}, + {3692, 0, "1h1min32s"}, + {67, 0, "1min7s"}, + {1, 0, "1s"}, + {0, 0, "0s"}, + }; + printf("===== HX_unit_seconds\n"); + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + char out[60]; + char *ret = HX_unit_seconds(out, ARRAY_SIZE(out), vt[i].input, vt[i].flags); + printf("%llus => \"%s\"\n", vt[i].input, ret); + if (strcmp(ret, vt[i].expect_out) != 0) + printf("\tBUG, expected \"%s\"\n", vt[i].expect_out); + } +} + +static void t_time_strto(void) +{ + static const struct { + const char *input; + unsigned long long expect_out; + const char expect_rem[4]; + } vt[] = { + {"1y1month1week1d1h1min1s ", 31557600+2629800+86400*8+3600+60+1, ""}, + {" -1d", 0, "-1d"}, + {"1 -", 1, "-"}, + {"1s", 1, ""}, + {"1min", 60, ""}, + {"0", 0, ""}, + }; + char *end; + printf("===== t_time_strto\n"); + for (size_t i = 0; i < ARRAY_SIZE(vt); ++i) { + unsigned long long q = HX_strtoull_sec(vt[i].input, &end); + printf("\"%s\" => %llus + \"%s\"\n", vt[i].input, q, end); + if (q != vt[i].expect_out) + printf("\tBUG: expected %llus\n", vt[i].expect_out); + if (strcmp(end, vt[i].expect_rem) != 0) + printf("\tBUG: expected remainder \"%s\"\n", vt[i].expect_rem); + } +} + +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; @@ -296,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) { @@ -316,6 +534,11 @@ int main(int argc, const char **argv) t_strtrim(); t_split(); t_split2(); + t_units(); + t_units_cu(); + t_units_strto(); + t_time_units(); + t_time_strto(); t_strlcpy(); t_strlcpy2(); HXmc_free(tx); diff --git a/src/tc-strquote.c b/src/tc-strquote.c index f26ff54..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> @@ -26,6 +22,10 @@ static const char input4[] = "http://user:pass@host.de/~path/file(msvc);stuff. static const char output4[] = "http%3A%2F%2Fuser%3Apass%40host.de%2F~path%2Ffile%28msvc%29%3Bstuff.php%3Fquery%5Bphpindex%5D%3Dvalue%26another%3Done%3Bstuff"; static const char input5[] = "echo hello `echo world`"; static const char output5[] = "echo hello ``echo world``"; +static const char input6[] = "\xfb\xef\xff"; +static const char output6[] = "++//"; +static const char input7[] = "\xfb\xef\xff"; +static const char output7[] = "--__"; static int test(const char *input, unsigned int mode, const char *expect) { @@ -65,6 +65,8 @@ int main(void) tst(input3, HXQUOTE_BASE64, output3c); tst(input4, HXQUOTE_URIENC, output4); tst(input5, HXQUOTE_SQLBQUOTE, output5); + tst(input6, HXQUOTE_BASE64, output6); + tst(input7, HXQUOTE_BASE64URL, output7); return 0; #undef tst } diff --git a/src/tc-switchuser.c b/src/tc-switchuser.c new file mode 100644 index 0000000..1763527 --- /dev/null +++ b/src/tc-switchuser.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#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[] = { + {.sh = 'u', .type = HXTYPE_STRING, .ptr = &user_name}, + {.sh = 'g', .type = HXTYPE_STRING, .ptr= &group_name}, + HXOPT_TABLEEND, +}; + +int main(int argc, const char **argv) +{ + HX_getopt(options_table, &argc, &argv, HXOPT_USAGEONERR); + const char *user = user_name != NULL ? user_name : "-"; + const char *group = group_name != NULL ? group_name : "-"; + switch (HXproc_switch_user(user_name, group_name)) { + case HXPROC_USER_NOT_FOUND: + if (user_name == NULL) + abort(); /* impossible outcomes */ + printf("No such user \"%s\": %s\n", user_name, strerror(errno)); + break; + case HXPROC_GROUP_NOT_FOUND: + if (group_name == NULL || *group_name == '\0') + abort(); /* impossible outcome */ + printf("No such group \"%s\": %s\n", group_name, strerror(errno)); + break; + case HXPROC_SETUID_FAILED: + printf("setuid %s: %s\n", user, strerror(errno)); + break; + case HXPROC_SETGID_FAILED: + printf("setgid %s: %s\n", group, strerror(errno)); + break; + case HXPROC_INITGROUPS_FAILED: + printf("initgroups for %s: %s\n", user, strerror(errno)); + break; + case HXPROC_SU_NOOP: + printf("No action was performed./User identity already reached.\n"); + /* fallthrough */ + case HXPROC_SU_SUCCESS: { + gid_t list[64] = {-1}; + int numgroups = getgroups(ARRAY_SIZE(list), list); + printf("Identity now: uid %lu euid %lu gid %lu egid %lu\n", + static_cast(unsigned long, getuid()), + static_cast(unsigned long, geteuid()), + static_cast(unsigned long, getgid()), + static_cast(unsigned long, getegid())); + printf("Secondary groups:"); + for (int i = 0; i < numgroups; ++i) + printf(" %lu", static_cast(unsigned long, list[i])); + printf("\n"); + break; + } + } + return EXIT_SUCCESS; +} +#else +int main(void) +{ + return EXIT_SUCCESS; +} +#endif diff --git a/src/tc-time.c b/src/tc-time.c index e842e77..5097cde 100644 --- a/src/tc-time.c +++ b/src/tc-time.c @@ -1,10 +1,5 @@ -/* - * 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> #include <stdlib.h> @@ -26,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}, @@ -36,10 +31,12 @@ static const struct timespec pairs[] = { }; /* - * Variant that uses full 64 bit division and is thus slower on - * a handful of hardware. + * The playing fields it not level at all! + * HX_timespec_add_DIVQ benefits from inlining and near jumps, + * while HX_timespec_add has to go via PLT, and also has the PIC tax. + * It is actually worse by 7% on i7-8250U/-m64. */ -static struct timespec *HX_timespec_add_FDIV(struct timespec *r, +static struct timespec *HX_timespec_add_DIVQ(struct timespec *r, const struct timespec *a, const struct timespec *b) { long long p, q; @@ -105,6 +102,20 @@ HX_timespec_mulf_S(struct timespec *r, const struct timespec *a, double f) return r; } +static void test_basic(void) +{ + struct timeval a = {1, 769298}, b = {2, 430520}, c; + struct timespec p = {1, 769298000}, q = {2, 430520000}, r; + HX_timeval_sub(&c, &b, &a); + HX_timespec_sub(&r, &q, &p); + printf(HX_TIMEVAL_FMT "\n", HX_TIMEVAL_EXP(&c)); + printf(HX_TIMESPEC_FMT "\n", HX_TIMESPEC_EXP(&r)); + assert(c.tv_sec == 0); + assert(c.tv_usec == 661222); + assert(r.tv_sec == 0); + assert(r.tv_nsec == 661222000); +} + static void test_same(void) { static const struct timespec zero = {0, 0}; @@ -205,9 +216,9 @@ static void test_add(void) for (a = pairs; a < pairs + ARRAY_SIZE(pairs); ++a) { for (b = pairs; b < pairs + ARRAY_SIZE(pairs); ++b) { HX_timespec_add(&r, a, b); - print_op2(&r, a, "+N", b); - HX_timespec_add_FDIV(&s, a, b); - print_op2(&r, a, "+F", b); + print_op2(&r, a, "+L", b); + HX_timespec_add_DIVQ(&s, a, b); + print_op2(&r, a, "+Q", b); if (r.tv_sec != s.tv_sec || r.tv_nsec != s.tv_nsec) abort(); HX_timespec_sub(&r, a, b); @@ -288,7 +299,7 @@ static void test_adds(void) { printf("# Test addition speed\n"); test_adds_1("normal: ", HX_timespec_add); - test_adds_1("fulldiv: ", HX_timespec_add_FDIV); + test_adds_1("div64: ", HX_timespec_add_DIVQ); printf("\n"); } @@ -335,11 +346,10 @@ static void test_mul(void) static void test_muls_1i(const char *text, mul_func_t fn) { struct timespec r, s, start, delta; - unsigned int i; printf("%s", text); clock_gettime(clock_id, &start); - for (i = 0; i < step_mul; ++i) { + for (time_t i = 0; i < step_mul; ++i) { r.tv_sec = -i; r.tv_nsec = -i / 4; (*fn)(&s, &r, 7); @@ -352,11 +362,10 @@ static void test_muls_1i(const char *text, mul_func_t fn) static void test_muls_1f(const char *text, mulf_func_t fn) { struct timespec r, s, start, delta; - unsigned int i; printf("%s", text); clock_gettime(clock_id, &start); - for (i = 0; i < step_mul; ++i) { + for (time_t i = 0; i < step_mul; ++i) { r.tv_sec = -i; r.tv_nsec = -i / 4; (*fn)(&s, &r, 7); @@ -382,6 +391,7 @@ int main(void) if (HX_init() <= 0) abort(); + test_basic(); test_same(); test_neg(); test_add(); 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> @@ -6,6 +6,7 @@ * General Public License as published by the Free Software Foundation; * either version 2.1 or (at your option) any later version. */ +#include <stdint.h> #include <sys/stat.h> #include <sys/time.h> #include <stdbool.h> @@ -39,38 +40,13 @@ HX_timespec_neg(struct timespec *r, const struct timespec *a) EXPORT_SYMBOL struct timespec *HX_timespec_add(struct timespec *r, const struct timespec *a, const struct timespec *b) { - /* - * Split the value represented by the struct into two - * independent values that can be added individually. - */ - long nsec[2]; - nsec[0] = (a->tv_sec < 0) ? -a->tv_nsec : a->tv_nsec; - nsec[1] = (b->tv_sec < 0) ? -b->tv_nsec : b->tv_nsec; - - r->tv_sec = a->tv_sec + b->tv_sec; - r->tv_nsec = nsec[0] + nsec[1]; - if (r->tv_nsec >= NANOSECOND) { - ++r->tv_sec; - r->tv_nsec -= NANOSECOND; - } else if (r->tv_nsec <= -NANOSECOND) { - --r->tv_sec; - r->tv_nsec += NANOSECOND; - } - - /* Combine again */ - if (r->tv_sec < 0) { - if (r->tv_nsec < 0) { - r->tv_nsec = -r->tv_nsec; - } else if (r->tv_nsec > 0) { - if (++r->tv_sec == 0) - r->tv_nsec = -NANOSECOND + r->tv_nsec; - else - r->tv_nsec = NANOSECOND - r->tv_nsec; - } - } else if (r->tv_sec > 0 && r->tv_nsec < 0) { - --r->tv_sec; - r->tv_nsec = NANOSECOND + r->tv_nsec; - } + long aa = a->tv_sec * NANOSECOND_LL + + ((a->tv_sec >= 0) ? a->tv_nsec : -a->tv_nsec); + long bb = b->tv_sec * NANOSECOND_LL + + ((b->tv_sec >= 0) ? b->tv_nsec : -b->tv_nsec); + long rr = aa + bb; + r->tv_sec = rr / NANOSECOND; + r->tv_nsec = ((r->tv_sec < 0) ? -rr : rr) % NANOSECOND; return r; } @@ -119,20 +95,14 @@ HX_timespec_mulf(struct timespec *r, const struct timespec *a, double f) EXPORT_SYMBOL struct timeval *HX_timeval_sub(struct timeval *delta, const struct timeval *future, const struct timeval *past) { - delta->tv_sec = future->tv_sec - past->tv_sec; - delta->tv_usec = future->tv_usec - past->tv_usec; - if (future->tv_sec < past->tv_sec || (future->tv_sec == past->tv_sec && - future->tv_usec < past->tv_usec)) { - if (future->tv_usec > past->tv_usec) { - delta->tv_usec = -MICROSECOND + delta->tv_usec; - ++delta->tv_sec; - } - if (delta->tv_sec < 0) - delta->tv_usec *= -1; - } else if (delta->tv_usec < 0) { - delta->tv_usec += MICROSECOND; - --delta->tv_sec; - } + struct timespec d, f, p; + f.tv_sec = future->tv_sec; + f.tv_nsec = future->tv_usec * 1000; + p.tv_sec = past->tv_sec; + p.tv_nsec = past->tv_usec * 1000; + HX_timespec_sub(&d, &f, &p); + delta->tv_sec = d.tv_sec; + delta->tv_usec = d.tv_nsec / 1000; return delta; } #endif diff --git a/src/tx-intdiff.cpp b/src/tx-intdiff.cpp new file mode 100644 index 0000000..cd8ec7a --- /dev/null +++ b/src/tx-intdiff.cpp @@ -0,0 +1,24 @@ +#include <cstdio> +#include <iterator> +#include <vector> +#include <libHX/intdiff.hpp> +int main() +{ + std::vector<int> a{1, 2, 5}; + std::vector<long> b{2, 3, 4, 5}; + std::vector<float> comm, left, right; + + HX::set_intersect_diff(a.cbegin(), a.cend(), b.cbegin(), b.cend(), + std::back_inserter(comm), std::back_inserter(left), + std::back_inserter(right)); + for (auto e : comm) + printf("%f,", e); + printf("\n"); + for (auto e : left) + printf("%f,", e); + printf("\n"); + for (auto e : right) + printf("%f,", e); + printf("\n"); + return 0; +} diff --git a/src/tx-option.cpp b/src/tx-option.cpp index 55e3566..b70110f 100644 --- a/src/tx-option.cpp +++ b/src/tx-option.cpp @@ -5,7 +5,9 @@ #endif #include <libHX/option.h> +static unsigned int g_verbose; static const struct HXoption t[] = { + {nullptr, 'v', HXTYPE_NONE | HXOPT_INC, &g_verbose}, HXOPT_AUTOHELP, HXOPT_TABLEEND, }; |