Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libHX for openSUSE:Factory checked in at 2021-10-11 15:30:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libHX (Old) and /work/SRC/openSUSE:Factory/.libHX.new.2443 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libHX" Mon Oct 11 15:30:41 2021 rev:62 rq:923056 version:4.0.1 Changes: -------- --- /work/SRC/openSUSE:Factory/libHX/libHX.changes 2021-08-05 20:48:16.311920671 +0200 +++ /work/SRC/openSUSE:Factory/.libHX.new.2443/libHX.changes 2021-10-11 15:31:16.090811389 +0200 @@ -1,0 +2,10 @@ +Sun Oct 3 00:28:41 UTC 2021 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 4.0.1 + * lib: add ``HX_slurp_fd``, ``HX_slurp_file`` + * proc: add ``HXproc_switch_user`` + * proc: add ``HXproc_top_fd`` + * socket: add ``HX_socket_from_env`` + * opt: add ``HXOPT_KEEP_ARGV`` flag + +------------------------------------------------------------------- Old: ---- libHX-3.26.tar.asc libHX-3.26.tar.xz New: ---- libHX-4.0.1.tar.asc libHX-4.0.1.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libHX.spec ++++++ --- /var/tmp/diff_new_pack.vjIcvr/_old 2021-10-11 15:31:16.694812357 +0200 +++ /var/tmp/diff_new_pack.vjIcvr/_new 2021-10-11 15:31:16.698812364 +0200 @@ -18,7 +18,7 @@ Name: libHX %define lname libHX32 -Version: 3.26 +Version: 4.0.1 Release: 0 Summary: Collection of routines for C and C++ programming License: LGPL-2.1-or-later @@ -70,7 +70,7 @@ pushd obj/ %define _configure ../configure %configure --includedir="%_includedir/%name" --docdir="%_docdir/%name" -make %{?_smp_mflags} +%make_build popd %install @@ -82,7 +82,7 @@ find "$b/%_libdir" -type f -name "*.la" -delete %check -make -C obj check %{?_smp_mflags} +%make_build -C obj check %post -n %lname -p /sbin/ldconfig %postun -n %lname -p /sbin/ldconfig ++++++ libHX-3.26.tar.xz -> libHX-4.0.1.tar.xz ++++++ ++++ 8862 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/Makefile.am new/libHX-4.0.1/Makefile.am --- old/libHX-3.26/Makefile.am 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/Makefile.am 2021-10-03 01:05:06.000000000 +0200 @@ -15,8 +15,8 @@ .PHONY: tarball tarball: # do not use mkdir_p here. - mkdir ${tmpdir}; - pushd ${top_srcdir} && git archive --prefix=${PACKAGE_NAME}-${PACKAGE_VERSION}/ HEAD | tar -C ${tmpdir} -x && popd; + mkdir ${tmpdir} + pushd ${top_srcdir} && git archive --prefix=${PACKAGE_NAME}-${PACKAGE_VERSION}/ HEAD | tar -C ${tmpdir} -x && popd pushd ${tmpdir}/${PACKAGE_NAME}-${PACKAGE_VERSION} && ./autogen.sh && popd - tar --use=${packer} -C ${tmpdir} -cf ${PACKAGE_NAME}-${PACKAGE_VERSION}${packext} --owner=root --group=root ${PACKAGE_NAME}-${PACKAGE_VERSION}/; - rm -Rf ${tmpdir}; + tar --use=${packer} -C ${tmpdir} -cf ${PACKAGE_NAME}-${PACKAGE_VERSION}${packext} --owner=root --group=root ${PACKAGE_NAME}-${PACKAGE_VERSION}/ + rm -Rf ${tmpdir} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/build-aux/ar-lib new/libHX-4.0.1/build-aux/ar-lib --- old/libHX-3.26/build-aux/ar-lib 2021-08-04 00:20:39.121549456 +0200 +++ new/libHX-4.0.1/build-aux/ar-lib 2021-10-03 02:30:14.941163473 +0200 @@ -2,9 +2,9 @@ # Wrapper for Microsoft lib.exe me=ar-lib -scriptversion=2012-03-01.08; # UTC +scriptversion=2019-07-04.01; # UTC -# Copyright (C) 2010-2017 Free Software Foundation, Inc. +# Copyright (C) 2010-2020 Free Software Foundation, Inc. # Written by Peter Rosin <p...@lysator.liu.se>. # # This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -65,7 +65,7 @@ mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin) + cygwin | msys) file=`cygpath -m "$file" || echo "$file"` ;; wine) @@ -224,10 +224,11 @@ esac done else - $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member - do - $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? - done + $AR -NOLOGO -LIST "$archive" | tr -d '\r' | sed -e 's/\\/\\\\/g' \ + | while read member + do + $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $? + done fi elif test -n "$quick$replace"; then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/build-aux/compile new/libHX-4.0.1/build-aux/compile --- old/libHX-3.26/build-aux/compile 2021-08-04 00:20:39.129547843 +0200 +++ new/libHX-4.0.1/build-aux/compile 2021-10-03 02:30:14.941163473 +0200 @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2016-01-11.22; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey <tro...@cygnus.com>. # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) @@ -340,7 +340,7 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/build-aux/missing new/libHX-4.0.1/build-aux/missing --- old/libHX-3.26/build-aux/missing 2021-08-04 00:20:39.145544615 +0200 +++ new/libHX-4.0.1/build-aux/missing 2021-10-03 02:30:14.953163507 +0200 @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2016-01-11.22; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <pin...@iro.umontreal.ca>, 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -101,9 +101,9 @@ exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -207,7 +207,7 @@ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/build-aux/test-driver new/libHX-4.0.1/build-aux/test-driver --- old/libHX-3.26/build-aux/test-driver 2021-08-04 00:20:39.281517180 +0200 +++ new/libHX-4.0.1/build-aux/test-driver 2021-10-03 02:30:15.089163901 +0200 @@ -1,9 +1,9 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2016-01-11.22; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 2011-2017 Free Software Foundation, Inc. +# Copyright (C) 2011-2020 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -42,11 +42,13 @@ { cat <<END Usage: - test-driver --test-name=NAME --log-file=PATH --trs-file=PATH - [--expect-failure={yes|no}] [--color-tests={yes|no}] - [--enable-hard-errors={yes|no}] [--] + test-driver --test-name NAME --log-file PATH --trs-file PATH + [--expect-failure {yes|no}] [--color-tests {yes|no}] + [--enable-hard-errors {yes|no}] [--] TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] + The '--test-name', '--log-file' and '--trs-file' options are mandatory. +See the GNU Automake documentation for information. END } @@ -59,7 +61,7 @@ while test $# -gt 1; do arg=${1%=*} val=${1#*=} - if [ $arg == $val ]; then + if [ $arg = $val ]; then val=$2 shift fi @@ -75,7 +77,7 @@ --) break;; -*) usage_error "invalid option: '$1'";; esac - [[ $arg != $val ]] && shift + [ $arg != $val ] && shift done missing_opts= @@ -145,7 +147,7 @@ # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/config.h.in new/libHX-4.0.1/config.h.in --- old/libHX-3.26/config.h.in 2021-08-04 00:20:38.513672104 +0200 +++ new/libHX-4.0.1/config.h.in 2021-10-03 02:30:14.377161841 +0200 @@ -24,6 +24,9 @@ /* Define to 1 if you have the `getppid' function. */ #undef HAVE_GETPPID +/* Define to 1 if you have the `initgroups' function. */ +#undef HAVE_INITGROUPS + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H @@ -33,6 +36,9 @@ /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE +/* Define to 1 if you have the `setgid' function. */ +#undef HAVE_SETGID + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/configure.ac new/libHX-4.0.1/configure.ac --- old/libHX-3.26/configure.ac 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/configure.ac 2021-10-03 01:05:06.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([libHX], [3.26]) +AC_INIT([libHX], [4.0.1]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) @@ -103,10 +103,9 @@ #include <sys/time.h> #include <time.h> ]) -AC_CHECK_FUNCS([fork execv execvp pipe], [b_proc="1"]) +AC_CHECK_FUNCS([fork execv execvp pipe]) AC_CHECK_FUNCS([getegid geteuid getpid getppid]) -AM_CONDITIONAL([B_PROC], [test "$b_proc" = 1]) - +AC_CHECK_FUNCS([initgroups setgid]) AC_CHECK_PROGS([LYX], [lyx]) AM_CONDITIONAL([BUILD_DOCS], [test -n "$LYX"]) @@ -119,6 +118,5 @@ AC_SUBST([regular_CPPFLAGS]) AC_SUBST([regular_CFLAGS]) AC_SUBST([regular_CXXFLAGS]) -AC_CONFIG_FILES([Makefile assorted/Makefile src/Makefile - include/Makefile libHX.pc]) +AC_CONFIG_FILES([Makefile src/Makefile include/Makefile libHX.pc]) AC_OUTPUT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/api.rst new/libHX-4.0.1/doc/api.rst --- old/libHX-3.26/doc/api.rst 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/api.rst 2021-10-03 01:05:06.000000000 +0200 @@ -9,6 +9,18 @@ ====== ====== ====== ======================================== RMV MinVer FirstA Name ====== ====== ====== ======================================== +3.27 3.27 3.27 HXOPT_KEEP_ARGV +3.27 3.27 3.27 HXproc_top_fd +3.27 3.27 3.27 HXproc_switch_user +3.27 3.27 3.27 HXPROC_SU_SUCCESS +3.27 3.27 3.27 HXPROC_SU_NOOP +3.27 3.27 3.27 HXPROC_USER_NOT_FOUND +3.27 3.27 3.27 HXPROC_GROUP_NOT_FOUND +3.27 3.27 3.27 HXPROC_SETUID_FAILED +3.27 3.27 3.27 HXPROC_SETGID_FAILED +3.27 3.27 3.27 HXPROC_INITGROUPS_FAILED +3.27 3.27 3.27 HX_slurp_fd +3.27 3.27 3.27 HX_slurp_file 3.25 3.25 3.25 HX_split_fixed 3.25 3.25 3.25 HX_split_inplace 3.22 3.22 3.22 HXQUOTE_SQLBQUOTE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/changelog.rst new/libHX-4.0.1/doc/changelog.rst --- old/libHX-3.26/doc/changelog.rst 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/changelog.rst 2021-10-03 01:05:06.000000000 +0200 @@ -1,3 +1,19 @@ +v4.0 (2021-10-03) +================= + +Enhancements: + +* lib: add ``HX_slurp_fd``, ``HX_slurp_file`` +* proc: add ``HXproc_switch_user`` +* proc: add ``HXproc_top_fd`` +* socket: add ``HX_socket_from_env`` +* opt: add ``HXOPT_KEEP_ARGV`` flag + +Fixes: + +* proc: re-close pipes when ``HXproc_build_pipes`` failed + + v3.26 (2021-08-03) ================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/files_and_dirs.rst new/libHX-4.0.1/doc/files_and_dirs.rst --- old/libHX-3.26/doc/files_and_dirs.rst 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/files_and_dirs.rst 2021-10-03 01:05:06.000000000 +0200 @@ -121,10 +121,24 @@ #include <libHX/io.h> + #define HXF_KEEP ... + #define HXF_UID ... + #define HXF_GID ... + int HX_copy_file(const char *src, const char *dest, unsigned int flags, ...); int HX_copy_dir(const char *src, const char *dest, unsigned int flags, ...); + char *HX_slurp_fd(int fd, size_t *outsize); + char *HX_slurp_file(const char *file, size_t *outsize); -Possible flags that can be used with the functions: +``HX_copy_file`` + Copies one named file to a new location. Possible ``flags`` are + ``HXF_KEEP``, ``HXF_UID`` and ``HXF_GID``. Error checking by + ``HX_copy_file`` is flakey. ``HX_copy_file`` will return >0 on success, + or ``-errno`` on failure. Errors can arise from the use of the syscalls + ``open``, ``read`` and ``write``. The return value of ``fchmod``, which + is used to set the UID and GID, is actually ignored, which means + verifying that the owner has been set cannot be detected with + ``HX_copy_file`` alone (historic negligience?). ``HXF_KEEP`` Do not overwrite existing files. @@ -137,13 +151,22 @@ Change the new file's group owner to the GID given in the varargs section. This is processed after ``HXF_UID``. -Error checking is flakey. - -``HX_copy_file`` will return >0 on success, or ``-errno`` on failure. Errors -can arise from the use of the syscalls ``open``, ``read`` and ``write``. The -return value of ``fchmod``, which is used to set the UID and GID, is actually -ignored, which means verifying that the owner has been set cannot be detected -with ``HX_copy_file`` alone (historic negligience?). +``HX_copy_dir`` + Copies one named directory to a new location, recursively. + (Uses ``HX_copy_file`` and ``HX_copy_dir``.) Error checking by + ``HX_copy_dir`` is flakey. + +``HX_slurp_fd`` + Reads all remaining bytes from the given filedescriptor ``fd`` and + returns a pointer to a newly-allocated content buffer. If ``outsize`` + is not ``NULL``, the size of the buffer will be written to it. The + buffer is always terminated by a gratuitious NUL (not counted in + ``outsize``). Once no longer needed, the buffer should be released with + ``free``. + +``HX_slurp_file`` + Reads all bytes from the given filename and returns a pointer to the + content buffer. Inherits all the characteristics from ``HX_slurp_fd``. Filedescriptor helpers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/option_parsing.rst new/libHX-4.0.1/doc/option_parsing.rst --- old/libHX-3.26/doc/option_parsing.rst 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/option_parsing.rst 2021-10-03 01:05:06.000000000 +0200 @@ -15,12 +15,9 @@ .. [#f4] popt failed to do this for a long time. -A table-based approach allows for the parser to run as one atomic block of code -(callbacks are, by definition, ???special??? exceptions), making it more opaque -than an open-coded ``getopt``(3) loop. You give it your argument vector and the -table, snip the finger (call the parser function once), and it is done. In -getopt on the other hand, the getopt function returns for every argument it -parsed and needs to be called repeatedly. +A table-based approach allows for the parser to run as one unit, quite unlike +the open-coded ``getopt``(3) loop where the function returns for every argument +it parsed and needs to be called repeatedly. Synopsis @@ -30,7 +27,7 @@ #include <libHX/option.h> - struct HXoption {struct HXoption + struct HXoption { const char *ln; char sh; unsigned int type; @@ -278,10 +275,11 @@ ``HX_getopt`` is the actual parsing function. It takes the option table, and a pointer to your argc and argv variables that you get from the main function. -The parser will, unlike GNU getopt, literally ???eat??? all options and their -arguments, leaving only non-options in ``argv``, and ``argc`` updated, when -finished. This is similar to how Perl's ``Getopt::Long`` module works. -Additional flags can control the exact behavior of ``HX_getopt``: +The parser will, by default, consume all options and their arguments, similar +to Perl's ``Getopt::Long`` module. ``*argv`` is then updated to point to a new +array of strings (to be deallocated with ``HX_zvecfree``) and ``*argc`` is +updated accordingly. Additional flags can control the exact behavior of +``HX_getopt``: ``HXOPT_PTHRU`` ???Passthrough mode???. Any unknown options are not ???eaten??? and are instead @@ -303,6 +301,9 @@ non-option argument in argv is encountered. This behavior is also implicit when the environment variable ``POSIXLY_CORRECT`` is set. +``HXOPT_KEEP_ARGV`` + Do not modify ``argc`` and ``argv`` at all. + The return value can be one of the following: ``HXOPT_ERR_SUCCESS`` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/process_management.rst new/libHX-4.0.1/doc/process_management.rst --- old/libHX-3.26/doc/process_management.rst 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/process_management.rst 2021-10-03 01:05:06.000000000 +0200 @@ -193,3 +193,41 @@ ``EINVAL`` Flags were not accepted. + + +User identity control +===================== + +.. code-block: c + + #include <libHX/proc.h> + + int HXproc_switch_user(const char *user, const char *group); + +``HXproc_switch_user`` is a wrapper for changing process identity to an +unprivileged user. This utilizes ``setuid``, and possibly ``setgid`` plus +``initgroups``. + +``user`` can either be a username or a numeric UID in string form, the latter +of which will be parsed with strtoul in automatic base. If ``user`` is ``NULL`` +or the empty string, no change of process user identity occurs. + +``group`` can likewise be a name or GID. When ``group`` is ``NULL``, the +process group(s) will change to the the user's group(s)????? both primary and +secondary????? provided a user was specified (see above). When ``gruop`` is the +empty string, no change of process group identity occurs. + + +Process information +=================== + +.. code-block:: c + + #include <libHX/proc.h> + + int HXproc_top_fd(void); + +``HXproc_top_fd`` + This function gives a heuristic for the highest fd in the process. + The returned number may be higher than the highest live fd actually. + On error, negative errno is returned. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/slurp.c new/libHX-4.0.1/doc/slurp.c --- old/libHX-3.26/doc/slurp.c 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/doc/slurp.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,38 +0,0 @@ -static void *p_slurp(const char *file, size_t *outsize) -{ - struct stat sb; - int ret = 0, fd = open(file, O_RDONLY | O_BINARY); - void *buf = NULL; - ssize_t rdret; - - if (fd < 0) { - fprintf(stderr, "ERROR: Slurping %s failed: %s\n", - file, strerror(errno)); - return NULL; - } - if (fstat(fd, &buf) < 0) { - ret = errno; - perror("fstat"); - goto out; - } - *outsize = sb.st_size; /* truncate if need be */ - buf = malloc(*outsize); - if (buf == NULL) { - ret = errno; - perror("malloc"); - goto out; - } - rdret = read(fd, buf, *outsize); - if (rdret < 0) { - ret = errno; - perror("read"); - free(buf); - } else { - *outsize = rdret; - } - out: - close(fd); - errno = ret; - return buf; -} - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/doc/socket_functions.rst new/libHX-4.0.1/doc/socket_functions.rst --- old/libHX-3.26/doc/socket_functions.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/libHX-4.0.1/doc/socket_functions.rst 2021-10-03 01:05:06.000000000 +0200 @@ -0,0 +1,16 @@ +================ +Socket functions +================ + +.. code-block:: c + + #include <libHX/socket.h> + + int HX_socket_from_env(const struct addrinfo *ai, const char *intf); + +``HX_socket_from_env`` + The function looks up the current process's file descriptors for a + socket that is listening and which matches the given addrinfo and + (optionally) intf if the latter is not NULL``. Upon success, the fd + number is returned, or -1 if no file descriptor matched. No errors are + signalled. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/include/Makefile.am new/libHX-4.0.1/include/Makefile.am --- old/libHX-3.26/include/Makefile.am 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/include/Makefile.am 2021-10-03 01:05:06.000000000 +0200 @@ -2,7 +2,6 @@ nobase_include_HEADERS = libHX.h \ libHX/ctype_helper.h libHX/defs.h libHX/deque.h libHX/init.h \ - libHX/io.h libHX/list.h \ - libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h libHX/string.h \ + libHX/intdiff.hpp libHX/io.h libHX/list.h \ + libHX/map.h libHX/misc.h libHX/option.h libHX/proc.h libHX/socket.h libHX/string.h \ libHX/libxml_helper.h libHX/wx_helper.hpp - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/include/libHX/io.h new/libHX-4.0.1/include/libHX/io.h --- old/libHX-3.26/include/libHX/io.h 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/include/libHX/io.h 2021-10-03 01:05:06.000000000 +0200 @@ -35,6 +35,8 @@ extern int HX_readlink(hxmc_t **, const char *); extern int HX_realpath(hxmc_t **, const char *, unsigned int); extern int HX_rrmdir(const char *); +extern char *HX_slurp_fd(int fd, size_t *outsize); +extern char *HX_slurp_file(const char *file, size_t *outsize); extern ssize_t HXio_fullread(int, void *, size_t); extern ssize_t HXio_fullwrite(int, const void *, size_t); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/include/libHX/option.h new/libHX-4.0.1/include/libHX/option.h --- old/libHX-3.26/include/libHX/option.h 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/include/libHX/option.h 2021-10-03 01:05:06.000000000 +0200 @@ -144,6 +144,7 @@ * %HXOPT_USAGEONERR: print out short usage when a parsing error occurs * %HXOPT_RQ_ORDER: require option order/POSIX mode: * first non-option terminates option processing + * %HXOPT_KEEP_ARGV: do not replace argc/argv at all */ enum { HXOPT_PTHRU = 1 << 0, @@ -152,6 +153,7 @@ HXOPT_HELPONERR = 1 << 3, HXOPT_USAGEONERR = 1 << 4, HXOPT_RQ_ORDER = 1 << 5, + HXOPT_KEEP_ARGV = 1 << 6, }; /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/include/libHX/proc.h new/libHX-4.0.1/include/libHX/proc.h --- old/libHX-3.26/include/libHX/proc.h 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/include/libHX/proc.h 2021-10-03 01:05:06.000000000 +0200 @@ -21,6 +21,16 @@ HXPROC_NULL_STDERR = 1 << 8, }; +enum HXproc_su_status { + HXPROC_INITGROUPS_FAILED = -5, + HXPROC_SETGID_FAILED = -4, + HXPROC_SETUID_FAILED = -3, + HXPROC_GROUP_NOT_FOUND = -2, + HXPROC_USER_NOT_FOUND = -1, + HXPROC_SU_NOOP = 0, + HXPROC_SU_SUCCESS = 1, +}; + struct HXproc_ops { void (*p_prefork)(void *); void (*p_postfork)(void *); @@ -41,6 +51,8 @@ extern int HXproc_run_async(const char *const *, struct HXproc *); extern int HXproc_run_sync(const char *const *, unsigned int); extern int HXproc_wait(struct HXproc *); +extern enum HXproc_su_status HXproc_switch_user(const char *user, const char *group); +extern int HXproc_top_fd(void); #ifdef __cplusplus } /* extern "C" */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/include/libHX/socket.h new/libHX-4.0.1/include/libHX/socket.h --- old/libHX-3.26/include/libHX/socket.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libHX-4.0.1/include/libHX/socket.h 2021-10-03 01:05:06.000000000 +0200 @@ -0,0 +1,20 @@ +#ifndef _LIBHX_SOCKET_H +#define _LIBHX_SOCKET_H 1 + +#ifdef _WIN32 +# include <ws2tcpip.h> +#else +# include <netdb.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern int HX_socket_from_env(const struct addrinfo *, const char *intf); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _LIBHX_SOCKET_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/.gitignore new/libHX-4.0.1/src/.gitignore --- old/libHX-3.26/src/.gitignore 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/.gitignore 2021-10-03 01:05:06.000000000 +0200 @@ -5,6 +5,7 @@ /t?-dir /t?-format /t?-intdiff +/t?-io /t?-link /t?-list /t?-list2 @@ -21,6 +22,7 @@ /t?-strchr2 /t?-string /t?-strquote +/t?-switchuser /t?-time # automake tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/Makefile.am new/libHX-4.0.1/src/Makefile.am --- old/libHX-3.26/src/Makefile.am 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/Makefile.am 2021-10-03 01:05:06.000000000 +0200 @@ -10,10 +10,10 @@ 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 + mc.c misc.c opt.c proc.c \ + rand.c socket.c string.c time.c libHX_la_LIBADD = ${libdl_LIBS} ${libpthread_LIBS} ${librt_LIBS} -libHX_la_LDFLAGS = -no-undefined -version-info 32:0:0 +libHX_la_LDFLAGS = -no-undefined -version-info 33:0:1 if WITH_GNU_LD libHX_la_LDFLAGS += -Wl,--version-script=${srcdir}/libHX.map endif @@ -22,9 +22,6 @@ if MINGW32 libHX_la_SOURCES += ux-file.c ux-mmap.c endif -if B_PROC -libHX_la_SOURCES += proc.c -endif libHX_rtcheck_la_SOURCES = rtcheck.c libHX_rtcheck_la_LIBADD = ${libdl_LIBS} @@ -35,16 +32,18 @@ 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-link \ 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 + tc-shconfig tc-strchr2 tc-string tc-strquote \ + tc-switchuser tc-time TESTS = 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_io_LDADD = libHX.la tc_link_LDADD = libHX.la tc_list_LDADD = libHX.la tc_list2_LDADD = libHX.la @@ -61,6 +60,7 @@ 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/internal.h new/libHX-4.0.1/src/internal.h --- old/libHX-3.26/src/internal.h 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/internal.h 2021-10-03 01:05:06.000000000 +0200 @@ -42,6 +42,7 @@ #define MAXLNLEN 1024 /* max length for usual line */ #define HXMC_IDENT 0x200571AF +#define nullptr NULL struct memcont { size_t alloc, length; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/io.c new/libHX-4.0.1/src/io.c --- old/libHX-3.26/src/io.c 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/io.c 2021-10-03 01:05:06.000000000 +0200 @@ -14,6 +14,7 @@ #include <stdarg.h> #include <stdbool.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -300,27 +301,38 @@ /* 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); + return -(errno = saved_errno); + } + if (static_cast(size_t, ret) < linkbuf_size) { + HXmc_setlen(target, ret); + return ret; + } + linkbuf_size *= 2; + if (HXmc_setlen(target, linkbuf_size) == NULL) { + int saved_errno = errno; + if (allocate) + HXmc_free(*target); + return -(errno = saved_errno); } - return ret; } - HXmc_setlen(target, ret); - return ret; + return 0; } /** @@ -567,3 +579,46 @@ } return done; } + +EXPORT_SYMBOL char *HX_slurp_fd(int fd, size_t *outsize) +{ + struct stat sb; + if (fstat(fd, &sb) < 0) + return NULL; + size_t fsize = sb.st_size; /* may truncate from loff_t to size_t */ + if (fsize == SIZE_MAX) + --fsize; + 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/libHX.map new/libHX-4.0.1/src/libHX.map --- old/libHX-3.26/src/libHX.map 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/libHX.map 2021-10-03 01:05:06.000000000 +0200 @@ -126,3 +126,12 @@ local: *; }; + +LIBHX_3.27 { +global: + HX_socket_from_env; + HX_slurp_fd; + HX_slurp_file; + HXproc_switch_user; + HXproc_top_fd; +} LIBHX_3.25; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/opt.c new/libHX-4.0.1/src/opt.c --- old/libHX-3.26/src/opt.c 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/opt.c 2021-10-03 01:05:06.000000000 +0200 @@ -758,6 +758,7 @@ 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) @@ -776,6 +777,7 @@ *argv = nvec; if (argc != NULL) *argc = argk; + } } else if (ret < 0) { if (!(ps.flags & HXOPT_QUIET)) fprintf(stderr, "%s: %s\n", __func__, strerror(errno)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/proc.c new/libHX-4.0.1/src/proc.c --- old/libHX-3.26/src/proc.c 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/proc.c 2021-10-03 01:05:06.000000000 +0200 @@ -7,42 +7,115 @@ * 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> -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 +161,20 @@ */ 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 } /** @@ -136,6 +211,7 @@ } if ((ret = HXproc_build_pipes(proc, pipes)) <= 0) { saved_errno = errno; + HXproc_close_pipes(pipes); if (nullfd >= 0) close(nullfd); errno = saved_errno; @@ -266,4 +342,41 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/socket.c new/libHX-4.0.1/src/socket.c --- old/libHX-3.26/src/socket.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libHX-4.0.1/src/socket.c 2021-10-03 01:05:06.000000000 +0200 @@ -0,0 +1,86 @@ +/* + * 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 <stdlib.h> +#include <string.h> +#ifdef _WIN32 +# include <ws2tcpip.h> +#else +# include <sys/socket.h> +# include <netdb.h> +#endif +#include <libHX/proc.h> +#include <libHX/socket.h> +#include "internal.h" + +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, &value, &optlen); + if (ret < 0 || value == 0) + return -1; + 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; + 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; + 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; + 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) { + top_fd = 3 + strtol(env_limit, nullptr, 0); + } else { + env_limit = getenv("HX_LISTEN_TOP_FD"); + top_fd = env_limit != nullptr ? strtol(env_limit, nullptr, 0) : HXproc_top_fd(); + } + for (int fd = 3; fd < top_fd; ++fd) + if (try_sk_from_env(fd, ai, intf) == fd) + return fd; + errno = ENOENT; + return -1; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/tc-io.c new/libHX-4.0.1/src/tc-io.c --- old/libHX-3.26/src/tc-io.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libHX-4.0.1/src/tc-io.c 2021-10-03 01:05:06.000000000 +0200 @@ -0,0 +1,11 @@ +#include <stdio.h> +#include <libHX/io.h> + +int main(void) +{ + size_t z; + char *s = HX_slurp_file("tc-io.c", &z); + printf("%s\n", s); + printf("Dumped %zu bytes\n", z); + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/tc-proc.c new/libHX-4.0.1/src/tc-proc.c --- old/libHX-3.26/src/tc-proc.c 2021-08-04 00:20:23.000000000 +0200 +++ new/libHX-4.0.1/src/tc-proc.c 2021-10-03 01:05:06.000000000 +0200 @@ -7,10 +7,12 @@ */ #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 +58,7 @@ { 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/libHX-3.26/src/tc-switchuser.c new/libHX-4.0.1/src/tc-switchuser.c --- old/libHX-3.26/src/tc-switchuser.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libHX-4.0.1/src/tc-switchuser.c 2021-10-03 01:05:06.000000000 +0200 @@ -0,0 +1,73 @@ +/* + * 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. + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#if defined(HAVE_INITGROUPS) +#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> + +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; +} +#endif