diff --git a/3RDPARTY b/3RDPARTY index 96dd6811..fce689fc 100644 --- a/3RDPARTY +++ b/3RDPARTY @@ -13,8 +13,6 @@ internal use in the code: - mkpath from NetBSD's mkdir(1): lib/external/mkpath.c -- fexec from NetBSD's pkg_install: lib/external/fexec.c - - libfetch-2.31 from NetBSD: lib/fetch - portableproplib-0.4.1 (lib/portableproplib) from diff --git a/COPYING b/COPYING index 4d190250..877fbe27 100644 --- a/COPYING +++ b/COPYING @@ -140,7 +140,7 @@ This product uses some code with the following license */ This product uses some code with the following license -(lib/humanize_number.c, lib/fexec.c): +(lib/humanize_number.c): /* * Copyright (c) 2003 The NetBSD Foundation, Inc. diff --git a/NEWS b/NEWS index 2054a147..504c5366 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ xbps-0.16 (???): + * libxbps: implemented xbps_file_exec thru posix_spawn. That means + posix_spawn() is now required in xbps. + * libxbps: renamed xbps_repository_pool_xxx to xbps_rpool_xxx (API/ABI incompat changes). diff --git a/configure b/configure index 1f48f5cf..6fc9d4b7 100755 --- a/configure +++ b/configure @@ -305,6 +305,28 @@ if [ -n "$BUILD_PIE" ]; then fi fi +# +# Check for posix_spawn (required). +# +func=posix_spawn +printf "Checking for $func() ... " +cat < _$func.c +#include +#include +int main(void) { + posix_spawn(NULL, NULL, NULL, NULL, NULL, NULL); + return 0; +} +EOF +if $XCC _${func}.c -o _${func} 2>/dev/null; then + rm -f _$func.c _$func + echo "yes." +else + echo "not found! $func is required by xbps, exiting..." + rm -f _$func.c _$func + exit 1 +fi + # # Check for vasprintf(). # diff --git a/include/xbps_api.h b/include/xbps_api.h index 56e60f5b..90cd32fe 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -56,7 +56,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.4" -#define XBPS_API_VERSION "20120530-2" +#define XBPS_API_VERSION "20120530-3" #define XBPS_VERSION "0.16" /** diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 15e4b51b..0f8a7f40 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -165,11 +165,9 @@ char HIDDEN *xbps_get_remote_repo_string(const char *); /** * @private - * From lib/fexec.c + * From lib/file_exec.c */ int HIDDEN xbps_file_exec(const char *, ...); -int HIDDEN xbps_file_exec_skipempty(const char *, ...); -int HIDDEN xbps_file_chdir_exec(const char *, const char *, ...); /** * @private diff --git a/lib/Makefile b/lib/Makefile index 86335fb5..ad48a46a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -37,7 +37,7 @@ LIBFETCH_OBJS = endif # External code used by libxbps -EXTOBJS = external/dewey.o external/fexec.o external/humanize_number.o +EXTOBJS = external/dewey.o external/humanize_number.o EXTOBJS += external/match.o external/mkpath.o # libxbps @@ -46,7 +46,7 @@ OBJS += package_remove.o package_remove_obsoletes.o package_state.o OBJS += package_unpack.o package_requiredby.o package_register.o OBJS += transaction_commit.o transaction_package_replace.o OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o -OBJS += download.o initend.o pkgdb.o +OBJS += download.o initend.o pkgdb.o file_exec.o OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o OBJS += plist_remove.o plist_fetch.o util.o util_hash.o OBJS += repository_finddeps.o cb_util.o diff --git a/lib/external/fexec.c b/lib/external/fexec.c deleted file mode 100644 index 613eecca..00000000 --- a/lib/external/fexec.c +++ /dev/null @@ -1,173 +0,0 @@ -/*- - * Copyright (c) 2003 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Matthias Scheler. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "xbps_api_impl.h" - -static int -pfcexec(const char *path, const char *file, const char **argv) -{ - pid_t child; - int status; - bool do_chroot = false; - - child = vfork(); - switch (child) { - case 0: - if (getuid() == 0 && access("./bin/sh", X_OK) == 0) - do_chroot = true; - - /* - * If uid==0 and /bin/sh exists, we can change root directory, - * fork and execute the command. Otherwise just change current - * directory and fork/execute. - */ - if (path && do_chroot) { - if (chroot(path) == -1) - _exit(127); - if (chdir("/") == -1) - _exit(127); - } else if (path && !do_chroot) { - if (chdir(path) == -1) - _exit(127); - } else if (path == NULL && do_chroot) { - if (chroot(".") == -1) { - if (errno != EPERM) - _exit(127); - if (chdir(".") == -1) - _exit(127); - } else { - if (chdir("/") == -1) - _exit(127); - } - } - - (void)execv(file, __UNCONST(argv)); - _exit(127); - /* NOTREACHED */ - case -1: - return -1; - } - - while (waitpid(child, &status, 0) < 0) { - if (errno != EINTR) - return -1; - } - - if (!WIFEXITED(status)) - return -1; - - return WEXITSTATUS(status); -} - -static int -vfcexec(const char *path, int skipempty, const char *arg, va_list ap) -{ - const char **argv; - size_t argv_size, argc; - int retval; - - argv_size = 16; - if ((argv = malloc(argv_size * sizeof(*argv))) == NULL) { - errno = ENOMEM; - return -1; - } - - argv[0] = arg; - argc = 1; - - do { - if (argc == argv_size) { - argv_size *= 2; - argv = realloc(argv, argv_size * sizeof(*argv)); - if (argv == NULL) { - errno = ENOMEM; - return -1; - } - } - - arg = va_arg(ap, const char *); - if (skipempty && arg && strlen(arg) == 0) - continue; - - argv[argc++] = arg; - - } while (arg != NULL); - - retval = pfcexec(path, argv[0], argv); - free(argv); - - return retval; -} - -int HIDDEN -xbps_file_exec(const char *arg, ...) -{ - va_list ap; - int result; - - va_start(ap, arg); - result = vfcexec(NULL, 0, arg, ap); - va_end(ap); - - return result; -} - -int HIDDEN -xbps_file_exec_skipempty(const char *arg, ...) -{ - va_list ap; - int result; - - va_start(ap, arg); - result = vfcexec(NULL, 1, arg, ap); - va_end(ap); - - return result; -} - -int HIDDEN -xbps_file_chdir_exec(const char *path, const char *arg, ...) -{ - va_list ap; - int result; - - va_start(ap, arg); - result = vfcexec(path, 0, arg, ap); - va_end(ap); - - return result; -} diff --git a/lib/file_exec.c b/lib/file_exec.c new file mode 100644 index 00000000..93b92159 --- /dev/null +++ b/lib/file_exec.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 2012 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xbps_api_impl.h" + +static int +pfcexec(const char *file, const char **argv) +{ + pid_t child; + int status, rv; + + if (((getuid() == 0) && (access("bin/sh", X_OK) == 0))) { + if ((chroot(".") != 0) && (chdir("/") != 0)) + return errno; + } + if ((rv = posix_spawn(&child, file, NULL, NULL, + (char ** const)__UNCONST(argv), + NULL)) == 0) { + while (waitpid(child, &status, 0) < 0) { + if (errno != EINTR) + return errno; + } + if (!WIFEXITED(status)) + return errno; + + return WEXITSTATUS(status); + } + return rv; +} + +static int +vfcexec(const char *arg, va_list ap) +{ + const char **argv; + size_t argv_size, argc; + int retval; + + argv_size = 16; + if ((argv = malloc(argv_size * sizeof(*argv))) == NULL) { + errno = ENOMEM; + return -1; + } + argv[0] = arg; + argc = 1; + + do { + if (argc == argv_size) { + argv_size *= 2; + argv = realloc(argv, argv_size * sizeof(*argv)); + if (argv == NULL) { + errno = ENOMEM; + return -1; + } + } + arg = va_arg(ap, const char *); + argv[argc++] = arg; + + } while (arg != NULL); + + retval = pfcexec(argv[0], argv); + free(argv); + + return retval; +} + +int HIDDEN +xbps_file_exec(const char *arg, ...) +{ + va_list ap; + int result; + + va_start(ap, arg); + result = vfcexec(arg, ap); + va_end(ap); + + return result; +}