From 2075e719ad3e7f1d9848d517ec723abd3b1599b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Thu, 12 Apr 2018 12:15:39 +0200 Subject: [PATCH] New upstream version 0.4.3 --- .gitignore | 22 +- .travis.yml | 51 +++ Makefile.am | 93 ++++-- README | 22 -- README.md | 34 ++ VERSION | 1 + {m4 => config/m4}/ax_pthread.m4 | 0 config/m4/custom_checks.m4 | 139 +++++++++ config/m4/utils.m4 | 94 ++++++ configure.ac | 79 +++-- debian/changelog | 83 +++++ debian/compat | 1 + debian/control | 33 ++ debian/copyright | 37 +++ debian/docs | 1 + debian/libfixposix-dev.install | 4 + debian/libfixposix3.install | 1 + debian/libfixposix3.symbols | 118 +++++++ debian/rules | 10 + debian/source/format | 1 + debian/source/options | 1 + libfixposix.spec.in | 61 ++++ m4/custom_checks.m4 | 83 ----- m4/utils.m4 | 43 --- src/include/lfp.h | 4 +- src/include/lfp/aux.h | 20 +- src/include/lfp/buildinfo.h | 42 +++ src/include/lfp/dirent.h | 14 +- src/include/lfp/errno.h | 4 +- src/include/lfp/fcntl.h | 6 +- src/{lib/utils.h => include/lfp/ioctl.h} | 46 +-- src/include/lfp/mman.h | 6 +- src/include/lfp/resource.h | 4 +- src/include/lfp/select.h | 5 +- src/include/lfp/sendfile.h | 4 +- src/include/lfp/signal.h | 6 +- src/include/lfp/signalfd.h | 4 +- src/include/lfp/socket.h | 7 +- src/include/lfp/spawn.h | 16 +- src/include/lfp/stat.h | 4 +- src/include/lfp/stdlib.h | 10 +- src/include/lfp/strerror.h | 38 +++ src/include/lfp/string.h | 30 +- src/include/lfp/syslog.h | 4 +- src/include/lfp/{time.h => time.h.in} | 22 +- src/include/lfp/unistd.h | 15 +- src/include/lfp/wait.h | 4 +- src/lib/aux/inlines.h | 72 +++++ src/lib/aux/macros.h | 44 +++ src/lib/bitset.c | 61 ++++ src/lib/bitset.h | 38 +++ src/lib/buildinfo.c.in | 44 +++ src/lib/dirent.c | 35 ++- src/lib/errno.c | 8 +- src/lib/fcntl.c | 25 +- src/lib/install_signalfd.c | 4 - src/lib/ioctl.c | 61 ++++ src/lib/mman.c | 10 +- src/lib/resource.c | 9 +- src/lib/select.c | 23 +- src/lib/sendfile.c | 16 +- src/lib/signal.c | 24 +- src/lib/socket.c | 58 +++- src/lib/spawn.c | 111 ++++--- src/lib/spawn_file_actions.c | 119 ++++--- src/lib/spawnattr.c | 89 +++--- src/lib/stat.c | 35 ++- src/lib/stdlib.c | 141 +++++++-- src/lib/strerror.c | 42 +++ src/lib/string.c | 113 +++++-- src/lib/syslog.c | 33 +- src/lib/time.c | 155 ++++++--- src/lib/unistd.c | 127 ++++++-- src/lib/wait.c | 30 +- src/libfixposix.libtool | 5 + libfixposix.pc.in => src/libfixposix.pc.in | 4 +- src/tests/buildinfo.bats.in | 26 ++ src/tests/buildinfo.c | 19 ++ src/tests/lib/LICENSE | 20 ++ src/tests/lib/bats | 142 +++++++++ src/tests/lib/bats-exec-suite | 55 ++++ src/tests/lib/bats-exec-test | 346 +++++++++++++++++++++ src/tests/lib/bats-format-tap-stream | 165 ++++++++++ src/tests/lib/bats-preprocess | 52 ++++ src/tests/mkstemp.c | 65 ++++ src/tests/select.c | 5 +- src/tests/spawn.c | 16 +- 87 files changed, 3101 insertions(+), 673 deletions(-) create mode 100644 .travis.yml delete mode 100644 README create mode 100644 README.md create mode 100644 VERSION rename {m4 => config/m4}/ax_pthread.m4 (100%) create mode 100644 config/m4/custom_checks.m4 create mode 100644 config/m4/utils.m4 create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100644 debian/libfixposix-dev.install create mode 100644 debian/libfixposix3.install create mode 100644 debian/libfixposix3.symbols create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/source/options create mode 100644 libfixposix.spec.in delete mode 100644 m4/custom_checks.m4 delete mode 100644 m4/utils.m4 create mode 100644 src/include/lfp/buildinfo.h rename src/{lib/utils.h => include/lfp/ioctl.h} (65%) create mode 100644 src/include/lfp/strerror.h rename src/include/lfp/{time.h => time.h.in} (83%) create mode 100644 src/lib/aux/inlines.h create mode 100644 src/lib/aux/macros.h create mode 100644 src/lib/bitset.c create mode 100644 src/lib/bitset.h create mode 100644 src/lib/buildinfo.c.in create mode 100644 src/lib/ioctl.c create mode 100644 src/lib/strerror.c create mode 100644 src/libfixposix.libtool rename libfixposix.pc.in => src/libfixposix.pc.in (72%) create mode 100644 src/tests/buildinfo.bats.in create mode 100644 src/tests/buildinfo.c create mode 100644 src/tests/lib/LICENSE create mode 100755 src/tests/lib/bats create mode 100755 src/tests/lib/bats-exec-suite create mode 100755 src/tests/lib/bats-exec-test create mode 100755 src/tests/lib/bats-format-tap-stream create mode 100755 src/tests/lib/bats-preprocess create mode 100644 src/tests/mkstemp.c diff --git a/.gitignore b/.gitignore index ca72f49..0325b87 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,9 @@ -Makefile -Makefile.in aclocal.m4 autom4te.cache/ +config/aux/ +config/m4/libtool.m4 +config/m4/lt*.m4 build/ -.build-aux/ -config.* configure -libtool -m4/l*.m4 -src/.* -*.lo -*.o -*.la -src/signalfd_test -.deps/ -.dirstamp -.libs/ -src/lib/libfixposix.h -src/tests/signalfd_test -src/tests/spawn_test +config.h.in* +Makefile.in diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d61a993 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,51 @@ +branches: + only: + - master + +os: + - linux + - osx +language: c +compiler: + - gcc + - clang + +matrix: + allow_failures: + - os: osx + +notifications: + email: + on_success: change + on_failure: always + irc: + channels: + - "chat.freenode.net#iolib" + on_success: change + on_failure: always + use_notice: true + skip_join: true + +before_install: + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -qq check; fi + +env: + global: + # Coverity Scan token + secure: "jJirBkZOyJ8KuYXMbjUpKem2FGaCsLBq7roP9oHs5mz8wIKENGB3i7pBe5USVLCwVAuqJ+TPjbfSo4nSnCIf5mLdJoNnyrq8FAYhSRzA/zl4COW6eN0Of9dgCOzcOriPY9rXUVbIapWoMogntnAS6MpmbiSxQCsq99VsIHq3TYk=" + +script: + - autoreconf -f -i + - ./configure --enable-tests + - make -j2 + - make check + +addons: + coverity_scan: + project: + name: sionescu/libfixposix + build_command_prepend: autoreconf -f -i && ./configure --enable-tests + build_command: make -j4 + branch_pattern: coverity + notification_email: sionescu@cddr.org diff --git a/Makefile.am b/Makefile.am index 292b99a..a8f8314 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,13 +6,22 @@ # # ######################################################################## -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I config/m4 -AM_CPPFLAGS = $(LFP_CPPFLAGS) +AM_CFLAGS = $(LFP_CFLAGS) -fvisibility=hidden -AM_CFLAGS = $(LFP_CFLAGS) +AM_CPPFLAGS = -include $(top_builddir)/config.h \ + -include $(top_srcdir)/src/lib/aux/macros.h \ + -I$(top_srcdir)/src/include \ + -I$(top_builddir)/src/include -INCLUDES = -I$(top_builddir)/src/include -I$(top_srcdir)/src/include +EXTRA_DIST = \ + LICENCE \ + VERSION \ + libfixposix.spec \ + debian \ + src/tests/lib \ + $(wildcard $(top_srcdir)/src/tests/*.in) @@ -23,7 +32,7 @@ INCLUDES = -I$(top_builddir)/src/include -I$(top_srcdir)/src/include ######################################################################## pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libfixposix.pc +pkgconfig_DATA = src/libfixposix.pc @@ -38,7 +47,11 @@ lib_LTLIBRARIES = src/lib/libfixposix.la # Private headers, used only for internal definitions # The only purpose of this definition it to ensure that # «make dist» knows about them -noinst_HEADERS = src/lib/utils.h src/lib/spawn.h +noinst_HEADERS = \ + src/lib/aux/inlines.h \ + src/lib/aux/macros.h \ + src/lib/bitset.h \ + src/lib/spawn.h include_HEADERS = src/include/lfp.h @@ -47,10 +60,12 @@ include_lfp_HEADERS = \ src/include/lfp/aux.h \ src/include/lfp/stdlib.h \ src/include/lfp/string.h \ + src/include/lfp/strerror.h \ src/include/lfp/errno.h \ src/include/lfp/fcntl.h \ src/include/lfp/stat.h \ src/include/lfp/unistd.h \ + src/include/lfp/ioctl.h \ src/include/lfp/mman.h \ src/include/lfp/select.h \ src/include/lfp/socket.h \ @@ -58,35 +73,47 @@ include_lfp_HEADERS = \ src/include/lfp/signal.h \ src/include/lfp/spawn.h \ src/include/lfp/dirent.h \ - src/include/lfp/time.h \ + $(top_builddir)/src/include/lfp/time.h \ src/include/lfp/resource.h \ src/include/lfp/sendfile.h \ - src/include/lfp/syslog.h + src/include/lfp/syslog.h \ + src/include/lfp/buildinfo.h # src/include/lfp/signalfd.h src_lib_libfixposix_la_SOURCES = \ + src/libfixposix.libtool \ src/lib/stdlib.c \ src/lib/string.c \ + src/lib/strerror.c \ src/lib/errno.c \ src/lib/fcntl.c \ src/lib/stat.c \ src/lib/unistd.c \ + src/lib/ioctl.c \ src/lib/mman.c \ src/lib/select.c \ src/lib/socket.c \ src/lib/wait.c \ src/lib/signal.c \ src/lib/spawnattr.c \ + src/lib/bitset.c \ src/lib/spawn_file_actions.c \ src/lib/spawn.c \ src/lib/dirent.c \ src/lib/time.c \ src/lib/resource.c \ src/lib/sendfile.c \ - src/lib/syslog.c + src/lib/syslog.c \ + src/lib/buildinfo.c # src/lib/install_signalfd.c -src_lib_libfixposix_la_LIBADD = $(LFP_LDFLAGS) +src_lib_libfixposix_la_DEPENDENCIES = \ + src/libfixposix.libtool + +src_lib_libfixposix_la_LIBADD = $(LFP_LIBS) + +src_lib_libfixposix_la_LDFLAGS = $(LFP_LDFLAGS) -no-undefined \ + -version-info `@AWK@ '/^Version:/ { print $$2 }' $(top_srcdir)/src/libfixposix.libtool` @@ -96,22 +123,50 @@ src_lib_libfixposix_la_LIBADD = $(LFP_LDFLAGS) # # ######################################################################## -check_PROGRAMS = src/tests/spawn src/tests/select +if TESTS -check_SCRIPTS = +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' \ + TOP_SRCDIR=$(top_srcdir) \ + TOP_BUILDDIR=$(top_builddir) \ + $(SHELL) $(top_srcdir)/config/aux/tap-driver.sh -TESTS = ${check_PROGRAMS} ${check_SCRIPTS} -XFAIL_TESTS = +compile_tests = \ + src/tests/buildinfo +run_tests = \ + src/tests/spawn \ + src/tests/select \ + src/tests/mkstemp -# src_tests_signalfd_SOURCES = src/tests/signalfd.c +check_PROGRAMS = $(compile_tests) $(run_tests) -# src_tests_signalfd_LDADD = src/lib/libfixposix.la +check_SCRIPTS = \ + src/tests/buildinfo.bats -src_tests_spawn_SOURCES = src/tests/spawn.c +# Bats tests must be created by /.configure to get the correct path of +# the Bats interpreter, but the configure script fails to preserve the +# execute bit, so we restore it here. +%.bats: %.bats.in $(top_builddir)/Makefile + sed 's:\@BATSPATH\@:$(BATSPATH):' < $< > $@ + chmod +x $@ -src_tests_spawn_LDADD = src/lib/libfixposix.la +TESTS = ${run_tests} ${check_SCRIPTS} +XFAIL_TESTS = + +src_tests_buildinfo_SOURCES = src/tests/buildinfo.c +src_tests_buildinfo_CFLAGS = @CHECK_CFLAGS@ +src_tests_buildinfo_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libfixposix.la + +src_tests_spawn_SOURCES = src/tests/spawn.c +src_tests_spawn_CFLAGS = @CHECK_CFLAGS@ +src_tests_spawn_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libfixposix.la src_tests_select_SOURCES = src/tests/select.c +src_tests_select_CFLAGS = @CHECK_CFLAGS@ +src_tests_select_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libfixposix.la + +src_tests_mkstemp_SOURCES = src/tests/mkstemp.c +src_tests_mkstemp_CFLAGS = @CHECK_CFLAGS@ +src_tests_mkstemp_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libfixposix.la -src_tests_select_LDADD = src/lib/libfixposix.la +endif diff --git a/README b/README deleted file mode 100644 index 8a6f29b..0000000 --- a/README +++ /dev/null @@ -1,22 +0,0 @@ --*- outline -*- - -The purpose of libfixposix is to offer replacements for parts of POSIX -whose behaviour is inconsistent across *NIX flavours. - -* Compilation - -If you've downloaded this library through git, you'll first need to -generate the ./configure script; in order to do that you need to have -at least autoconf-2.67, automake-1.10 and libtool-2.2.6b and run -this inside the top directory: -> autoreconf -i - -For best results use a dedicated build directory instead of running -the configure script directly in the source tree: -> mkdir build ; cd build -> ../libfixposix/configure -> make -> make install - -On Linux, you might need to run «ldconfig» as superuser after -installing, otherwise the *nix linker won't be able to find the library diff --git a/README.md b/README.md new file mode 100644 index 0000000..3b46c42 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +-*- markdown -*- + +The purpose of libfixposix is to offer replacements for parts of POSIX +whose behaviour is inconsistent across *NIX flavours. + +* Compilation + +If you've downloaded this library through git, you'll first need to +generate the ./configure script; in order to do that you need to have +at least autoconf-2.67, automake-1.10, libtool-2.2.6b, pkg-config and check (for +the test suite: see http://check.sf.net) then run this inside the top +directory: +> autoreconf -i -f + +For best results use a dedicated build directory instead of running +the configure script directly in the source tree: +> mkdir build ; cd build +> ../libfixposix/configure +> make +> make install + +On Linux, you might need to run «ldconfig» as superuser after +installing, otherwise the *nix linker won't be able to find the library + +* Installation through distro repositories + +For a certain number of Linux distributions, there are officially +supported repositories. +You can find the instructions to configure the binary repository at +https://software.opensuse.org/download.html?project=home:sionescu&package=libfixposix. +Just click on your distribution, if present. + +http://article.gmane.org/gmane.lisp.iolib.devel/422 also has a set of +older instructions about installing on Debian-based distros. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..17b2ccd --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.4.3 diff --git a/m4/ax_pthread.m4 b/config/m4/ax_pthread.m4 similarity index 100% rename from m4/ax_pthread.m4 rename to config/m4/ax_pthread.m4 diff --git a/config/m4/custom_checks.m4 b/config/m4/custom_checks.m4 new file mode 100644 index 0000000..0781279 --- /dev/null +++ b/config/m4/custom_checks.m4 @@ -0,0 +1,139 @@ +# -*- Autoconf -*- + +AC_DEFUN([LFP_TESTS_CHECK], [ +AC_ARG_ENABLE([tests], + [AS_HELP_STRING([--enable-tests], + [enable test suite using CHECK @<:@default=no@:>@])], + [], + [enable_tests=no]) +AS_CASE($enable_tests, + [yes], [PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) + AC_SUBST([CHECK_CFLAGS]) + AC_SUBST([CHECK_LIBS])], + [no], [], + AC_MSG_ERROR( + [--enable-tests was given an illegal value: "$enable_tests"]) +) +AM_CONDITIONAL(TESTS, test x$enable_tests = xyes) +]) + +AC_DEFUN([LFP_INIT], [ + # Build flags + LFP_CFLAGS="" + AC_SUBST(LFP_CFLAGS) + LFP_LDFLAGS="" + AC_SUBST(LFP_LDFLAGS) + LFP_LIBS="" + AC_SUBST(LFP_LIBS) + # Version Info + major=`echo $1 | cut -d . -f 1` + AC_SUBST(LFP_MAJOR_VERSION, $major) + minor=`echo $1 | cut -d . -f 2` + AC_SUBST(LFP_MINOR_VERSION, $minor) + micro=`echo $1 | cut -d . -f 3` + AC_SUBST(LFP_MICRO_VERSION, $micro) + AC_CHECK_PROG([GIT], [git], [yes]) + if test "x$ac_cv_prog_GIT" = xyes + then + vcsid=`git rev-parse --short HEAD` + fi + AC_SUBST(LFP_VCSID, $vcsid) +]) + +AC_DEFUN([LFP_SYS_PLATFORM_SPECIFIC_DEFINITIONS], [ + case "$host_os" in + linux*) + LFP_CFLAGS="$LFP_CFLAGS -D_XOPEN_SOURCE=600 -D_GNU_SOURCE=1" + ;; + freebsd*) + LFP_CFLAGS="$LFP_CFLAGS -D_XOPEN_SOURCE=600 -D__BSD_VISIBLE" + ;; + netbsd*) + LFP_CFLAGS="$LFP_CFLAGS -D_XOPEN_SOURCE=600 -D_NETBSD_SOURCE" + ;; + openbsd*) + LFP_CFLAGS="$LFP_CFLAGS -D__BSD_VISIBLE" + ;; + darwin*) + LFP_CFLAGS="$LFP_CFLAGS -D_DARWIN_C_SOURCE" + ;; + sunos* | solaris*) + LFP_CFLAGS="$LFP_CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS" + ;; + esac +]) + +AC_DEFUN([LFP_SYS_LARGEFILE], [ + LFP_GETCONF_UNDEF([LFS_CFLAGS], [LFS_CFLAGS]) + LFP_GETCONF_UNDEF([LFS_LDFLAGS], [LFS_LDFLAGS]) + LFP_GETCONF_UNDEF([LFS_LIBS], [LFS_LIBS]) +]) + +AC_DEFUN([LFP_CHECK_POSIX_REALTIME_CLOCK_TYPES], [ + LFP_REQUIRE_TYPE([clockid_t], [sys/time.h time.h]) + AC_SUBST([HAVE_CLOCKID_T], [1]) + LFP_REQUIRE_DECL([CLOCK_REALTIME], [sys/time.h time.h]) + LFP_REQUIRE_DECL([CLOCK_MONOTONIC], [sys/time.h time.h]) +]) + +AC_DEFUN([LFP_CHECK_POSIX_REALTIME_CLOCK_ALTERNATIVES], [ + case "$host_os" in + darwin*) + LFP_REQUIRE_HEADERS([mach/mach.h mach/clock.h]) + LFP_REQUIRE_FUNCS([host_get_clock_service clock_get_attributes]) + dnl LFP_REQUIRE_DECL([CLOCK_GET_TIME_RES], [mach/mach.h mach/clock.h]) + dnl LFP_REQUIRE_DECL([CALENDAR_CLOCK], [mach/mach.h mach/clock.h]) + dnl LFP_REQUIRE_DECL([REALTIME_CLOCK], [mach/mach.h mach/clock.h]) + ;; + *) + AC_MSG_ERROR([clock_gettime not found and no workaround available]) + ;; + esac +]) + +AC_DEFUN([LFP_REQUIRE_MONOTONIC_CLOCK], [ + LFP_SEARCH_LIBS([clock_gettime], [rt], [ + AC_SUBST([HAVE_CLOCK_GETTIME], [1]) + LFP_CHECK_POSIX_REALTIME_CLOCK_TYPES + AC_DEFINE([HAVE_CLOCK_GETTIME], [1], + [We have the function clock_gettime()])], + [AC_SUBST([HAVE_CLOCK_GETTIME], [0]) + AC_SUBST([HAVE_CLOCKID_T], [0]) + LFP_CHECK_POSIX_REALTIME_CLOCK_ALTERNATIVES]) +]) + +AC_DEFUN([LFP_REQUIRE_GETPEEREID], [ + AC_CHECK_FUNCS([getpeereid], + [AC_DEFINE([HAVE_GETPEEREID], [1], [We have the function getpeereid()])], + AC_CHECK_FUNCS([getpeerucred], + [LFP_REQUIRE_HEADERS([ucred.h]) + AC_DEFINE([HAVE_GETPEERUCRED], [1], [We have the function getpeerucred()])], + [LFP_REQUIRE_DECL([SO_PEERCRED], [sys/types.h sys/socket.h])])) +]) + +AC_DEFUN([LFP_ARG_ENABLE_EMULATED_SIGNALFD], [ +AC_ARG_ENABLE([emulated-signalfd], + [AS_HELP_STRING([--enable-emulated-signalfd={yes|no|check}], + [Use emulated signalfd @<:@default=check@:>@])], + [], + [enable_emulated_signalfd=check]) +AS_CASE($enable_emulated_signalfd, + [yes], [AC_DEFINE(HAVE_EMULATED_SIGNALFD, 1, [Whether to use signalfd emulation]) + AC_SUBST(HAVE_EMULATED_SIGNALFD, 1) + ], + [check], [if test x"$ac_cv_header_sys_signalfd_h" = xyes ; then + AC_DEFINE(HAVE_EMULATED_SIGNALFD, 0, [Whether to use signalfd emulation]) + AC_SUBST(HAVE_EMULATED_SIGNALFD, 0) + else + AC_DEFINE(HAVE_EMULATED_SIGNALFD, 1, [Whether to use signalfd emulation]) + AC_SUBST(HAVE_EMULATED_SIGNALFD, 1) + fi], + [no], [if test x"$ac_cv_header_sys_signalfd_h" = xyes ; then + AC_DEFINE(HAVE_EMULATED_SIGNALFD, 0, [Whether to use signalfd emulation]) + AC_SUBST(HAVE_EMULATED_SIGNALFD, 0) + else + AC_MSG_FAILURE([signalfd emulation was disabled although is absent]) + fi], + [AC_MSG_FAILURE( + [--enable-emulated-signalfd was given an illegal value: "$enable_emulated_signalfd"])]) +]) diff --git a/config/m4/utils.m4 b/config/m4/utils.m4 new file mode 100644 index 0000000..ef0b4e7 --- /dev/null +++ b/config/m4/utils.m4 @@ -0,0 +1,94 @@ +# -*- Autoconf -*- + +AC_DEFUN([LFP_SAVE_FLAGS], [ + _lfp_saved_cppflags_$1=$CPPFLAGS + _lfp_saved_cflags_$1=$CFLAGS + _lfp_saved_ldflags_$1=$LDFLAGS + _lfp_saved_libs_$1=$LIBS + CPPFLAGS="$LFP_CPPFLAGS" + CFLAGS="$LFP_CFLAGS" + LDFLAGS="$LFP_LDFLAGS" + LIBS="$LFP_LIBS" +]) + +AC_DEFUN([LFP_RESTORE_FLAGS], [ + CPPFLAGS="$_lfp_saved_cppflags_$1" + CFLAGS="$_lfp_saved_cflags_$1" + LDFLAGS="$_lfp_saved_ldflags_$1" + LIBS="$_lfp_saved_libs_$1" +]) + +# Check for some headers and print an error if not found +AC_DEFUN([LFP_REQUIRE_HEADERS], [ + LFP_SAVE_FLAGS(AS_TR_CPP($1)) + AC_CHECK_HEADERS($1,,AC_MSG_FAILURE([Cannot find header $ac_header])) + LFP_RESTORE_FLAGS(AS_TR_CPP($1)) +]) + +# Check for a function and print an error if not found +AC_DEFUN([LFP_REQUIRE_FUNCS], [ + LFP_SAVE_FLAGS(AS_TR_CPP($1)) + AC_CHECK_FUNCS($1,,AC_MSG_FAILURE([Cannot find function $ac_func])) + LFP_RESTORE_FLAGS(AS_TR_CPP($1)) +]) + +# Check for a type and print an error if not found +AC_DEFUN([LFP_REQUIRE_TYPE], [ + LFP_SAVE_FLAGS(AS_TR_CPP($1)) + AC_CHECK_TYPES($1,,AC_MSG_FAILURE([Cannot find type $1 in $2]), + [m4_foreach_w([header], [$2], [[#]include [<]header[>] + ])]) + LFP_RESTORE_FLAGS(AS_TR_CPP($1)) +]) + +# Check for a declaration and print an error if not found +AC_DEFUN([LFP_REQUIRE_DECL], [ + LFP_SAVE_FLAGS(AS_TR_CPP($1)) + AC_CHECK_DECL($1,,AC_MSG_FAILURE([Cannot find $1 in <$2>]), + [m4_foreach_w([header], [$2], [[#]include [<]header[>] + ])]) + LFP_RESTORE_FLAGS(AS_TR_CPP($1)) +]) + +# Check for a library and print an error if not found +AC_DEFUN([LFP_SEARCH_LIBS], [ + LFP_SAVE_FLAGS(AS_TR_CPP($1)) + AC_SEARCH_LIBS($1,$2,$3 + [if test -n "$LIBS"; then LFP_LIBS="$LFP_LIBS $LIBS"; fi], + m4_default_nblank_quoted([$4],AC_MSG_FAILURE([Cannot find $1 in <$2>]))) + LFP_RESTORE_FLAGS(AS_TR_CPP($1)) +]) + +AC_DEFUN([LFP_REQUIRE_PROG], [ + AC_CHECK_PROG($1, $2, [yes]) + if test "x$ac_cv_prog_$1" != xyes + then + AC_MSG_FAILURE([Program $2 not found]) + fi +]) + +# Check for a declaration and print an error if not found +# Syntax: LFP_GETCONF(VARIABLE, SYSTEM_VAR, +# ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +AC_DEFUN([LFP_GETCONF], [ + $1=`(getconf $2) 2>/dev/null` + AC_SUBST($1) + if test $? -eq 0 ; then + : ; $3 + else + : ; $4 + fi +]) + +# Check for a declaration and print an error if not found or is undefined +# Syntax: LFP_GETCONF(VARIABLE, SYSTEM_VAR, +# ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +AC_DEFUN([LFP_GETCONF_UNDEF], [ + $1=`(getconf $2) 2>/dev/null` + AC_SUBST($1) + if test $? -eq 0 && test x"$$1" != xundefined ; then + : ; $3 + else + : ; $4 + fi +]) diff --git a/configure.ac b/configure.ac index 9218766..a1a5146 100644 --- a/configure.ac +++ b/configure.ac @@ -9,19 +9,33 @@ dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. dnl Minimum Autoconf version required. -AC_INIT([LibFixPOSIX], [0.1], [iolib-devel@common-lisp.net], - [libfixposix], [http://common-lisp.net/project/iolib/]) AC_PREREQ([2.67]) + +AC_INIT([LibFixPOSIX], m4_esyscmd_s([cat VERSION]), + [iolib-devel@common-lisp.net], + [libfixposix], [https://github.com/sionescu/libfixposix]) +AC_COPYRIGHT([Copyright © 2010-2018 Stelian Ionescu ]) + +AC_MSG_NOTICE([srcdir: $srcdir]) +AC_MSG_NOTICE([builddir: $builddir]) +AC_MSG_NOTICE([CPPFLAGS: $CPPFLAGS]) +AC_MSG_NOTICE([CFLAGS: $CFLAGS]) +AC_MSG_NOTICE([LDFLAGS: $LDFLAGS]) +AS_IF([test "`/bin/pwd`" = "`cd $srcdir; /bin/pwd`"], [ + AC_MSG_WARN([you should configure in a separate build directory]) +]) + AC_CONFIG_HEADERS([config.h]) dnl Where to generate output; srcdir location. AC_CONFIG_SRCDIR([src/lib/spawn.c]) dnl Auxiliary M4 macros -AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_MACRO_DIR([config/m4]) dnl Must come before AM_INIT_AUTOMAKE. -AC_CONFIG_AUX_DIR([.build-aux]) +AC_CONFIG_AUX_DIR([config/aux]) + AM_INIT_AUTOMAKE([1.10 foreign silent-rules subdir-objects color-tests parallel-tests]) @@ -31,49 +45,68 @@ AM_SILENT_RULES([yes]) dnl Contains replacement functions # AC_CONFIG_LIBOBJ_DIR([lib]) +AC_LANG([C]) + dnl Checks for programs. # We need a C compiler. AC_PROG_CC_C99 +AC_PROG_AWK # And we need libtool for building the shared library -LT_INIT +LT_INIT([pic-only disable-static disable-fast-install]) +LT_PREREQ([2.2.6]) -LFP_FLAGS_INIT +AC_SUBST([PACKAGE_VERSION]) +LFP_INIT($PACKAGE_VERSION) dnl Checks for programs -AC_CHECK_PROG([GETCONF], [getconf], [yes]) -if test "x$ac_cv_prog_GETCONF" != xyes -then - AC_MSG_FAILURE([Program getconf not found]) -fi +LFP_REQUIRE_PROG([GETCONF], [getconf]) dnl Set compiler & linker flags LFP_SYS_PLATFORM_SPECIFIC_DEFINITIONS AX_PTHREAD LFP_SYS_LARGEFILE -LFP_CPPFLAGS+=" $LFS_CFLAGS" -LFP_CFLAGS+=" $PTHREAD_CFLAGS" -LFP_LDFLAGS+=" $PTHREAD_LIBS $LFS_LDFLAGS $LFS_LIBS" - dnl Checks for C99 & POSIX headers AC_HEADER_ASSERT +AC_HEADER_STDBOOL LFP_REQUIRE_HEADERS([stdlib.h stdio.h string.h errno.h time.h]) -LFP_REQUIRE_HEADERS([sys/types.h unistd.h fcntl.h signal.h]) -AC_CHECK_HEADER([sys/signalfd.h]) +LFP_REQUIRE_HEADERS([sys/types.h unistd.h fcntl.h sys/signal.h signal.h]) + +LFP_CFLAGS="$LFP_CFLAGS $LFS_CFLAGS $PTHREAD_CFLAGS" +LFP_LDFLAGS="$LFP_LDFLAGS $LFS_LDFLAGS" +LFP_LIBS="$LFP_LIBS $PTHREAD_LIBS $LFS_LIBS" dnl Checks for declarations -LFP_REQUIRE_DECLS([NSIG], [signal.h]) +LFP_REQUIRE_DECL([TIOCSCTTY], [sys/ioctl.h]) +LFP_REQUIRE_DECL([NSIG], [sys/types.h sys/signal.h signal.h]) +LFP_REQUIRE_DECL([IP_HDRINCL], [sys/types.h sys/socket.h netinet/in.h]) + +dnl Checks for non-standard headers +AC_CHECK_HEADER([sys/signalfd.h]) dnl Checks for functions -AC_CHECK_FUNCS([__xpg_strerror_r strnlen strndup]) -AC_CHECK_FUNCS([accept4 pipe2 sendfile]) -LFP_REQUIRE_FUNCS([pselect vsyslog]) -LFP_CHECK_POSIX_MONOTONIC_CLOCK +AC_CHECK_FUNCS([__xpg_strerror_r strnlen strndup clearenv]) +LFP_REQUIRE_FUNCS([strtok_r]) +LFP_SEARCH_LIBS([socket], [socket nsl]) +AC_CHECK_FUNCS([accept4 pipe2 sendfile pselect ptsname_r]) +LFP_REQUIRE_FUNCS([vsyslog ptsname posix_openpt]) +LFP_REQUIRE_MONOTONIC_CLOCK +LFP_REQUIRE_GETPEEREID dnl Checks for types dnl Configuration switches # LFP_ARG_ENABLE_EMULATED_SIGNALFD -AC_CONFIG_FILES([Makefile libfixposix.pc]) +# Test suite. +LFP_TESTS_CHECK +AC_SUBST([BATSPATH], [$srcdir/src/tests/lib]) + +AC_CONFIG_FILES([Makefile + libfixposix.spec + src/libfixposix.pc + src/lib/buildinfo.c + src/include/lfp/time.h]) + +AC_REQUIRE_AUX_FILE([tap-driver.sh]) AC_OUTPUT diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..a61a2d2 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,83 @@ +libfixposix (0.4.3) unstable; urgency=low + + * Release 0.4.3 + + -- Stelian Ionescu Mon, 19 Feb 2018 21:00:00 +0100 + +libfixposix (0.4.2) unstable; urgency=low + + * Release 0.4.2 + + -- Stelian Ionescu Sat, 17 Feb 2018 15:00:00 +0100 + +libfixposix (0.4.1) unstable; urgency=low + + * Release 0.4.1 + + -- Stelian Ionescu Thu, 23 Jun 2016 21:00:00 +0200 + +libfixposix (0.4.0) unstable; urgency=low + + * Release 0.4.0 + + -- Stelian Ionescu Tue, 3 May 2016 20:00:00 +0200 + +libfixposix (0.3.0-1) unstable; urgency=low + + * Release 0.3.0 + + -- Stelian Ionescu Tue, 5 Mar 2013 12:00:00 +0200 + +libfixposix (0.2.4-3) unstable; urgency=low + + * Add symbols file + + -- Stelian Ionescu Tue, 26 Jun 2012 20:48:00 +0200 + +libfixposix (0.2.4-2) unstable; urgency=low + + * Update copyright file + + -- Stelian Ionescu Tue, 26 Jun 2012 20:23:00 +0200 + +libfixposix (0.2.4-1) unstable; urgency=low + + * Increase epoch to 1 + + -- Stelian Ionescu Tue, 26 Jun 2012 19:17:00 +0200 + +libfixposix (0.2.4-1) unstable; urgency=low + + * Release 0.2.4 + + -- Stelian Ionescu Wed, 12 Jun 2012 16:45:00 +0200 + +libfixposix (0.2.3-1) unstable; urgency=low + + * Release 0.2.3 + + -- Stelian Ionescu Wed, 12 Jun 2012 15:57:00 +0200 + +libfixposix (0.2.2-1) unstable; urgency=low + + * Release 0.2.2 + + -- Stelian Ionescu Wed, 30 May 2012 18:13:00 +0200 + +libfixposix (0.2.1-1) unstable; urgency=low + + * Release 0.2.1 + + -- Stelian Ionescu Fri, 25 Nov 2011 23:08:12 +0200 + +libfixposix (0.2-1) unstable; urgency=low + + * Release 0.2 + + -- Stelian Ionescu Mon, 14 Nov 2011 15:52:33 +0200 + +libfixposix (0.1-1) unstable; urgency=low + + * Initial package + + -- Stelian Ionescu Tue, 6 Sep 2011 01:55:44 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..ac12f64 --- /dev/null +++ b/debian/control @@ -0,0 +1,33 @@ +Source: libfixposix +Priority: optional +Section: libdevel +Maintainer: Stelian Ionescu +Standards-Version: 3.9.8 +Build-Depends: cdbs (>= 0.4.58), debhelper (>= 9), pkg-config (>= 0.25), check (>= 0.9.4) +Homepage: https://github.com/sionescu/libfixposix + +Package: libfixposix3 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Thin wrapper over POSIX syscalls + The purpose of libfixposix is to offer replacements for parts of POSIX + whose behaviour is inconsistent across *NIX flavours + . + This package contains the shared library. + +Package: libfixposix-dev +Architecture: any +Depends: libfixposix3 (= ${binary:Version}), libc6-dev, ${misc:Depends} +Description: Development files for LibFixPOSIX + . + This package contains header files and static archives. + +Package: libfixposix-dbg +Section: debug +Priority: extra +Depends: libfixposix3 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: Debug package for LibFixPOSIX + . + This package contains debugging symbols useful for gdb. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..d486423 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,37 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: LibFixPOSIX +Upstream-Contact: Stelian Ionescu +Source: https://github.com/sionescu/libfixposix/releases/ + +Files: * +Copyright: 2010-2016 Stelian Ionescu + 2010 Francois-Rene Rideau + 2011 David Lichteblau +License: BSL + +Files: debian/* +Copyright: 2010-2016 Stelian Ionescu +License: BSL + +License: BSL + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + . + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..b43bf86 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README.md diff --git a/debian/libfixposix-dev.install b/debian/libfixposix-dev.install new file mode 100644 index 0000000..fda50e9 --- /dev/null +++ b/debian/libfixposix-dev.install @@ -0,0 +1,4 @@ +usr/include/ +usr/lib/libfixposix.so +usr/lib/libfixposix.a +usr/lib/pkgconfig/libfixposix.pc diff --git a/debian/libfixposix3.install b/debian/libfixposix3.install new file mode 100644 index 0000000..189ca31 --- /dev/null +++ b/debian/libfixposix3.install @@ -0,0 +1 @@ +usr/lib/libfixposix.so.* diff --git a/debian/libfixposix3.symbols b/debian/libfixposix3.symbols new file mode 100644 index 0000000..63796d9 --- /dev/null +++ b/debian/libfixposix3.symbols @@ -0,0 +1,118 @@ +libfixposix.so.3 libfixposix3 #MINVER# + lfp_accept@Base 0.3.0 + lfp_buildinfo@Base 0.4.3 + lfp_clearenv@Base 0.3.0 + lfp_clock_getres@Base 0.3.0 + lfp_clock_gettime@Base 0.3.0 + lfp_clock_settime@Base 0.3.0 + lfp_closedir@Base 0.4.0 + lfp_closelog@Base 0.3.0 + lfp_cmsg_data@Base 0.3.0 + lfp_cmsg_firsthdr@Base 0.3.0 + lfp_cmsg_len@Base 0.3.0 + lfp_cmsg_nxthdr@Base 0.3.0 + lfp_cmsg_space@Base 0.3.0 + lfp_creat@Base 0.3.0 + lfp_errno@Base 0.3.0 + lfp_execve@Base 0.3.0 + lfp_execvpe@Base 0.3.0 + lfp_fd_clr@Base 0.3.0 + lfp_fd_isset@Base 0.3.0 + lfp_fd_set@Base 0.3.0 + lfp_fd_zero@Base 0.3.0 + lfp_fstat@Base 0.3.0 + lfp_ftruncate@Base 0.3.0 + lfp_get_environ@Base 0.3.0 + lfp_getpath@Base 0.3.0 + lfp_getpeereid@Base 0.3.0 + lfp_getrlimit@Base 0.3.0 + lfp_is_fd_cloexec@Base 0.3.0 + lfp_is_fd_nonblock@Base 0.3.0 + lfp_is_fd_open@Base 0.3.0 + lfp_isblk@Base 0.3.0 + lfp_ischr@Base 0.3.0 + lfp_isdir@Base 0.3.0 + lfp_isfifo@Base 0.3.0 + lfp_islnk@Base 0.3.0 + lfp_isreg@Base 0.3.0 + lfp_issock@Base 0.3.0 + lfp_log_mask@Base 0.3.0 + lfp_log_upto@Base 0.3.0 + lfp_lseek@Base 0.3.0 + lfp_lstat@Base 0.3.0 + lfp_mkostemp@Base 0.3.0 + lfp_mkstemp@Base 0.3.0 + lfp_mmap@Base 0.3.0 + lfp_munmap@Base 0.3.0 + lfp_open@Base 0.3.0 + lfp_opendir@Base 0.4.0 + lfp_openlog@Base 0.3.0 + lfp_openpt@Base 0.3.0 + lfp_parse_memsize@Base 0.3.0 + lfp_pipe@Base 0.3.0 + lfp_pread@Base 0.3.0 + lfp_ptsname@Base 0.3.0 + lfp_pwrite@Base 0.3.0 + lfp_readdir@Base 0.3.0 + lfp_rewinddir@Base 0.4.0 + lfp_seekdir@Base 0.4.0 + lfp_select@Base 0.3.0 + lfp_sendfile@Base 0.3.0 + lfp_set_environ@Base 0.3.0 + lfp_set_errno@Base 0.3.0 + lfp_set_fd_cloexec@Base 0.3.0 + lfp_set_fd_nonblock@Base 0.3.0 + lfp_setlogmask@Base 0.3.0 + lfp_setrlimit@Base 0.3.0 + lfp_sig_dfl@Base 0.3.0 + lfp_sig_err@Base 0.3.0 + lfp_sig_hold@Base 0.3.0 + lfp_sig_ign@Base 0.3.0 + lfp_sigrtmax@Base 0.3.0 + lfp_sigrtmin@Base 0.3.0 + lfp_socket@Base 0.3.0 + lfp_spawn@Base 0.3.0 + lfp_spawn_file_actions_addclose@Base 0.3.0 + lfp_spawn_file_actions_adddup2@Base 0.3.0 + lfp_spawn_file_actions_addkeep@Base 0.4.0 + lfp_spawn_file_actions_addopen@Base 0.3.0 + lfp_spawn_file_actions_destroy@Base 0.3.0 + lfp_spawn_file_actions_init@Base 0.3.0 + lfp_spawnattr_destroy@Base 0.3.0 + lfp_spawnattr_getctty@Base 0.3.0 + lfp_spawnattr_getcwd@Base 0.3.0 + lfp_spawnattr_getflags@Base 0.3.0 + lfp_spawnattr_getgid@Base 0.3.0 + lfp_spawnattr_getpgroup@Base 0.3.0 + lfp_spawnattr_getsigdefault@Base 0.3.0 + lfp_spawnattr_getsigmask@Base 0.3.0 + lfp_spawnattr_getuid@Base 0.3.0 + lfp_spawnattr_init@Base 0.3.0 + lfp_spawnattr_setctty@Base 0.3.0 + lfp_spawnattr_setcwd@Base 0.3.0 + lfp_spawnattr_setflags@Base 0.3.0 + lfp_spawnattr_setgid@Base 0.3.0 + lfp_spawnattr_setpgroup@Base 0.3.0 + lfp_spawnattr_setsid@Base 0.3.0 + lfp_spawnattr_setsigdefault@Base 0.3.0 + lfp_spawnattr_setsigmask@Base 0.3.0 + lfp_spawnattr_setuid@Base 0.3.0 + lfp_spawnp@Base 0.3.0 + lfp_stat@Base 0.3.0 + lfp_strerror@Base 0.3.0 + lfp_strndup@Base 0.3.0 + lfp_strnlen@Base 0.3.0 + lfp_syslog@Base 0.3.0 + lfp_telldir@Base 0.4.0 + lfp_truncate@Base 0.3.0 + lfp_tty_attach@Base 0.3.0 + lfp_tty_fattach@Base 0.3.0 + lfp_vsyslog@Base 0.3.0 + lfp_wcoredump@Base 0.3.0 + lfp_wexitstatus@Base 0.3.0 + lfp_wifcontinued@Base 0.3.0 + lfp_wifexited@Base 0.3.0 + lfp_wifsignaled@Base 0.3.0 + lfp_wifstopped@Base 0.3.0 + lfp_wstopsig@Base 0.3.0 + lfp_wtermsig@Base 0.3.0 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..916537f --- /dev/null +++ b/debian/rules @@ -0,0 +1,10 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/autotools.mk + +DEB_CONFIGURE_EXTRA_FLAGS := --enable-static --with-pic --enable-tests +DEB_MAKE_BUILD_TARGET := all +DEB_MAKE_CHECK_TARGET := check +DEB_DH_MAKESHLIBS_ARGS := -V diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 0000000..c5ca455 --- /dev/null +++ b/debian/source/options @@ -0,0 +1 @@ +compression = "gzip" diff --git a/libfixposix.spec.in b/libfixposix.spec.in new file mode 100644 index 0000000..d4e3570 --- /dev/null +++ b/libfixposix.spec.in @@ -0,0 +1,61 @@ +Name: libfixposix +Summary: POSIX syscall wrappers +Version: @PACKAGE_VERSION@ +Release: 0 +License: BSL-1.0 +Group: Development/Libraries/C and C++ +URL: https://github.com/sionescu/%{name} +Source: https://github.com/sionescu/%{name}/releases/download/v%{version}/%{name}_%{version}.tar.gz + +%define srcdir %{name} + +BuildRequires: check-devel pkgconfig +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +Thin wrapper over POSIX syscalls and some replacement functionality, most notably lfp_spawn(). + +%package -n libfixposix3 +Summary: Shared library for libfixposix +Group: Development/Libraries/C and C++ + +%description -n libfixposix3 +Thin wrapper over POSIX syscalls. + +%package -n libfixposix-devel +Summary: Development files +Group: Development/Libraries/C and C++ +Requires: glibc-devel +Requires: libfixposix3 = %{version}-%{release} +Provides: %{name}-static = %{version}-%{release} + +%description devel +Header files, static libraries and API documentation for using libfixposix. + +%prep +%setup -q -n %{srcdir} + +%build +%configure --enable-static --with-pic --enable-tests +make %{?_smp_mflags} + +%check +make %{?_smp_mflags} check + +%install +make %{?_smp_mflags} DESTDIR=%{buildroot} install +find %{buildroot} -type f -name "*.la" -delete -print + +%post -n libfixposix3 -p /sbin/ldconfig +%postun -n libfixposix3 -p /sbin/ldconfig + +%files -n libfixposix3 +%defattr(-,root,root) +%{_libdir}/lib*so.* + +%files -n libfixposix-devel +%defattr(-,root,root) +%{_includedir}/* +%{_libdir}/lib*.so +%{_libdir}/lib*.a +%{_libdir}/pkgconfig/libfixposix.pc diff --git a/m4/custom_checks.m4 b/m4/custom_checks.m4 deleted file mode 100644 index 22fb375..0000000 --- a/m4/custom_checks.m4 +++ /dev/null @@ -1,83 +0,0 @@ -# -*- Autoconf -*- - -AC_DEFUN([LFP_FLAGS_INIT], [ -LFP_CPPFLAGS="-D_XOPEN_SOURCE" -LFP_CFLAGS="" -LFP_LDFLAGS="" -AC_SUBST(LFP_CPPFLAGS) -AC_SUBST(LFP_CFLAGS) -AC_SUBST(LFP_LDFLAGS) -]) - -AC_DEFUN([LFP_SYS_PLATFORM_SPECIFIC_DEFINITIONS], [ -case "$host" in - *-*-linux*) - LFP_CPPFLAGS+=" -D_GNU_SOURCE=1" - LFP_LDFLAGS+=" -lrt" - ;; - *-*-freebsd*) - LFP_CPPFLAGS+=" -D__BSD_VISIBLE" - ;; - *-apple-darwin*) - LFP_CPPFLAGS+=" -D_DARWIN_C_SOURCE" - ;; - *-sunos*|*-solaris*) - LFP_CPPFLAGS+=" -D__EXTENSIONS__ -D_XPG4 -D_XPG4_2" - ;; -esac -]) - -AC_DEFUN([LFP_SYS_LARGEFILE], [ -LFP_GETCONF_UNDEF([LFS_CFLAGS], [LFS_CFLAGS]) -LFP_GETCONF_UNDEF([LFS_LDFLAGS], [LFS_LDFLAGS]) -LFP_GETCONF_UNDEF([LFS_LIBS], [LFS_LIBS]) -]) - -AC_DEFUN([LFP_CHECK_SIZEOF_CLOCKID_T], [ -AC_CHECK_TYPE([clockid_t], - [AC_CHECK_SIZEOF([clockid_t], [], [[#include ]]) - if test "$ac_cv_sizeof_clockid_t" -gt 4 ; then - AC_MSG_FAILURE([Type clockid_t is larger than 32 bits]) - fi], - [case "$host" in - *-apple-darwin*) : ;; - *) AC_MSG_FAILURE([Type clockid_t not found]) ;; - esac], - [[#include ]]) -]) - -AC_DEFUN([LFP_CHECK_POSIX_MONOTONIC_CLOCK], [ -LFP_GETCONF_UNDEF([POSIX_MONOTONIC_CLOCK], [_POSIX_MONOTONIC_CLOCK], - [LFP_CHECK_SIZEOF_CLOCKID_T], - [case "$host" in - *-apple-darwin*) : ;; - *) AC_MSG_FAILURE([Type clockid_t not found]) ;; - esac]) -]) - -AC_DEFUN([LFP_ARG_ENABLE_EMULATED_SIGNALFD], [ -AC_ARG_ENABLE([emulated-signalfd], - [AS_HELP_STRING([--enable-emulated-signalfd={yes|no|check}], - [Use emulated signalfd @<:@default=check@:>@])], - [], - [enable_emulated_signalfd=check]) -AS_CASE($enable_emulated_signalfd, - [yes], [AC_DEFINE(HAVE_EMULATED_SIGNALFD, 1, [Whether to use signalfd emulation]) - AC_SUBST(HAVE_EMULATED_SIGNALFD, 1) - ], - [check], [if test x"$ac_cv_header_sys_signalfd_h" = xyes ; then - AC_DEFINE(HAVE_EMULATED_SIGNALFD, 0, [Whether to use signalfd emulation]) - AC_SUBST(HAVE_EMULATED_SIGNALFD, 0) - else - AC_DEFINE(HAVE_EMULATED_SIGNALFD, 1, [Whether to use signalfd emulation]) - AC_SUBST(HAVE_EMULATED_SIGNALFD, 1) - fi], - [no], [if test x"$ac_cv_header_sys_signalfd_h" = xyes ; then - AC_DEFINE(HAVE_EMULATED_SIGNALFD, 0, [Whether to use signalfd emulation]) - AC_SUBST(HAVE_EMULATED_SIGNALFD, 0) - else - AC_MSG_FAILURE([signalfd emulation was disabled although is absent]) - fi], - [AC_MSG_FAILURE( - [--enable-emulated-signalfd was given an illegal value: "$enable_emulated_signalfd"])]) -]) diff --git a/m4/utils.m4 b/m4/utils.m4 deleted file mode 100644 index 5881561..0000000 --- a/m4/utils.m4 +++ /dev/null @@ -1,43 +0,0 @@ -# -*- Autoconf -*- - -# Check for some headers and print an error if not found -AC_DEFUN([LFP_REQUIRE_HEADERS], - [AC_CHECK_HEADERS($1,,AC_MSG_FAILURE([Cannot find header(s) $1]))]) - -# Check for a function and print an error if not found -AC_DEFUN([LFP_REQUIRE_FUNCS], - [AC_CHECK_FUNCS($1,,AC_MSG_FAILURE([Cannot find function(s) $1]))]) - -# Check for a type and print an error if not found -AC_DEFUN([LFP_REQUIRE_TYPE], - [AC_CHECK_TYPE($1,,AC_MSG_FAILURE([Cannot find type $1 in $2]), - [[#include <$2>]])]) - -# Check for a declaration and print an error if not found -AC_DEFUN([LFP_REQUIRE_DECLS], - [AC_CHECK_DECLS($1,,AC_MSG_FAILURE([Cannot find $1 in $2]), - [[#include <$2>]])]) - -# Check for a declaration and print an error if not found -# Syntax: LFP_GETCONF(VARIABLE, SYSTEM_VAR, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) -AC_DEFUN([LFP_GETCONF], [ -$1=`(getconf $2) 2>/dev/null` -AC_SUBST($1) -if test $? -eq 0 ; then - : ; $3 -else - : ; $4 -fi -]) - -# Check for a declaration and print an error if not found or is undefined -# Syntax: LFP_GETCONF(VARIABLE, SYSTEM_VAR, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) -AC_DEFUN([LFP_GETCONF_UNDEF], [ -$1=`(getconf $2) 2>/dev/null` -AC_SUBST($1) -if test $? -eq 0 && test x"$$1" != xundefined ; then - : ; $3 -else - : ; $4 -fi -]) diff --git a/src/include/lfp.h b/src/include/lfp.h index c9da6aa..c6919c9 100644 --- a/src/include/lfp.h +++ b/src/include/lfp.h @@ -25,8 +25,6 @@ #if !defined(_LFP_H_) # define _LFP_H_ -#include - #include #include @@ -61,4 +59,6 @@ #include +#include + #endif /* _LFP_H_ */ diff --git a/src/include/lfp/aux.h b/src/include/lfp/aux.h index 21bbf02..22633b2 100644 --- a/src/include/lfp/aux.h +++ b/src/include/lfp/aux.h @@ -26,14 +26,24 @@ # define _LFP_AUX_H_ #if defined(__cplusplus) -# define CPLUSPLUS_GUARD extern "C" { -# define END_CPLUSPLUS_GUARD } +# define LFP_BEGIN_DECLS extern "C" { #else -# define CPLUSPLUS_GUARD -# define END_CPLUSPLUS_GUARD +# define LFP_BEGIN_DECLS #endif -#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L +#if defined(__cplusplus) +# define LFP_END_DECLS } +#else +# define LFP_END_DECLS +#endif + +#ifdef GCC +# define ATTRIBUTE_NONNULL __attribute__((nonnull (1))) +#else +# define ATTRIBUTE_NONNULL +#endif + +#if (__STDC_VERSION__ - 0) < 199901L // only C99 has restricted pointers # define restrict #endif diff --git a/src/include/lfp/buildinfo.h b/src/include/lfp/buildinfo.h new file mode 100644 index 0000000..b70b075 --- /dev/null +++ b/src/include/lfp/buildinfo.h @@ -0,0 +1,42 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#if !defined(_LFP_BUILDINFO_H_) +# define _LFP_BUILDINFO_H_ + +#include +#include + +LFP_BEGIN_DECLS + +struct lfp_buildinfo { + uint64_t release; + char vcsid[32+1]; +}; + +int lfp_buildinfo(struct lfp_buildinfo *v); + +LFP_END_DECLS + +#endif /* _LFP_BUILDINFO_H_ */ diff --git a/src/include/lfp/dirent.h b/src/include/lfp/dirent.h index f88b0a6..fe86bd1 100644 --- a/src/include/lfp/dirent.h +++ b/src/include/lfp/dirent.h @@ -27,12 +27,22 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include +DIR* lfp_opendir(const char *name); + int lfp_readdir(DIR *dirp, struct dirent *entry, struct dirent **result); -END_CPLUSPLUS_GUARD +long lfp_telldir(DIR *dirp); + +void lfp_seekdir(DIR *dirp, long offset); + +void lfp_rewinddir(DIR *dirp); + +int lfp_closedir(DIR *dirp); + +LFP_END_DECLS #endif /* _LFP_DIRENT_H_ */ diff --git a/src/include/lfp/errno.h b/src/include/lfp/errno.h index b952a66..6c79ed5 100644 --- a/src/include/lfp/errno.h +++ b/src/include/lfp/errno.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -37,6 +37,6 @@ int lfp_errno(void); int lfp_set_errno(int value); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LPF_ERRNO_H_ */ diff --git a/src/include/lfp/fcntl.h b/src/include/lfp/fcntl.h index 9ccdfa1..a8213a1 100644 --- a/src/include/lfp/fcntl.h +++ b/src/include/lfp/fcntl.h @@ -27,15 +27,13 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include #include #include -extern char **environ; - #if !defined(O_CLOEXEC) // Syscalls use "int" for passing flags, and since // *nix systems use the LP64 data model, "int" is 32 bits @@ -58,6 +56,6 @@ int lfp_is_fd_nonblock(int fd); int lfp_set_fd_nonblock(int fd, bool enabled); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_FCNTL_H_ */ diff --git a/src/lib/utils.h b/src/include/lfp/ioctl.h similarity index 65% rename from src/lib/utils.h rename to src/include/lfp/ioctl.h index 6ef44bc..ec2a4f7 100644 --- a/src/lib/utils.h +++ b/src/include/lfp/ioctl.h @@ -22,46 +22,22 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#if !defined(_LFP_INTERNAL_UTILS_H_) -# define _LFP_INTERNAL_UTILS_H_ +#if !defined(_LFP_IOCTL_H_) +# define _LFP_IOCTL_H_ -#include -#include -#include -#if defined(__APPLE__) -# include -#endif - -static inline void -_lfp_timespec_to_timeval(struct timespec *ts, struct timeval *tv) -{ - tv->tv_sec = ts->tv_sec; - tv->tv_usec = ts->tv_nsec / 1000; -} +#include -static inline void -_lfp_timeval_to_timespec(struct timeval *tv, struct timespec *ts) -{ - ts->tv_sec = tv->tv_sec; - ts->tv_nsec = tv->tv_usec * 1000; -} +LFP_BEGIN_DECLS -#if defined(__APPLE__) -static inline void -_lfp_timespec_to_mach_timespec_t(struct timespec *ts, mach_timespec_t *mts) -{ - mts->tv_sec = ts->tv_sec; - mts->tv_nsec = ts->tv_nsec; -} -#endif +#include +#include -#define SYSERR(errcode) do { errno = errcode; return -1; } while(0) +#include -#define SYSCHECK(errcode,expr) do { if(expr) SYSERR(errcode); } while(0) +int lfp_tty_attach(const char *path); -#define SYSGUARD(expr) do { if((expr) < 0) return(-1); } while(0) +int lfp_tty_fattach(int fd); -/* not checking for OPEN_MAX, which might not be valid, on Linux */ -#define INVALID_FD(fd) ( fd < 0 ) +LFP_END_DECLS -#endif /* _LFP_INTERNAL_UTILS_H_ */ +#endif /* _LFP_IOCTL_H_ */ diff --git a/src/include/lfp/mman.h b/src/include/lfp/mman.h index 9fa9910..cb16695 100644 --- a/src/include/lfp/mman.h +++ b/src/include/lfp/mman.h @@ -27,15 +27,15 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include -void *lfp_mmap(void *addr, size_t length, int prot, +void* lfp_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int lfp_munmap(void *addr, size_t length); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_MMAN_H_ */ diff --git a/src/include/lfp/resource.h b/src/include/lfp/resource.h index 4ad7a26..27e3d69 100644 --- a/src/include/lfp/resource.h +++ b/src/include/lfp/resource.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -35,6 +35,6 @@ int lfp_getrlimit(int resource, struct rlimit *rlim); int lfp_setrlimit(int resource, const struct rlimit *rlim); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LPF_RESOURCE_H_ */ diff --git a/src/include/lfp/select.h b/src/include/lfp/select.h index ca5c758..1094f74 100644 --- a/src/include/lfp/select.h +++ b/src/include/lfp/select.h @@ -27,9 +27,10 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include +#include #include @@ -44,6 +45,6 @@ void lfp_fd_set(int fd, fd_set *set); void lfp_fd_zero(fd_set *set); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SELECT_H_ */ diff --git a/src/include/lfp/sendfile.h b/src/include/lfp/sendfile.h index 7580444..acb6a95 100644 --- a/src/include/lfp/sendfile.h +++ b/src/include/lfp/sendfile.h @@ -27,12 +27,12 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include ssize_t lfp_sendfile(int out_fd, int in_fd, off_t offset, size_t nbytes); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SENDFILE_H_ */ diff --git a/src/include/lfp/signal.h b/src/include/lfp/signal.h index c0edf43..758474a 100644 --- a/src/include/lfp/signal.h +++ b/src/include/lfp/signal.h @@ -27,8 +27,10 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS +#include +#include #include typedef void (*lfp_sighandler_t) (int); @@ -45,6 +47,6 @@ int lfp_sigrtmin(void); int lfp_sigrtmax(void); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SIGNAL_H_ */ diff --git a/src/include/lfp/signalfd.h b/src/include/lfp/signalfd.h index ab41072..c70c387 100644 --- a/src/include/lfp/signalfd.h +++ b/src/include/lfp/signalfd.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -45,6 +45,6 @@ int lfp_install_signalfd(int signum, int sa_flags, bool* blockp); int lfp_uninstall_signalfd(int signum, bool block); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SIGNALFD_H_ */ diff --git a/src/include/lfp/socket.h b/src/include/lfp/socket.h index 2a20087..3808528 100644 --- a/src/include/lfp/socket.h +++ b/src/include/lfp/socket.h @@ -27,8 +27,9 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS +#include #include #include @@ -50,6 +51,8 @@ size_t lfp_cmsg_len(size_t length); void* lfp_cmsg_data(struct cmsghdr* cmsg); -END_CPLUSPLUS_GUARD +int lfp_getpeereid(int socket, uid_t *euid, gid_t *egid); + +LFP_END_DECLS #endif /* _LFP_SOCKET_H_ */ diff --git a/src/include/lfp/spawn.h b/src/include/lfp/spawn.h index d174def..109a7e3 100644 --- a/src/include/lfp/spawn.h +++ b/src/include/lfp/spawn.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include #include @@ -36,9 +36,12 @@ CPLUSPLUS_GUARD #include typedef struct { - int initialized; - int allocated; + uint initialized; + uint allocated; struct lfp_spawn_action *actions; + bool keep_descriptors; + int *kfd; + int kfd_size; } lfp_spawn_file_actions_t; int lfp_spawn_file_actions_init(lfp_spawn_file_actions_t *file_actions); @@ -55,6 +58,9 @@ int lfp_spawn_file_actions_addclose(lfp_spawn_file_actions_t *file_actions, int lfp_spawn_file_actions_adddup2(lfp_spawn_file_actions_t *file_actions, int fd, int newfd); +int lfp_spawn_file_actions_addkeep(lfp_spawn_file_actions_t *file_actions, + int fd); + typedef struct { uint32_t flags; sigset_t sigdefault; @@ -85,6 +91,8 @@ typedef enum { #define LFP_SPAWN_SETSID ( 1 << 7 ) LFP_SPAWN_SETCTTY = 1 << 8, #define LFP_SPAWN_SETCTTY ( 1 << 8 ) + LFP_SPAWN_USEVFORK = 1 << 9, +#define LFP_SPAWN_USEVFORK ( 1 << 9 ) } lfp_spawnattr_flags; int lfp_spawnattr_init(lfp_spawnattr_t *attr); @@ -130,6 +138,6 @@ int lfp_spawnp(pid_t *restrict pid, const lfp_spawn_file_actions_t *restrict file_actions, const lfp_spawnattr_t *restrict attr); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SPAWN_H_ */ diff --git a/src/include/lfp/stat.h b/src/include/lfp/stat.h index 01eed88..56cba48 100644 --- a/src/include/lfp/stat.h +++ b/src/include/lfp/stat.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -55,6 +55,6 @@ bool lfp_islnk(mode_t mode); bool lfp_issock(mode_t mode); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_STAT_H_ */ diff --git a/src/include/lfp/stdlib.h b/src/include/lfp/stdlib.h index d158211..49af841 100644 --- a/src/include/lfp/stdlib.h +++ b/src/include/lfp/stdlib.h @@ -27,16 +27,20 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS + +#include #include int lfp_mkstemp(char *tmplate); +int lfp_mkostemp(char *tmplate, uint64_t flags); + char* lfp_getpath(char *const envp[]); -char *lfp_ptsname(int masterfd); +int lfp_ptsname(int masterfd, char *buf, size_t buflen); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_STDLIB_H_ */ diff --git a/src/include/lfp/strerror.h b/src/include/lfp/strerror.h new file mode 100644 index 0000000..ad5055e --- /dev/null +++ b/src/include/lfp/strerror.h @@ -0,0 +1,38 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#if !defined(_LFP_STRING_H_) +# define _LFP_STRING_H_ + +#include + +LFP_BEGIN_DECLS + +#include + +int lfp_strerror(int errnum, char *buf, size_t buflen); + +LFP_END_DECLS + +#endif /* _LFP_STRING_H_ */ diff --git a/src/include/lfp/string.h b/src/include/lfp/string.h index 9d8b438..dd89b84 100644 --- a/src/include/lfp/string.h +++ b/src/include/lfp/string.h @@ -27,16 +27,36 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS +#include +#include #include -int lfp_strerror(int errnum, char *buf, size_t buflen); +#include size_t lfp_strnlen(const char *s, size_t maxlen); -char *lfp_strndup(const char *s, size_t maxlen); - -END_CPLUSPLUS_GUARD +char* lfp_strndup(const char *s, size_t maxlen); + +enum lfp_memsize_measure_unit { + LFP_OCTETS = 0, + LFP_KB, + LFP_KIB, + LFP_MB, + LFP_MIB, + LFP_GB, + LFP_GIB, + LFP_TB, + LFP_TIB, + LFP_PB, + LFP_PIB, + LFP_EB, + LFP_EIB +}; + +int64_t lfp_parse_memsize(const char *s, enum lfp_memsize_measure_unit default_unit); + +LFP_END_DECLS #endif /* _LFP_STRING_H_ */ diff --git a/src/include/lfp/syslog.h b/src/include/lfp/syslog.h index 7917fc9..200cf83 100644 --- a/src/include/lfp/syslog.h +++ b/src/include/lfp/syslog.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -47,6 +47,6 @@ int lfp_log_mask(int priority); int lfp_log_upto(int priority); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_SYSLOG_H_ */ diff --git a/src/include/lfp/time.h b/src/include/lfp/time.h.in similarity index 83% rename from src/include/lfp/time.h rename to src/include/lfp/time.h.in index e60b8e5..407a896 100644 --- a/src/include/lfp/time.h +++ b/src/include/lfp/time.h.in @@ -27,28 +27,28 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS -#include #include +#include #include -typedef uint64_t lfp_clockid_t; +#if ! @HAVE_CLOCKID_T@ +typedef int clockid_t; +#endif // HAVE_CLOCKID_T -#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 +#if ! @HAVE_CLOCK_GETTIME@ # define CLOCK_REALTIME 0 # define CLOCK_MONOTONIC 1 -#elif !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 -# define CLOCK_MONOTONIC (1 << 32) -#endif +#endif // HAVE_CLOCK_GETTIME -int lfp_clock_getres(lfp_clockid_t clk_id, struct timespec *res); +int lfp_clock_getres(clockid_t clk_id, struct timespec *res); -int lfp_clock_gettime(lfp_clockid_t clk_id, struct timespec *tp); +int lfp_clock_gettime(clockid_t clk_id, struct timespec *tp); -int lfp_clock_settime(lfp_clockid_t clk_id, struct timespec *tp); +int lfp_clock_settime(clockid_t clk_id, struct timespec *tp); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_TIME_H_ */ diff --git a/src/include/lfp/unistd.h b/src/include/lfp/unistd.h index 2104730..a9fa68c 100644 --- a/src/include/lfp/unistd.h +++ b/src/include/lfp/unistd.h @@ -27,12 +27,19 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS +#include #include #include +char **lfp_get_environ(void); + +int lfp_set_environ(char **newenv); + +int lfp_clearenv(void); + off_t lfp_lseek(int fd, off_t offset, int whence); int lfp_pipe(int pipefd[2], uint64_t flags); @@ -46,11 +53,11 @@ int lfp_truncate(const char *path, off_t length); int lfp_ftruncate(int fd, off_t length); int lfp_execve(const char *path, char *const argv[], char *const envp[]) - __attribute__((nonnull (1))); + ATTRIBUTE_NONNULL; int lfp_execvpe(const char *file, char *const argv[], char *const envp[]) - __attribute__((nonnull (1))); + ATTRIBUTE_NONNULL; -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_UNISTD_H_ */ diff --git a/src/include/lfp/wait.h b/src/include/lfp/wait.h index b6bac81..b12f734 100644 --- a/src/include/lfp/wait.h +++ b/src/include/lfp/wait.h @@ -27,7 +27,7 @@ #include -CPLUSPLUS_GUARD +LFP_BEGIN_DECLS #include @@ -49,6 +49,6 @@ int lfp_wstopsig(int status); bool lfp_wifcontinued(int status); -END_CPLUSPLUS_GUARD +LFP_END_DECLS #endif /* _LFP_WAIT_H_ */ diff --git a/src/lib/aux/inlines.h b/src/lib/aux/inlines.h new file mode 100644 index 0000000..a0b1e5d --- /dev/null +++ b/src/lib/aux/inlines.h @@ -0,0 +1,72 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#if !defined(_LFP_INTERNAL_AUX_INLINES_H_) +# define _LFP_INTERNAL_AUX_INLINES_H_ + +#include +#include +#include +#include +#if defined(__APPLE__) +# include +#endif + +static inline +void _lfp_timespec_to_timeval(const struct timespec *ts, struct timeval *tv) +{ + tv->tv_sec = ts->tv_sec; + // Syscalls often have special code paths for null timeouts + // so set this to 1 microsecond + if(ts->tv_sec == 0 && ts->tv_nsec > 0 && ts->tv_nsec <= 1000) + tv->tv_usec = 1; + else + tv->tv_usec = ts->tv_nsec / 1000; +} + +#if defined(__APPLE__) +static inline +void _lfp_mach_timespec_t_to_timespec(const mach_timespec_t *mts, + struct timespec *ts) +{ + ts->tv_sec = mts->tv_sec; + ts->tv_nsec = mts->tv_nsec; +} +#endif + +/* xorshift rng from Marsaglia */ +static inline uint32_t +_xorshift(uint32_t y) +{ + if (y == 0) return 1; /* 0 is a degenerate case + we won't reach this unless + stores to uint32_t are non-atomic + for thread-safety we need this. + */ + y ^= y << 13; + y ^= y >> 17; + return (y ^ (y << 5)); +} + +#endif /* _LFP_INTERNAL_AUX_INLINES_H_ */ diff --git a/src/lib/aux/macros.h b/src/lib/aux/macros.h new file mode 100644 index 0000000..5c89700 --- /dev/null +++ b/src/lib/aux/macros.h @@ -0,0 +1,44 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#if !defined(_LFP_INTERNAL_AUX_MACROS_H_) +# define _LFP_INTERNAL_AUX_MACROS_H_ + +#include + +#define SYSERR(errcode) \ + do { errno = errcode; return -1; } while(0) + +#define SYSCHECK(errcode,expr) \ + do { if(expr) SYSERR(errcode); } while(0) + +#define SYSGUARD(expr) \ + do { if((expr) < 0) return(-1); } while(0) + +#define GET_ERRNO(expr) \ + (expr) == -1 ? lfp_errno() : 0 + +#define DSO_PUBLIC __attribute__ ((visibility ("default"))) + +#endif /* _LFP_INTERNAL_AUX_MACROS_H_ */ diff --git a/src/lib/bitset.c b/src/lib/bitset.c new file mode 100644 index 0000000..b4a57c5 --- /dev/null +++ b/src/lib/bitset.c @@ -0,0 +1,61 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#include +#include +#include + +#include "bitset.h" + +#define NBITS (sizeof(int) * 8) + +int +bitset_alloc(int **bitset, size_t size) +{ + size_t alloc_size = (size / 8) + ((size % 8) ? 1 : 0); + if (posix_memalign((void**)bitset, sizeof(uint64_t), alloc_size) < 0 ) + return -1; + memset(*bitset, 0, alloc_size); + return 0; +} + +int +bitset_insert(int *bitset, int i) +{ + bitset[i / NBITS] |= (1 << (i % NBITS)); + return 0; +} + +int +bitset_delete(int *bitset, int i) +{ + bitset[i / NBITS] &= ~(1 << (i % NBITS)); + return 0; +} + +bool +bitset_contains(int *bitset, int i) +{ + return bitset[i / NBITS] & (1 << (i % NBITS)) ? true : false; +} diff --git a/src/lib/bitset.h b/src/lib/bitset.h new file mode 100644 index 0000000..de6c904 --- /dev/null +++ b/src/lib/bitset.h @@ -0,0 +1,38 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#if !defined(_LFP_BITSET_H_) +# define _LFP_BITSET_H_ + +#include + +int bitset_alloc(int **bitset, size_t size); + +int bitset_insert(int *bitset, int i); + +int bitset_delete(int *bitset, int i); + +bool bitset_contains(int *bitset, int i); + +#endif // _LFP_BITSET_H_ diff --git a/src/lib/buildinfo.c.in b/src/lib/buildinfo.c.in new file mode 100644 index 0000000..c6aed53 --- /dev/null +++ b/src/lib/buildinfo.c.in @@ -0,0 +1,44 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#include + +#include + +#define MAJOR__ (@LFP_MAJOR_VERSION@ << 16) +#define MINOR__ (@LFP_MINOR_VERSION@ << 8) +#define MICRO__ @LFP_MICRO_VERSION@ +#define VCSID__ "@LFP_VCSID@" + +DSO_PUBLIC int +lfp_buildinfo(struct lfp_buildinfo *v) +{ + SYSCHECK(EINVAL, v == NULL); + v->release = (uint64_t) MAJOR__ | MINOR__ | MICRO__; + memset(v->vcsid, 0, sizeof(v->vcsid)); + // TODO: Switch sources to C11 and use _Static_assert. + SYSCHECK(EINVAL, sizeof(VCSID__) > sizeof(v->vcsid)); + strncpy(v->vcsid, VCSID__, sizeof(v->vcsid)); + return 0; +} diff --git a/src/lib/dirent.c b/src/lib/dirent.c index ea7001d..403f0c9 100644 --- a/src/lib/dirent.c +++ b/src/lib/dirent.c @@ -22,13 +22,18 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include -int lfp_readdir(DIR *dirp, struct dirent *entry, struct dirent **result) +DSO_PUBLIC DIR* +lfp_opendir(const char *name) +{ + return opendir(name); +} + +DSO_PUBLIC int +lfp_readdir(DIR *dirp, struct dirent *entry, struct dirent **result) { int ret = readdir_r(dirp, entry, result); if ( ret > 0 ) { @@ -40,3 +45,27 @@ int lfp_readdir(DIR *dirp, struct dirent *entry, struct dirent **result) return 1; } } + +DSO_PUBLIC long +lfp_telldir(DIR *dirp) +{ + return telldir(dirp); +} + +DSO_PUBLIC void +lfp_seekdir(DIR *dirp, long offset) +{ + return seekdir(dirp, offset); +} + +DSO_PUBLIC void +lfp_rewinddir(DIR *dirp) +{ + return rewinddir(dirp); +} + +DSO_PUBLIC int +lfp_closedir(DIR *dirp) +{ + return closedir(dirp); +} diff --git a/src/lib/errno.c b/src/lib/errno.c index 284f22c..6842bf7 100644 --- a/src/lib/errno.c +++ b/src/lib/errno.c @@ -22,16 +22,16 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include -int lfp_errno () +DSO_PUBLIC int +lfp_errno (void) { return errno; } -int lfp_set_errno (int value) +DSO_PUBLIC int +lfp_set_errno (int value) { errno = value; return errno; diff --git a/src/lib/fcntl.c b/src/lib/fcntl.c index 78f7120..5d4777d 100644 --- a/src/lib/fcntl.c +++ b/src/lib/fcntl.c @@ -22,8 +22,6 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include @@ -31,9 +29,8 @@ #include #include -#include "utils.h" - -int lfp_open (const char *pathname, uint64_t flags, ...) +DSO_PUBLIC int +lfp_open (const char *pathname, uint64_t flags, ...) { if (flags & O_CREAT) { va_list args; @@ -46,7 +43,8 @@ int lfp_open (const char *pathname, uint64_t flags, ...) } } -int lfp_openpt (uint64_t flags) +DSO_PUBLIC int +lfp_openpt (uint64_t flags) { bool cloexec = flags & O_CLOEXEC; flags &= ~O_CLOEXEC; @@ -61,14 +59,16 @@ int lfp_openpt (uint64_t flags) } } -int lfp_creat (const char *pathname, mode_t mode) +DSO_PUBLIC int +lfp_creat (const char *pathname, mode_t mode) { return creat(pathname, mode); } -int lfp_is_fd_cloexec (int fd) +DSO_PUBLIC int +lfp_is_fd_cloexec (int fd) { int current_flags = fcntl(fd, F_GETFD); if (current_flags < 0) { @@ -78,7 +78,8 @@ int lfp_is_fd_cloexec (int fd) } } -int lfp_set_fd_cloexec (int fd, bool enabled) +DSO_PUBLIC int +lfp_set_fd_cloexec (int fd, bool enabled) { int current_flags = fcntl(fd, F_GETFD); if (current_flags < 0) { @@ -94,7 +95,8 @@ int lfp_set_fd_cloexec (int fd, bool enabled) } } -int lfp_is_fd_nonblock (int fd) +DSO_PUBLIC int +lfp_is_fd_nonblock (int fd) { int current_flags = fcntl(fd, F_GETFL); if (current_flags < 0) { @@ -104,7 +106,8 @@ int lfp_is_fd_nonblock (int fd) } } -int lfp_set_fd_nonblock (int fd, bool enabled) +DSO_PUBLIC int +lfp_set_fd_nonblock (int fd, bool enabled) { int current_flags = fcntl(fd, F_GETFL); if (current_flags < 0) { diff --git a/src/lib/install_signalfd.c b/src/lib/install_signalfd.c index 536ce0c..c475646 100644 --- a/src/lib/install_signalfd.c +++ b/src/lib/install_signalfd.c @@ -22,12 +22,8 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include -#include "utils.h" - static struct signalfd_params { int read_fd; int write_fd; diff --git a/src/lib/ioctl.c b/src/lib/ioctl.c new file mode 100644 index 0000000..54ab096 --- /dev/null +++ b/src/lib/ioctl.c @@ -0,0 +1,61 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +DSO_PUBLIC int +lfp_tty_attach(const char *path) +{ + SYSCHECK(EINVAL, path == NULL); + SYSCHECK(ENOENT, path[0] == '\0'); + + int ttyfd; + + SYSGUARD(ttyfd = lfp_open(path, O_RDONLY | O_NOCTTY)); + if (lfp_tty_fattach(ttyfd) < 0) { + int saved_errno = lfp_errno(); + close(ttyfd); + SYSERR(saved_errno); + } else { + close(ttyfd); + } + + return 0; +} + +DSO_PUBLIC int +lfp_tty_fattach(int fd) +{ + SYSGUARD(ioctl(fd, TIOCSCTTY, 0)); + + return 0; +} diff --git a/src/lib/mman.c b/src/lib/mman.c index 84c8432..bb3e9ef 100644 --- a/src/lib/mman.c +++ b/src/lib/mman.c @@ -22,17 +22,17 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include -void *lfp_mmap(void *addr, size_t length, int prot, - int flags, int fd, off_t offset) +DSO_PUBLIC void* +lfp_mmap(void *addr, size_t length, int prot, + int flags, int fd, off_t offset) { return mmap(addr, length, prot, flags, fd, offset); } -int lfp_munmap(void *addr, size_t length) +DSO_PUBLIC int +lfp_munmap(void *addr, size_t length) { return munmap(addr, length); } diff --git a/src/lib/resource.c b/src/lib/resource.c index ffff3b6..d7a9b71 100644 --- a/src/lib/resource.c +++ b/src/lib/resource.c @@ -22,17 +22,16 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include - -int lfp_getrlimit(int resource, struct rlimit *rlim) +DSO_PUBLIC int +lfp_getrlimit(int resource, struct rlimit *rlim) { return getrlimit(resource, rlim); } -int lfp_setrlimit(int resource, const struct rlimit *rlim) +DSO_PUBLIC int +lfp_setrlimit(int resource, const struct rlimit *rlim) { return setrlimit(resource, rlim); } diff --git a/src/lib/select.c b/src/lib/select.c index 22533b8..0ce7d35 100644 --- a/src/lib/select.c +++ b/src/lib/select.c @@ -22,41 +22,44 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include -#include "utils.h" +#include "aux/inlines.h" -int lfp_select(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, const struct timespec *timeout) +DSO_PUBLIC int +lfp_select(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timespec *timeout) { #if defined(HAVE_PSELECT) return pselect(nfds, readfds, writefds, exceptfds, timeout, NULL); #else struct timeval tv; _lfp_timespec_to_timeval(timeout, &tv); - return select(nfds, readfds, writefds, exceptfds, timeout); + return select(nfds, readfds, writefds, exceptfds, &tv); #endif } -void lfp_fd_clr(int fd, fd_set *set) +DSO_PUBLIC void +lfp_fd_clr(int fd, fd_set *set) { FD_CLR(fd, set); } -bool lfp_fd_isset(int fd, fd_set *set) +DSO_PUBLIC bool +lfp_fd_isset(int fd, fd_set *set) { return (bool) FD_ISSET(fd, set); } -void lfp_fd_set(int fd, fd_set *set) +DSO_PUBLIC void +lfp_fd_set(int fd, fd_set *set) { FD_SET(fd, set); } -void lfp_fd_zero(fd_set *set) +DSO_PUBLIC void +lfp_fd_zero(fd_set *set) { FD_ZERO(set); } diff --git a/src/lib/sendfile.c b/src/lib/sendfile.c index bb27c2f..a298a9b 100644 --- a/src/lib/sendfile.c +++ b/src/lib/sendfile.c @@ -22,30 +22,34 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #if defined(HAVE_SENDFILE) # if defined(__linux__) # include -# elif defined(__FreeBSD__) || defined(__APPLE__) +# elif defined(__FreeBSD__) || defined(__DragonFly__) # include # include # include +# elif defined(__APPLE__) +// OSX doesn't expose sendfile if XOPEN_SOURCE is defined +int sendfile(int, int, off_t, off_t *, void *, int); # endif #endif -#include "utils.h" +#include -ssize_t lfp_sendfile(int out_fd, int in_fd, off_t offset, size_t nbytes) +DSO_PUBLIC ssize_t +lfp_sendfile(int out_fd, int in_fd, off_t offset, size_t nbytes) { #if defined(HAVE_SENDFILE) # if defined(__linux__) off_t off = offset; return (ssize_t) sendfile(out_fd, in_fd, &off, nbytes); # elif defined(__FreeBSD__) - return (ssize_t) sendfile(in_fd, out_fd, offset, nbytes, NULL, SF_MNOWAIT); + return (ssize_t) sendfile(in_fd, out_fd, offset, nbytes, NULL, NULL, SF_MNOWAIT); +# elif defined(__DragonFly__) + return (ssize_t) sendfile(in_fd, out_fd, offset, nbytes, NULL, NULL, 0); # elif defined(__APPLE__) off_t len = nbytes; return (ssize_t) sendfile(in_fd, out_fd, offset, &len, NULL, 0); diff --git a/src/lib/signal.c b/src/lib/signal.c index bffbf01..08731bb 100644 --- a/src/lib/signal.c +++ b/src/lib/signal.c @@ -22,33 +22,38 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include -#include "utils.h" +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) +# include +#endif -lfp_sighandler_t lfp_sig_dfl (void) +DSO_PUBLIC lfp_sighandler_t +lfp_sig_dfl (void) { return SIG_DFL; } -lfp_sighandler_t lfp_sig_err (void) +DSO_PUBLIC lfp_sighandler_t +lfp_sig_err (void) { return SIG_ERR; } -lfp_sighandler_t lfp_sig_hold (void) +DSO_PUBLIC lfp_sighandler_t +lfp_sig_hold (void) { return SIG_HOLD; } -lfp_sighandler_t lfp_sig_ign (void) +DSO_PUBLIC lfp_sighandler_t +lfp_sig_ign (void) { return SIG_IGN; } -int lfp_sigrtmin (void) +DSO_PUBLIC int +lfp_sigrtmin (void) { #if defined(SIGRTMIN) return SIGRTMIN; @@ -57,7 +62,8 @@ int lfp_sigrtmin (void) #endif // SIGRTMIN } -int lfp_sigrtmax (void) +DSO_PUBLIC int +lfp_sigrtmax (void) { #if defined(SIGRTMAX) return SIGRTMAX; diff --git a/src/lib/socket.c b/src/lib/socket.c index a28b3c0..4a4ad32 100644 --- a/src/lib/socket.c +++ b/src/lib/socket.c @@ -22,13 +22,12 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include -int lfp_socket(int domain, int type, int protocol, uint64_t flags) +DSO_PUBLIC int +lfp_socket(int domain, int type, int protocol, uint64_t flags) { #if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) return socket(domain, @@ -53,10 +52,11 @@ int lfp_socket(int domain, int type, int protocol, uint64_t flags) #endif } -int lfp_accept(int sockfd, - struct sockaddr *addr, - socklen_t *addrlen, - uint64_t flags) +DSO_PUBLIC int +lfp_accept(int sockfd, + struct sockaddr *addr, + socklen_t *addrlen, + uint64_t flags) { // FIXME: This branch requires that SOCK_CLOEXEC and SOCK_NONBLOCK be // defined when accept4(2) is present. Should we add an Autoconf check ? @@ -81,30 +81,62 @@ int lfp_accept(int sockfd, return -1; #endif } - -struct cmsghdr* lfp_cmsg_firsthdr (struct msghdr* msgh) +DSO_PUBLIC struct cmsghdr* +lfp_cmsg_firsthdr (struct msghdr* msgh) { return CMSG_FIRSTHDR(msgh); } -struct cmsghdr* lfp_cmsg_nxthdr (struct msghdr* msgh, struct cmsghdr* cmsg) +DSO_PUBLIC struct cmsghdr* +lfp_cmsg_nxthdr (struct msghdr* msgh, struct cmsghdr* cmsg) { return CMSG_NXTHDR(msgh, cmsg); } -size_t lfp_cmsg_space (size_t length) +DSO_PUBLIC size_t +lfp_cmsg_space (size_t length) { return CMSG_SPACE(length); } -size_t lfp_cmsg_len (size_t length) +DSO_PUBLIC size_t +lfp_cmsg_len (size_t length) { return CMSG_LEN(length); } -void* lfp_cmsg_data (struct cmsghdr* cmsg) +DSO_PUBLIC void* +lfp_cmsg_data (struct cmsghdr* cmsg) { return CMSG_DATA(cmsg); } + + +DSO_PUBLIC int +lfp_getpeereid(int sockfd, uid_t *euid, gid_t *egid) +{ +#if defined(HAVE_GETPEEREID) + return getpeereid(sockfd, euid, egid); +#elif defined(HAVE_GETPEERUCRED) + ucred_t stack_ucred; + ucred_t *ucred = &stack_ucred; + + SYSGUARD(getpeerucred(sockfd, &ucred)); + *euid = ucred_geteuid(ucred); + *egid = ucred_getegid(ucred); + + return (*euid < 0 || *egid < 0) ? -1 : 0; +#elif defined(SO_PEERCRED) + struct ucred ucred; + socklen_t len = sizeof(ucred); + + SYSGUARD(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len)); + + *euid = ucred.uid; + *egid = ucred.gid; + + return 0; +#endif +} diff --git a/src/lib/spawn.c b/src/lib/spawn.c index b168f22..84e492f 100644 --- a/src/lib/spawn.c +++ b/src/lib/spawn.c @@ -22,31 +22,28 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include #include #include -#include "utils.h" #include "spawn.h" -typedef int (execfun)(const char*, char *const[], char *const[]); +typedef int (*execfun)(const char*, char *const[], char *const[]); -static -void child_exit(int pipe, int child_errno) +static void +child_exit(int pipefd, int child_errno) { - int noctets = write(pipe, &child_errno, sizeof(int)); + int noctets = write(pipefd, &child_errno, sizeof(int)); if (noctets == sizeof(int)) _exit(255); else _exit(254); } -static -int _lfp_spawn_apply_default_attributes(const lfp_spawnattr_t *attr) +static int +_lfp_spawn_apply_default_attributes(const lfp_spawnattr_t *attr) { if (attr == NULL || ! (attr->flags & LFP_SPAWN_SETSIGMASK)) { sigset_t set; @@ -56,28 +53,32 @@ int _lfp_spawn_apply_default_attributes(const lfp_spawnattr_t *attr) return 0; } -static -void handle_child(execfun *execfun, - const char *path, - char *const argv[], - char *const envp[], - const lfp_spawn_file_actions_t *file_actions, - const lfp_spawnattr_t *attr, - int pipes[2]) +static void +handle_child(execfun execfn, + const char *path, + char *const argv[], + char *const envp[], + const lfp_spawn_file_actions_t *file_actions, + const lfp_spawnattr_t *attr, + int pipes[2], + bool use_vfork) { - close(pipes[0]); - int child_errno; - if ((child_errno = _lfp_spawn_apply_default_attributes(attr)) != 0 || \ - (child_errno = lfp_spawn_apply_attributes(attr)) != 0 || \ - (child_errno = lfp_spawn_apply_file_actions(file_actions)) != 0) { - child_exit(pipes[1], child_errno); + if (_lfp_spawn_apply_default_attributes(attr) || + lfp_spawn_apply_attributes(attr) || + lfp_spawn_apply_file_actions(file_actions)) { + goto error; } - execfun(path, argv, envp); - child_exit(pipes[1], lfp_errno()); + execfn(path, argv, envp); + error: + if (use_vfork) + _exit(255); + else + child_exit(pipes[1], errno); } -static -int handle_parent(pid_t child_pid, int pipes[2]) +static int +handle_parent(pid_t child_pid, + int pipes[2]) { close(pipes[1]); int status, child_errno; @@ -99,54 +100,62 @@ int handle_parent(pid_t child_pid, int pipes[2]) } } -static -int _lfp_spawn(execfun *execfun, - pid_t *restrict pid, - const char *restrict path, - char *const argv[restrict], - char *const envp[restrict], - const lfp_spawn_file_actions_t *restrict file_actions, - const lfp_spawnattr_t *restrict attr) +static int +_lfp_spawn(execfun execfn, + pid_t *restrict pid, + const char *restrict path, + char *const argv[restrict], + char *const envp[restrict], + const lfp_spawn_file_actions_t *restrict file_actions, + const lfp_spawnattr_t *restrict attr) { int pipes[2]; + bool use_vfork = (attr && (attr->flags & LFP_SPAWN_USEVFORK)); + // Used for passing the error code from child to parent in case // some of the syscalls executed in the child fail - if (lfp_pipe(pipes, O_CLOEXEC) < 0) + if (!use_vfork && lfp_pipe(pipes, O_CLOEXEC) < 0) return -1; - *pid = fork(); + if(use_vfork) { + *pid = vfork(); + } else { + *pid = fork(); + } switch (*pid) { case -1: return -1; case 0: - handle_child(execfun, path, argv, envp, file_actions, attr, pipes); + handle_child(execfn, path, argv, envp, file_actions, attr, pipes, use_vfork); // Flow reaches this point only if child_exit() mysteriously fails SYSERR(EBUG); default: - return handle_parent(*pid, pipes); + return use_vfork ? 0 : handle_parent(*pid, pipes); } } -int lfp_spawn(pid_t *restrict pid, - const char *restrict path, - char *const argv[restrict], - char *const envp[restrict], - const lfp_spawn_file_actions_t *restrict file_actions, - const lfp_spawnattr_t *restrict attr) +DSO_PUBLIC int +lfp_spawn(pid_t *restrict pid, + const char *restrict path, + char *const argv[restrict], + char *const envp[restrict], + const lfp_spawn_file_actions_t *restrict file_actions, + const lfp_spawnattr_t *restrict attr) { SYSCHECK(EINVAL, pid == NULL); return _lfp_spawn(&lfp_execve, pid, path, argv, envp, file_actions, attr); } -int lfp_spawnp(pid_t *restrict pid, - const char *restrict file, - char *const argv[restrict], - char *const envp[restrict], - const lfp_spawn_file_actions_t *restrict file_actions, - const lfp_spawnattr_t *restrict attr) +DSO_PUBLIC int +lfp_spawnp(pid_t *restrict pid, + const char *restrict file, + char *const argv[restrict], + char *const envp[restrict], + const lfp_spawn_file_actions_t *restrict file_actions, + const lfp_spawnattr_t *restrict attr) { SYSCHECK(EINVAL, pid == NULL); diff --git a/src/lib/spawn_file_actions.c b/src/lib/spawn_file_actions.c index a5f8916..0aba790 100644 --- a/src/lib/spawn_file_actions.c +++ b/src/lib/spawn_file_actions.c @@ -22,18 +22,20 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include #include #include +#include #include -#include "utils.h" #include "spawn.h" +#include "bitset.h" + +/* not checking for OPEN_MAX, which might not be valid, on Linux */ +#define INVALID_FD(fd) ( fd < 0 ) typedef enum { LFP_SPAWN_FILE_ACTION_OPEN, @@ -50,44 +52,56 @@ typedef struct lfp_spawn_action { mode_t mode; } lfp_spawn_action; -int lfp_spawn_file_actions_init(lfp_spawn_file_actions_t *file_actions) +static inline int +_lfp_spawn_file_actions_init(lfp_spawn_file_actions_t *file_actions, size_t kfd_size) +{ + *file_actions = (lfp_spawn_file_actions_t) {0}; + file_actions->kfd_size = kfd_size; + return bitset_alloc(&file_actions->kfd, kfd_size); +} + +DSO_PUBLIC int +lfp_spawn_file_actions_init(lfp_spawn_file_actions_t *file_actions) { + struct rlimit limit; + SYSCHECK(EINVAL, file_actions == NULL); - file_actions->initialized = 0; - file_actions->allocated = 0; - file_actions->actions = NULL; - return 0; + SYSGUARD(lfp_getrlimit(RLIMIT_NOFILE, &limit)); + + return _lfp_spawn_file_actions_init(file_actions, limit.rlim_cur); } -static -void lfp_spawn_file_actions_free_paths(lfp_spawn_action *actions, int initialized) +static void +lfp_spawn_file_actions_free_paths(lfp_spawn_action *actions, int initialized) { for (int i = 0; i < initialized; i++) if (actions[i].type == LFP_SPAWN_FILE_ACTION_OPEN) free((void*)actions[i].path); } -int lfp_spawn_file_actions_destroy(lfp_spawn_file_actions_t *file_actions) +DSO_PUBLIC int +lfp_spawn_file_actions_destroy(lfp_spawn_file_actions_t *file_actions) { SYSCHECK(EINVAL, file_actions == NULL); - if (file_actions->actions) { - lfp_spawn_file_actions_free_paths(file_actions->actions, file_actions->initialized); + lfp_spawn_file_actions_free_paths(file_actions->actions, file_actions->initialized); + if (file_actions->actions) free(file_actions->actions); - } - // lfp_spawn_file_actions_init(file_actions); + if (file_actions->kfd) + free(file_actions->kfd); + *file_actions = (lfp_spawn_file_actions_t) {0}; return 0; } -static -lfp_spawn_action* lfp_spawn_file_actions_allocate(lfp_spawn_file_actions_t *file_actions) +static lfp_spawn_action* +lfp_spawn_file_actions_allocate(lfp_spawn_file_actions_t *file_actions) { - int index = file_actions->initialized++; + int init_index = file_actions->initialized++; int allocated = file_actions->allocated; lfp_spawn_action *actions = file_actions->actions; int new_allocated; lfp_spawn_action *new_actions; - if (index >= allocated) { + if (init_index >= allocated) { /* Note: this code assumes we run out of memory before we overflow. */ new_allocated = 4 + allocated * 3 / 2; new_actions = calloc(new_allocated, sizeof(lfp_spawn_action)); @@ -101,14 +115,15 @@ lfp_spawn_action* lfp_spawn_file_actions_allocate(lfp_spawn_file_actions_t *file actions = new_actions; file_actions->actions = actions; file_actions->allocated = new_allocated; - memset(actions+index, 0, (new_allocated - index) * sizeof(lfp_spawn_action)); + memset(actions + init_index, 0, (new_allocated - init_index) * sizeof(lfp_spawn_action)); } - return actions + index; + return actions + init_index; } -int lfp_spawn_file_actions_addopen(lfp_spawn_file_actions_t *file_actions, - int fd, const char *path, - uint64_t oflags, mode_t mode) +DSO_PUBLIC int +lfp_spawn_file_actions_addopen(lfp_spawn_file_actions_t *file_actions, + int fd, const char *path, + uint64_t oflags, mode_t mode) { SYSCHECK(EINVAL, file_actions == NULL); SYSCHECK(EBADF, INVALID_FD(fd)); @@ -118,15 +133,16 @@ int lfp_spawn_file_actions_addopen(lfp_spawn_file_actions_t *file_actions, action->type = LFP_SPAWN_FILE_ACTION_OPEN; action->fd = fd; - action->path = lfp_strndup(path, PATH_MAX); + action->path = strdup(path); action->flags = oflags; action->mode = mode; return 0; } -int lfp_spawn_file_actions_addclose(lfp_spawn_file_actions_t *file_actions, - int fd) +DSO_PUBLIC int +lfp_spawn_file_actions_addclose(lfp_spawn_file_actions_t *file_actions, + int fd) { SYSCHECK(EINVAL, file_actions == NULL); SYSCHECK(EBADF, INVALID_FD(fd)); @@ -140,8 +156,9 @@ int lfp_spawn_file_actions_addclose(lfp_spawn_file_actions_t *file_actions, return 0; } -int lfp_spawn_file_actions_adddup2(lfp_spawn_file_actions_t *file_actions, - int fd, int newfd) +DSO_PUBLIC int +lfp_spawn_file_actions_adddup2(lfp_spawn_file_actions_t *file_actions, + int fd, int newfd) { SYSCHECK(EINVAL, file_actions == NULL); SYSCHECK(EBADF, INVALID_FD(fd) || INVALID_FD(newfd)); @@ -156,20 +173,31 @@ int lfp_spawn_file_actions_adddup2(lfp_spawn_file_actions_t *file_actions, return 0; } -static -int lfp_spawn_apply_one_file_action(const lfp_spawn_action *action) +DSO_PUBLIC int +lfp_spawn_file_actions_addkeep(lfp_spawn_file_actions_t *file_actions, + int fd) +{ + file_actions->keep_descriptors = true; + return bitset_insert(file_actions->kfd, fd); +} + +static int +lfp_spawn_apply_one_file_action(const lfp_spawn_action *action) { int err, fd; switch (action->type) { case LFP_SPAWN_FILE_ACTION_OPEN: fd = lfp_open(action->path, action->flags, action->mode); - if (fd == -1) { return errno; } + if (fd == -1) { return lfp_errno(); } if (fd != action->fd) { - err = dup2(fd, action->fd); - if (err == -1) { return errno; } - err = close(fd); - if (err == -1) { return errno; } + int dup2_errno = GET_ERRNO(dup2(fd, action->fd)); + int close_errno = GET_ERRNO(close(fd)); + if (dup2_errno) { + return dup2_errno; + } else if (close_errno) { + return close_errno; + } } return 0; case LFP_SPAWN_FILE_ACTION_CLOSE: @@ -185,10 +213,27 @@ int lfp_spawn_apply_one_file_action(const lfp_spawn_action *action) } } -int lfp_spawn_apply_file_actions(const lfp_spawn_file_actions_t *file_actions) +static int +_lfp_spawn_close_descriptors(const lfp_spawn_file_actions_t *file_actions) +{ + for (int i = 0; i < file_actions->kfd_size; i++) + if (!bitset_contains(file_actions->kfd, i)) { + // Ignore EBADF + int ret = lfp_set_fd_cloexec(i, true); + if(ret < 0 && lfp_errno() != EBADF) + return -1; + } + return 0; +} + +int +lfp_spawn_apply_file_actions(const lfp_spawn_file_actions_t *file_actions) { if (file_actions == NULL) return 0; + if(file_actions->keep_descriptors) + _lfp_spawn_close_descriptors(file_actions); + lfp_spawn_action *action = file_actions->actions; int err; diff --git a/src/lib/spawnattr.c b/src/lib/spawnattr.c index 32c37b8..713fefb 100644 --- a/src/lib/spawnattr.c +++ b/src/lib/spawnattr.c @@ -22,13 +22,12 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include #include #include +#include #include #include @@ -36,7 +35,6 @@ #include #include -#include "utils.h" #include "spawn.h" #define LFP_SPAWN_ALLATTRS ( LFP_SPAWN_SETSIGMASK | \ @@ -47,9 +45,11 @@ LFP_SPAWN_SETGID | \ LFP_SPAWN_SETCWD | \ LFP_SPAWN_SETSID | \ - LFP_SPAWN_SETCTTY ) + LFP_SPAWN_SETCTTY | \ + LFP_SPAWN_USEVFORK ) -int lfp_spawnattr_init(lfp_spawnattr_t *attr) +DSO_PUBLIC int +lfp_spawnattr_init(lfp_spawnattr_t *attr) { SYSCHECK(EINVAL, attr == NULL); memset(attr, 0, sizeof(lfp_spawnattr_t)); @@ -57,7 +57,8 @@ int lfp_spawnattr_init(lfp_spawnattr_t *attr) return 0; } -int lfp_spawnattr_destroy(lfp_spawnattr_t *attr) +DSO_PUBLIC int +lfp_spawnattr_destroy(lfp_spawnattr_t *attr) { SYSCHECK(EINVAL, attr == NULL); if (attr->chdir_path) { @@ -71,28 +72,32 @@ int lfp_spawnattr_destroy(lfp_spawnattr_t *attr) return 0; } -int lfp_spawnattr_getflags(lfp_spawnattr_t *attr, uint32_t *flags) +DSO_PUBLIC int +lfp_spawnattr_getflags(lfp_spawnattr_t *attr, uint32_t *flags) { SYSCHECK(EINVAL, attr == NULL || flags == NULL); *flags = attr->flags; return 0; } -int lfp_spawnattr_setflags(lfp_spawnattr_t *attr, const uint32_t flags) +DSO_PUBLIC int +lfp_spawnattr_setflags(lfp_spawnattr_t *attr, const uint32_t flags) { SYSCHECK(EINVAL, attr == NULL || (flags & ~LFP_SPAWN_ALLATTRS) != 0); attr->flags = flags; return 0; } -int lfp_spawnattr_getsigmask(lfp_spawnattr_t *attr, sigset_t *sigmask) +DSO_PUBLIC int +lfp_spawnattr_getsigmask(lfp_spawnattr_t *attr, sigset_t *sigmask) { SYSCHECK(EINVAL, attr == NULL || sigmask == NULL); memcpy(sigmask, &attr->sigmask, sizeof(sigset_t)); return 0; } -int lfp_spawnattr_setsigmask(lfp_spawnattr_t *attr, const sigset_t *sigmask) +DSO_PUBLIC int +lfp_spawnattr_setsigmask(lfp_spawnattr_t *attr, const sigset_t *sigmask) { SYSCHECK(EINVAL, attr == NULL); attr->flags |= LFP_SPAWN_SETSIGMASK; @@ -100,14 +105,16 @@ int lfp_spawnattr_setsigmask(lfp_spawnattr_t *attr, const sigset_t *sigmask) return 0; } -int lfp_spawnattr_getsigdefault(lfp_spawnattr_t *attr, sigset_t *sigdefault) +DSO_PUBLIC int +lfp_spawnattr_getsigdefault(lfp_spawnattr_t *attr, sigset_t *sigdefault) { SYSCHECK(EINVAL, attr == NULL || sigdefault == NULL); memcpy(sigdefault, &attr->sigdefault, sizeof(sigset_t)); return 0; } -int lfp_spawnattr_setsigdefault(lfp_spawnattr_t *attr, const sigset_t *sigdefault) +DSO_PUBLIC int +lfp_spawnattr_setsigdefault(lfp_spawnattr_t *attr, const sigset_t *sigdefault) { SYSCHECK(EINVAL, attr == NULL || sigdefault == NULL); attr->flags |= LFP_SPAWN_SETSIGDEFAULT; @@ -115,14 +122,16 @@ int lfp_spawnattr_setsigdefault(lfp_spawnattr_t *attr, const sigset_t *sigdefaul return 0; } -int lfp_spawnattr_getpgroup(lfp_spawnattr_t *attr, pid_t *pgroup) +DSO_PUBLIC int +lfp_spawnattr_getpgroup(lfp_spawnattr_t *attr, pid_t *pgroup) { SYSCHECK(EINVAL, attr == NULL || pgroup == NULL); *pgroup = attr->pgroup; return 0; } -int lfp_spawnattr_setpgroup(lfp_spawnattr_t *attr, const pid_t pgroup) +DSO_PUBLIC int +lfp_spawnattr_setpgroup(lfp_spawnattr_t *attr, const pid_t pgroup) { SYSCHECK(EINVAL, attr == NULL); attr->flags |= LFP_SPAWN_SETPGROUP; @@ -130,59 +139,64 @@ int lfp_spawnattr_setpgroup(lfp_spawnattr_t *attr, const pid_t pgroup) return 0; } -int lfp_spawnattr_setsid(lfp_spawnattr_t *attr) +DSO_PUBLIC int +lfp_spawnattr_setsid(lfp_spawnattr_t *attr) { SYSCHECK(EINVAL, attr == NULL); attr->flags |= LFP_SPAWN_SETSID; return 0; } -int lfp_spawnattr_getctty(lfp_spawnattr_t *attr, char **path) +DSO_PUBLIC int +lfp_spawnattr_getctty(lfp_spawnattr_t *attr, char **path) { SYSCHECK(EINVAL, attr == NULL || path == NULL); *path = strdup(attr->pts_path); return 0; } -int lfp_spawnattr_setctty(lfp_spawnattr_t *attr, const char *path) +DSO_PUBLIC int +lfp_spawnattr_setctty(lfp_spawnattr_t *attr, const char *path) { SYSCHECK(EINVAL, attr == NULL || path == NULL); - attr->flags |= LFP_SPAWN_SETCTTY; + attr->flags |= LFP_SPAWN_SETCTTY | LFP_SPAWN_SETSID; if (attr->pts_path) { free(attr->pts_path); } - attr->pts_path = lfp_strndup(path, PATH_MAX); - attr->pts_path[PATH_MAX] = 0; + attr->pts_path = strdup(path); return 0; } -int lfp_spawnattr_getcwd(lfp_spawnattr_t *attr, char **path) +DSO_PUBLIC int +lfp_spawnattr_getcwd(lfp_spawnattr_t *attr, char **path) { SYSCHECK(EINVAL, attr == NULL || path == NULL); *path = strdup(attr->chdir_path); return 0; } -int lfp_spawnattr_setcwd(lfp_spawnattr_t *attr, const char *path) +DSO_PUBLIC int +lfp_spawnattr_setcwd(lfp_spawnattr_t *attr, const char *path) { SYSCHECK(EINVAL, attr == NULL || path == NULL); attr->flags |= LFP_SPAWN_SETCWD; if (attr->chdir_path) { free(attr->chdir_path); } - attr->chdir_path = lfp_strndup(path, PATH_MAX); - attr->chdir_path[PATH_MAX] = 0; + attr->chdir_path = strdup(path); return 0; } -int lfp_spawnattr_getuid(lfp_spawnattr_t *attr, uid_t *uid) +DSO_PUBLIC int +lfp_spawnattr_getuid(lfp_spawnattr_t *attr, uid_t *uid) { SYSCHECK(EINVAL, attr == NULL || uid == NULL); *uid = attr->uid; return 0; } -int lfp_spawnattr_setuid(lfp_spawnattr_t *attr, const uid_t uid) +DSO_PUBLIC int +lfp_spawnattr_setuid(lfp_spawnattr_t *attr, const uid_t uid) { SYSCHECK(EINVAL, attr == NULL); attr->flags |= LFP_SPAWN_SETUID; @@ -190,21 +204,22 @@ int lfp_spawnattr_setuid(lfp_spawnattr_t *attr, const uid_t uid) return 0; } -int lfp_spawnattr_getgid(lfp_spawnattr_t *attr, gid_t *gid) +DSO_PUBLIC int +lfp_spawnattr_getgid(lfp_spawnattr_t *attr, gid_t *gid) { SYSCHECK(EINVAL, attr == NULL || gid == NULL); *gid = attr->gid; return 0; } -int lfp_spawnattr_setgid(lfp_spawnattr_t *attr, const gid_t gid) +DSO_PUBLIC int +lfp_spawnattr_setgid(lfp_spawnattr_t *attr, const gid_t gid) { SYSCHECK(EINVAL, attr == NULL); attr->flags |= LFP_SPAWN_SETGID; attr->gid = gid; return 0; } - int lfp_spawn_apply_attributes(const lfp_spawnattr_t *attr) @@ -253,20 +268,12 @@ int lfp_spawn_apply_attributes(const lfp_spawnattr_t *attr) } if (attr->flags & LFP_SPAWN_SETCTTY) { - int ttyfd = lfp_open(attr->pts_path, O_RDWR | O_NOCTTY); - if (ttyfd < 0) { -#if !defined(NDEBUG) - perror("LFP_SPAWN_APPLY_ATTR:SETCTTY:lfp_open"); -#endif - goto error_return; - } else { - if (ioctl(ttyfd, TIOCSCTTY) < 0) { + if (lfp_tty_attach(attr->pts_path) < 0) { #if !defined(NDEBUG) - perror("LFP_SPAWN_APPLY_ATTR:SETCTTY:ioctl"); + perror("LFP_SPAWN_APPLY_ATTR:SETCTTY:lfp_tty_attach"); #endif - goto error_return; - } - } + goto error_return; + } } if (attr->flags & LFP_SPAWN_SETCWD) diff --git a/src/lib/stat.c b/src/lib/stat.c index 4565b19..7c5d799 100644 --- a/src/lib/stat.c +++ b/src/lib/stat.c @@ -22,27 +22,29 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include -int lfp_stat(const char *path, struct stat *buf) +DSO_PUBLIC int +lfp_stat(const char *path, struct stat *buf) { return stat(path, buf); } -int lfp_fstat(int fd, struct stat *buf) +DSO_PUBLIC int +lfp_fstat(int fd, struct stat *buf) { return fstat(fd, buf); } -int lfp_lstat(const char *path, struct stat *buf) +DSO_PUBLIC int +lfp_lstat(const char *path, struct stat *buf) { return lstat(path, buf); } -int lfp_is_fd_open(int fd) +DSO_PUBLIC int +lfp_is_fd_open(int fd) { struct stat buf; int ret = fstat(fd, &buf); @@ -57,37 +59,44 @@ int lfp_is_fd_open(int fd) } } -bool lfp_isreg(mode_t mode) +DSO_PUBLIC bool +lfp_isreg(mode_t mode) { return (bool) S_ISREG(mode); } -bool lfp_isdir(mode_t mode) +DSO_PUBLIC bool +lfp_isdir(mode_t mode) { return (bool) S_ISDIR(mode); } -bool lfp_ischr(mode_t mode) +DSO_PUBLIC bool +lfp_ischr(mode_t mode) { return (bool) S_ISCHR(mode); } -bool lfp_isblk(mode_t mode) +DSO_PUBLIC bool +lfp_isblk(mode_t mode) { return (bool) S_ISBLK(mode); } -bool lfp_isfifo(mode_t mode) +DSO_PUBLIC bool +lfp_isfifo(mode_t mode) { return (bool) S_ISFIFO(mode); } -bool lfp_islnk(mode_t mode) +DSO_PUBLIC bool +lfp_islnk(mode_t mode) { return (bool) S_ISLNK(mode); } -bool lfp_issock(mode_t mode) +DSO_PUBLIC bool +lfp_issock(mode_t mode) { return (bool) S_ISSOCK(mode); } diff --git a/src/lib/stdlib.c b/src/lib/stdlib.c index 614cb60..5d3e452 100644 --- a/src/lib/stdlib.c +++ b/src/lib/stdlib.c @@ -22,35 +22,123 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include +#include +#include +#include +#include +#include +#include +#include "aux/inlines.h" #include #include #include #include +#include -int lfp_mkstemp(char *template) +static char* +_valid_template_p(char *s, size_t len) { - return mkstemp(template); + size_t start_offset = len - 6; + for (size_t off = start_offset; off < len; off++) { + if (s[off] != 'X') return NULL; + } + return s + start_offset; } -static -char* _lfp_getenv(const char *name, unsigned short len, char *const envp[]) +static int +_randomize_template(uint32_t *seed, char *s) { - if (envp == NULL) return NULL; + uint32_t internalSeed = *seed; + int retval = 0; + + char random_value[6]; + memcpy(random_value, &internalSeed, 4); + internalSeed = _xorshift(internalSeed); + memcpy(random_value + 4, &internalSeed, 2); + + char bag[] = "0123456789QWERTYUIOPASDFGHJKLZXCVBNM"; + for (unsigned i = 0; i < 6; i++) { + s[i] = bag[random_value[i]%(sizeof(bag)-1)]; + //random_value /= (sizeof(bag)-1); + } + + *seed = internalSeed; + return retval; +} + +DSO_PUBLIC int +lfp_mkstemp(char *template) +{ + return lfp_mkostemp(template, O_RDWR | O_CLOEXEC); +} + +static inline uint32_t +_pid_seed(void) +{ + /* Try to pick a seed different from everyone else */ + struct timespec ts; + SYSGUARD(lfp_clock_gettime(CLOCK_REALTIME, &ts)); + return (ts.tv_nsec << 2) + getpid() + ts.tv_sec; +} + +DSO_PUBLIC int +lfp_mkostemp(char *template, uint64_t flags) +{ + static uint32_t seed = 0; + + size_t len = strlen(template); + SYSCHECK(EINVAL, len < 6 || template[0] != '/'); + + char *x_start = _valid_template_p(template, len); + SYSCHECK(EINVAL, x_start == NULL); + + for (int i = 0; i < 1024; i++) { + SYSGUARD(_randomize_template(&seed, x_start)); + int fd = lfp_open(template, O_EXCL | O_CREAT | flags, S_IRUSR | S_IWUSR); + if (fd >= 0) { + return fd; + } else { + switch (lfp_errno()) { + case EEXIST: + /* If we hit here, we may be colliding with + * a forked process, so increment the seed */ + if(i == 0) { + seed = _pid_seed(); + } + //seed+=1; + continue; + default: + return -1; + } + } + } + SYSERR(EEXIST); +} + +static bool +valid_path_p(const char *path, size_t len) +{ + return path[len] == '/' && path[len+1] != '\0' ? true : false; +} + +static char* +_lfp_getenv(const char *name, size_t len, char *const envp[]) +{ + if (envp == NULL || *envp == NULL) + return NULL; do { - if (strlen(*envp) > len && strncmp(name, *envp, len) == 0) - return (char*)*envp+len; + if (strncmp(name, *envp, len) == 0 && valid_path_p(*envp, len)) + return *envp+len; } while(*(++envp) != NULL); return NULL; } // FIXME: add autoconf check that confstr(_CS_PATH) returns sane values -static -char* _lfp_default_path(void) +static char* +_lfp_default_path(void) { size_t default_path_size = confstr(_CS_PATH, NULL, 0); char *default_path = malloc(default_path_size); @@ -58,9 +146,11 @@ char* _lfp_default_path(void) return default_path; } -char* lfp_getpath(char *const envp[]) +DSO_PUBLIC char* +lfp_getpath(char *const envp[]) { - char *envpath = _lfp_getenv("PATH=", sizeof("PATH=")-1, envp); + char *envpath = _lfp_getenv("PATH=", sizeof("PATH=") - 1, + envp ? envp : lfp_get_environ()); if (envpath != NULL) { return strdup(envpath); } else { @@ -68,18 +158,19 @@ char* lfp_getpath(char *const envp[]) } } -static pthread_mutex_t ptsname_mutex = PTHREAD_MUTEX_INITIALIZER; - -char *lfp_ptsname(int masterfd) +DSO_PUBLIC int +lfp_ptsname(int masterfd, char *buf, size_t buflen) { - pthread_mutex_lock(&ptsname_mutex); - - char *_name = ptsname(masterfd); - if (_name != NULL) { - _name = lfp_strndup(_name, PATH_MAX); +#if defined(HAVE_PTSNAME_R) + return ptsname_r(masterfd, buf, buflen); +#elif defined(HAVE_PTSNAME) + char *pts = ptsname(masterfd); + size_t ptslen = lfp_strnlen(pts, buflen); + if (ptslen >= buflen) { + SYSERR(EINVAL); + } else { + memcpy(buf, pts, ptslen); + return 0; } - - pthread_mutex_unlock(&ptsname_mutex); - - return _name; +#endif } diff --git a/src/lib/strerror.c b/src/lib/strerror.c new file mode 100644 index 0000000..bb73148 --- /dev/null +++ b/src/lib/strerror.c @@ -0,0 +1,42 @@ +/*******************************************************************************/ +/* Permission is hereby granted, free of charge, to any person or organization */ +/* obtaining a copy of the software and accompanying documentation covered by */ +/* this license (the "Software") to use, reproduce, display, distribute, */ +/* execute, and transmit the Software, and to prepare derivative works of the */ +/* Software, and to permit third-parties to whom the Software is furnished to */ +/* do so, all subject to the following: */ +/* */ +/* The copyright notices in the Software and this entire statement, including */ +/* the above license grant, this restriction and the following disclaimer, */ +/* must be included in all copies of the Software, in whole or in part, and */ +/* all derivative works of the Software, unless such copies or derivative */ +/* works are solely in the form of machine-executable object code generated by */ +/* a source language processor. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT */ +/* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE */ +/* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, */ +/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */ +/* DEALINGS IN THE SOFTWARE. */ +/*******************************************************************************/ + +#include + +#include + +#if defined(HAVE___XPG_STRERROR_R) +int __xpg_strerror_r (int errnum, char *buf, size_t buflen); +#endif + +DSO_PUBLIC int +lfp_strerror (int errnum, char *buf, size_t buflen) +{ + SYSCHECK(EINVAL, buf == NULL); +#if defined(HAVE___XPG_STRERROR_R) + return __xpg_strerror_r(errnum, buf, buflen); +#else + return strerror_r(errnum, buf, buflen); +#endif // HAVE___XPG_STRERROR_R +} diff --git a/src/lib/string.c b/src/lib/string.c index 4c18c68..8c8ca4e 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -22,29 +22,17 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include -#include "utils.h" - -#if defined(HAVE___XPG_STRERROR_R) -int __xpg_strerror_r (int errnum, char *buf, size_t buflen); -#endif +#include +#include -int lfp_strerror (int errnum, char *buf, size_t buflen) -{ - SYSCHECK(EINVAL, buf == NULL); -#if defined(HAVE___XPG_STRERROR_R) - return __xpg_strerror_r(errnum, buf, buflen); -#else - return strerror_r(errnum, buf, buflen); -#endif // HAVE___XPG_STRERROR_R -} +static int64_t compute_multiplier(enum lfp_memsize_measure_unit unit); -size_t lfp_strnlen(const char *s, size_t maxlen) +DSO_PUBLIC size_t +lfp_strnlen(const char *s, size_t maxlen) { #if defined(HAVE_STRNLEN) return strnlen(s, maxlen); @@ -58,7 +46,8 @@ size_t lfp_strnlen(const char *s, size_t maxlen) #endif } -char *lfp_strndup(const char *s, size_t maxlen) +DSO_PUBLIC char* +lfp_strndup(const char *s, size_t maxlen) { #if defined(HAVE_STRNDUP) return strndup(s, maxlen); @@ -68,13 +57,93 @@ char *lfp_strndup(const char *s, size_t maxlen) } else { size_t len = lfp_strnlen(s, maxlen); char *newstr = malloc(len + 1); - if (newstr == NULL) { - return NULL; - } else { + if (newstr != NULL) { memcpy(newstr, s, len); newstr[len] = '\0'; - return newstr; } + return newstr; } #endif } + +static inline int64_t +compute_multiplier(enum lfp_memsize_measure_unit unit) +{ + switch(unit) { + case LFP_OCTETS: return 1; + case LFP_KB: return 1000LL; + case LFP_KIB: return 1024LL; + case LFP_MB: return 1000LL*1000LL; + case LFP_MIB: return 1024LL*1024LL; + case LFP_GB: return 1000LL*1000LL*1000LL; + case LFP_GIB: return 1024LL*1024LL*1024LL; + case LFP_TB: return 1000LL*1000LL*1000LL*1000LL; + case LFP_TIB: return 1024LL*1024LL*1024LL*1024LL; + case LFP_PB: return 1000LL*1000LL*1000LL*1000LL*1000LL; + case LFP_PIB: return 1024LL*1024LL*1024LL*1024LL*1024LL; + case LFP_EB: return 1000LL*1000LL*1000LL*1000LL*1000LL*1000LL; + case LFP_EIB: return 1024LL*1024LL*1024LL*1024LL*1024LL*1024LL; + default: SYSERR(EINVAL); + } +} + +DSO_PUBLIC int64_t +lfp_parse_memsize(const char *s, enum lfp_memsize_measure_unit default_unit) +{ + int64_t default_multiplier, multiplier, amount; + + SYSCHECK(EINVAL, s == NULL || *s == '\0'); + SYSGUARD(default_multiplier = compute_multiplier(default_unit)); + + char *endptr = NULL; + lfp_set_errno(0); + SYSGUARD(amount = strtoll(s, &endptr, 10)); + SYSCHECK(ERANGE, amount < 0); + + if (amount == 0) { + return 0; + } else if (*endptr) { + if (strcasecmp(endptr, "KB") == 0) { + multiplier = 1000LL; + } else if (strcasecmp(endptr, "K") == 0 || + strcasecmp(endptr, "KiB") == 0) { + multiplier = 1024LL; + } else if (strcasecmp(endptr, "MB") == 0) { + multiplier = 1000LL*1000LL; + } else if (strcasecmp(endptr, "M") == 0 || + strcasecmp(endptr, "MiB") == 0) { + multiplier = 1024LL*1024LL; + } else if (strcasecmp(endptr, "GB") == 0) { + multiplier = 1000LL*1000LL*1000LL; + } else if (strcasecmp(endptr, "G") == 0 || + strcasecmp(endptr, "GiB") == 0) { + multiplier = 1024LL*1024LL*1024LL; + } else if (strcasecmp(endptr, "TB") == 0) { + multiplier = 1000LL*1000LL*1000LL*1000LL; + } else if (strcasecmp(endptr, "T") == 0 || + strcasecmp(endptr, "TiB") == 0) { + multiplier = 1024LL*1024LL*1024LL*1024LL; + } else if (strcasecmp(endptr, "PB") == 0) { + multiplier = 1000LL*1000LL*1000LL*1000LL*1000LL; + } else if (strcasecmp(endptr, "P") == 0 || + strcasecmp(endptr, "PiB") == 0) { + multiplier = 1024LL*1024LL*1024LL*1024LL*1024LL; + } else if (strcasecmp(endptr, "EB") == 0) { + multiplier = 1000LL*1000LL*1000LL*1000LL*1000LL*1000LL; + } else if (strcasecmp(endptr, "E") == 0 || + strcasecmp(endptr, "EiB") == 0) { + multiplier = 1024LL*1024LL*1024LL*1024LL*1024LL*1024LL; + } else { + SYSERR(EINVAL); + } + } else { + multiplier = default_multiplier; + } + + // Check for overflow + if (amount > (INT64_MAX / multiplier)) { + SYSERR(ERANGE); + } else { + return amount * multiplier; + } +} diff --git a/src/lib/syslog.c b/src/lib/syslog.c index 91ef21d..aeb8fc5 100644 --- a/src/lib/syslog.c +++ b/src/lib/syslog.c @@ -22,24 +22,20 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include #include -#include "utils.h" - static pthread_mutex_t syslog_mutex = PTHREAD_MUTEX_INITIALIZER; static char *syslog_ident = NULL; #define SYSLOG_IDENT_SIZE 1024 -static -void _lfp_closelog() +static void +_lfp_closelog(void) { closelog(); if (syslog_ident) { @@ -48,8 +44,8 @@ void _lfp_closelog() } } -static -void copy_syslog_ident(const char *ident) +static void +copy_syslog_ident(const char *ident) { if (ident) { syslog_ident = malloc(SYSLOG_IDENT_SIZE); @@ -58,7 +54,8 @@ void copy_syslog_ident(const char *ident) } } -void lfp_openlog(const char *ident, int options, int facility) +DSO_PUBLIC void +lfp_openlog(const char *ident, int options, int facility) { pthread_mutex_lock(&syslog_mutex); _lfp_closelog(); @@ -67,7 +64,8 @@ void lfp_openlog(const char *ident, int options, int facility) pthread_mutex_unlock(&syslog_mutex); } -void lfp_syslog(int priority, const char *msg, ...) +DSO_PUBLIC void +lfp_syslog(int priority, const char *msg, ...) { va_list args; va_start(args, msg); @@ -75,29 +73,34 @@ void lfp_syslog(int priority, const char *msg, ...) va_end(args); } -void lfp_vsyslog(int priority, const char *msg, va_list args) +DSO_PUBLIC void +lfp_vsyslog(int priority, const char *msg, va_list args) { vsyslog(priority, msg, args); } -void lfp_closelog(void) +DSO_PUBLIC void +lfp_closelog(void) { pthread_mutex_lock(&syslog_mutex); _lfp_closelog(); pthread_mutex_unlock(&syslog_mutex); } -int lfp_setlogmask(int maskpri) +DSO_PUBLIC int +lfp_setlogmask(int maskpri) { return setlogmask(maskpri); } -int lfp_log_mask(int priority) +DSO_PUBLIC int +lfp_log_mask(int priority) { return LOG_MASK(priority); } -int lfp_log_upto(int priority) +DSO_PUBLIC int +lfp_log_upto(int priority) { return LOG_UPTO(priority); } diff --git a/src/lib/time.c b/src/lib/time.c index ed73eb3..9b6e1cf 100644 --- a/src/lib/time.c +++ b/src/lib/time.c @@ -22,8 +22,6 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include @@ -33,93 +31,152 @@ # include #endif -#include "utils.h" +#include "aux/inlines.h" + +#define MACH_SYSERR(errcode) \ + do { errno = errcode; ret = -1; goto cleanup; } while(0) + +#define MACH_SYSCHECK(errcode, expr) \ + do { if(expr) MACH_SYSERR(errcode); } while(0) -int lfp_clock_getres(lfp_clockid_t clk_id, struct timespec *res) +/*******************/ +/* clock_getres() */ +/*******************/ + +#if defined(__APPLE__) && !HAVE_CLOCK_GETTIME +static +int _lfp_clock_getres(clock_id_t clk_id, struct timespec *tp) { -#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - return clock_getres((clockid_t)clk_id & 0xFFFFFFFF, res); -#else + int ret = 0; + kern_return_t kr; + clock_serv_t clk_serv; + + host_t host_self = mach_host_self(); + kr = host_get_clock_service(host_self, clk_id, &clk_serv); + MACH_SYSCHECK(EINVAL, kr != KERN_SUCCESS); + + natural_t attributes[4]; + mach_msg_type_number_t count = sizeof(attributes) / sizeof(natural_t); + kr = clock_get_attributes(clk_serv, CLOCK_GET_TIME_RES, (clock_attr_t)attributes, &count); + MACH_SYSCHECK(EINVAL, kr != KERN_SUCCESS); + + tp->tv_sec = attributes[0] / 10^9; + tp->tv_nsec = attributes[0] % 10^9; + + cleanup: + mach_port_deallocate(mach_task_self(), host_self); + mach_port_deallocate(mach_task_self(), clk_serv); + + return ret; +} +#endif + +DSO_PUBLIC int +lfp_clock_getres(clockid_t clk_id, struct timespec *res) +{ +#if HAVE_CLOCK_GETTIME + return clock_getres(clk_id, res); +#elif defined(__APPLE__) + SYSCHECK(EINVAL, res == NULL); + switch (clk_id) { case CLOCK_REALTIME: + return _lfp_clock_getres(CALENDAR_CLOCK, res); case CLOCK_MONOTONIC: - // FIXME: it's probably safe to assume that it's 10ms - // or lower(OS scheduler running at 100Hz or more) - res->tv_sec = 0; - res->tv_nsec = 10^7; - return 0; + return _lfp_clock_getres(REALTIME_CLOCK, res); default: SYSERR(EINVAL); } +#else +# error "BUG! This point should not be reached" #endif } + -#if !defined(_POSIX_TIMERS) || _POSIX_TIMERS < 0 -static inline -int _lfp_clock_gettime_realtime(struct timespec *tp) -{ - struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) { - return -1; - } else { - _lfp_timeval_to_timespec(&tv, tp); - return 0; - } -} -#endif +/*******************/ +/* clock_gettime() */ +/*******************/ -#if !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 +#if defined(__APPLE__) && !HAVE_CLOCK_GETTIME static inline -int _lfp_clock_gettime_monotonic(struct timespec *tp) +int _lfp_clock_gettime(clock_id_t clk_id, struct timespec *tp) { -# if defined(__APPLE__) + int ret = 0; + kern_return_t kr; clock_serv_t clk_serv; mach_timespec_t mtp; - _lfp_timespec_to_mach_timespec_t(tp, &mtp); - SYSGUARD(host_get_clock_service(mach_host_self(), 0, &clk_serv)); - SYSGUARD(clock_get_time(clk_serv, &mtp)); - return 0; -# else - SYSERR(EINVAL); -# endif + host_t host_self = mach_host_self(); + kr = host_get_clock_service(host_self, clk_id, &clk_serv); + MACH_SYSCHECK(EINVAL, kr != KERN_SUCCESS); + + kr = clock_get_time(clk_serv, &mtp); + MACH_SYSCHECK(EINVAL, kr != KERN_SUCCESS); + _lfp_mach_timespec_t_to_timespec(&mtp, tp); + + cleanup: + mach_port_deallocate(mach_task_self(), host_self); + mach_port_deallocate(mach_task_self(), clk_serv); + + return ret; } #endif -int lfp_clock_gettime(lfp_clockid_t clk_id, struct timespec *tp) +DSO_PUBLIC int +lfp_clock_gettime(clockid_t clk_id, struct timespec *tp) { -#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - return clock_gettime((clockid_t)clk_id & 0xFFFFFFFF, tp); -#else +#if HAVE_CLOCK_GETTIME + return clock_gettime(clk_id, tp); +#elif defined(__APPLE__) + SYSCHECK(EINVAL, tp == NULL); + switch (clk_id) { case CLOCK_REALTIME: - return _lfp_clock_gettime_realtime(tp); + return _lfp_clock_gettime(CALENDAR_CLOCK, tp); case CLOCK_MONOTONIC: - return _lfp_clock_gettime_monotonic(tp); + return _lfp_clock_gettime(REALTIME_CLOCK, tp); default: SYSERR(EINVAL); } +#else +# error "BUG! This point should not be reached" #endif } + -int lfp_clock_settime(lfp_clockid_t clk_id, struct timespec *tp) +/*******************/ +/* clock_settime() */ +/*******************/ + +#if defined(__APPLE__) && !HAVE_CLOCK_GETTIME +static inline +int _lfp_clock_settime_realtime(struct timespec *tp) { -#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - return clock_settime((clockid_t)clk_id & 0xFFFFFFFF, tp); -#else - int ret; struct timeval tv; _lfp_timespec_to_timeval(tp, &tv); + SYSGUARD(settimeofday(&tv, NULL)); + return 0; +} +#endif + +DSO_PUBLIC int +lfp_clock_settime(clockid_t clk_id, struct timespec *tp) +{ +#if HAVE_CLOCK_GETTIME + return clock_settime(clk_id, tp); +#elif defined(__APPLE__) + SYSCHECK(EINVAL, tp == NULL); + switch (clk_id) { case CLOCK_REALTIME: - ret = settimeofday(&tv, NULL); - if (ret < 0) { return -1; } - return 0; + return _lfp_clock_settime_realtime(tp); case CLOCK_MONOTONIC: SYSERR(EPERM); default: SYSERR(EINVAL); } +#else +# error "BUG! This point should not be reached" #endif } diff --git a/src/lib/unistd.c b/src/lib/unistd.c index 5e37edf..4bed0c6 100644 --- a/src/lib/unistd.c +++ b/src/lib/unistd.c @@ -22,27 +22,103 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include #include #include #include #include +#if !defined(HAVE_GETPEEREID) +# if defined(HAVE_UCRED_H) +# include +# else +# include +# endif +#endif + +#if defined(__APPLE__) +# include +#else +extern char** environ; +#endif + #include #include -#include "utils.h" +DSO_PUBLIC char** +lfp_get_environ(void) +{ +#if defined(__APPLE__) + return *_NSGetEnviron(); +#else + return environ; +#endif +} + +DSO_PUBLIC int +lfp_set_environ(char **newenv) +{ + if (lfp_clearenv() < 0) { + return -1; + } else if (newenv != NULL) { + for(char **var = newenv; *var != NULL; var++) { + putenv(*var); + } + } + return 0; +} -off_t lfp_lseek(int fd, off_t offset, int whence) +#if !defined(HAVE_CLEARENV) +static void +_lfp_reset_environ(void) +{ +# if defined(__APPLE__) + char ***envptr = _NSGetEnviron(); + *envptr = NULL; +# else + environ = NULL; +# endif +} +#endif + +DSO_PUBLIC int +lfp_clearenv(void) +{ +#if defined(HAVE_CLEARENV) + return clearenv(); +#else + char **env = lfp_get_environ(); + if (env == NULL) return 0; + + for(char **var = env; *var != NULL; var++) { + char *tmp = strdup(*var); + char *eql = strchr(tmp, '='); + if (eql == NULL) { + free(tmp); + return -1; + } else { + eql = '\0'; + unsetenv(eql); + free(tmp); + } + } + + _lfp_reset_environ(); + return 0; +#endif +} + + +DSO_PUBLIC off_t +lfp_lseek(int fd, off_t offset, int whence) { return lseek(fd, offset, whence); } -int lfp_pipe (int pipefd[2], uint64_t flags) +DSO_PUBLIC int +lfp_pipe (int pipefd[2], uint64_t flags) { #if defined(HAVE_PIPE2) // We assume that if pipe2() is defined then O_CLOEXEC too @@ -76,31 +152,36 @@ int lfp_pipe (int pipefd[2], uint64_t flags) -ssize_t lfp_pread(int fd, void *buf, size_t count, off_t offset) +DSO_PUBLIC ssize_t +lfp_pread(int fd, void *buf, size_t count, off_t offset) { return pread(fd, buf, count, offset); } -ssize_t lfp_pwrite(int fd, const void *buf, size_t count, off_t offset) +DSO_PUBLIC ssize_t +lfp_pwrite(int fd, const void *buf, size_t count, off_t offset) { return pwrite(fd, buf, count, offset); } -int lfp_truncate(const char *path, off_t length) +DSO_PUBLIC int +lfp_truncate(const char *path, off_t length) { return truncate(path, length); } -int lfp_ftruncate(int fd, off_t length) +DSO_PUBLIC int +lfp_ftruncate(int fd, off_t length) { return ftruncate(fd, length); } -int lfp_execve(const char *path, char *const argv[], char *const envp[]) +DSO_PUBLIC int +lfp_execve(const char *path, char *const argv[], char *const envp[]) { SYSCHECK(EINVAL, path == NULL); SYSCHECK(ENOENT, path[0] == '\0'); @@ -108,7 +189,8 @@ int lfp_execve(const char *path, char *const argv[], char *const envp[]) return execve(path, argv, envp); } -int lfp_execvpe(const char *file, char *const argv[], char *const envp[]) +DSO_PUBLIC int +lfp_execvpe(const char *file, char *const argv[], char *const envp[]) { SYSCHECK(EINVAL, file == NULL); SYSCHECK(ENOENT, file[0] == '\0'); @@ -116,28 +198,31 @@ int lfp_execvpe(const char *file, char *const argv[], char *const envp[]) if (strchr(file, '/')) return execve(file, argv, envp); - size_t name_max = (size_t) pathconf(file, _PC_NAME_MAX); - size_t filelen = lfp_strnlen(file, name_max); - SYSCHECK(ENAMETOOLONG, filelen >= name_max); + size_t filelen = strlen(file); - char path[PATH_MAX], *searchpath=NULL, *tmpath=NULL, *bindir=NULL; + char path[PATH_MAX]; + char *searchpath, *tmpath, *bindir, *saveptr = NULL; tmpath = searchpath = lfp_getpath(envp); - while ((bindir = strsep(&tmpath, ":")) != NULL) + while ((bindir = strtok_r(tmpath, ":", &saveptr)) != NULL) { + tmpath = NULL; if ( bindir[0] != '\0' ) { size_t dirlen = lfp_strnlen(bindir, PATH_MAX); - // directory + / + file + // directory + '/' + file size_t pathlen = dirlen + 1 + filelen; // if pathlen == PATH_MAX there's no room for the final \0 - SYSCHECK(ENAMETOOLONG, pathlen >= PATH_MAX); + if (pathlen >= PATH_MAX) { + errno = ENAMETOOLONG; + break; + } snprintf(path, PATH_MAX, "%s/%s", bindir, file); path[pathlen] = '\0'; - lfp_execve(path, argv, envp); - if ( errno == E2BIG || errno == ENOEXEC || - errno == ENOMEM || errno == ETXTBSY ) + execve(path, argv, envp); + if ( errno == E2BIG || errno == ENOMEM ) break; } + } free(searchpath); diff --git a/src/lib/wait.c b/src/lib/wait.c index 87feddc..0958dea 100644 --- a/src/lib/wait.c +++ b/src/lib/wait.c @@ -22,31 +22,34 @@ /* DEALINGS IN THE SOFTWARE. */ /*******************************************************************************/ -#include - #include -bool lfp_wifexited (int status) +DSO_PUBLIC bool +lfp_wifexited (int status) { return WIFEXITED(status); } -int lfp_wexitstatus (int status) +DSO_PUBLIC int +lfp_wexitstatus (int status) { return WEXITSTATUS(status); } -bool lfp_wifsignaled (int status) +DSO_PUBLIC bool +lfp_wifsignaled (int status) { return WIFSIGNALED(status); } -int lfp_wtermsig (int status) +DSO_PUBLIC int +lfp_wtermsig (int status) { return WTERMSIG(status); } -bool lfp_wcoredump (int status) +DSO_PUBLIC bool +lfp_wcoredump (int status) { #ifdef WCOREDUMP return WCOREDUMP(status); @@ -55,17 +58,24 @@ bool lfp_wcoredump (int status) #endif } -bool lfp_wifstopped (int status) +DSO_PUBLIC bool +lfp_wifstopped (int status) { return WIFSTOPPED(status); } -int lfp_wstopsig (int status) +DSO_PUBLIC int +lfp_wstopsig (int status) { return WSTOPSIG(status); } -bool lfp_wifcontinued (int status) +DSO_PUBLIC bool +lfp_wifcontinued (int status) { +#ifdef WIFCONTINUED return WIFCONTINUED(status); +#else + return false; +#endif } diff --git a/src/libfixposix.libtool b/src/libfixposix.libtool new file mode 100644 index 0000000..214e29a --- /dev/null +++ b/src/libfixposix.libtool @@ -0,0 +1,5 @@ +# Makes sure that the library is properly re-linked +# when the version changes +# +# CURRENT:REVISION:AGE +Version: 5:0:2 diff --git a/libfixposix.pc.in b/src/libfixposix.pc.in similarity index 72% rename from libfixposix.pc.in rename to src/libfixposix.pc.in index 81dcb39..dc01824 100644 --- a/libfixposix.pc.in +++ b/src/libfixposix.pc.in @@ -8,6 +8,6 @@ Description: Thin wrapper over POSIX functions Version: @PACKAGE_VERSION@ URL: @PACKAGE_URL@ -Cflags: -I${includedir} @LFP_CFLAGS@ @LFP_CPPFLAGS@ +Cflags: -I${includedir} @LFP_CFLAGS@ Libs: -L${libdir} -lfixposix @PTHREAD_LIBS@ -Libs.private: -L${libdir} @LFP_LDFLAGS@ +Libs.private: -L${libdir} @LFP_LIBS@ diff --git a/src/tests/buildinfo.bats.in b/src/tests/buildinfo.bats.in new file mode 100644 index 0000000..1916002 --- /dev/null +++ b/src/tests/buildinfo.bats.in @@ -0,0 +1,26 @@ +#!@BATSPATH@/bats +# -*- shell-script -*- + +srcdir="${BATS_PREFIX}/../.." +testbin="./src/tests/buildinfo" +verfile=${srcdir}/VERSION + +@test "should return correct status code" { + run "${testbin}" + [ "${status}" -eq 0 ] +} + +@test "should print build info" { + run "${testbin}" + + got_release=$(echo "${output}" | cut -d \; -f 1) + got_vcsid=$(echo "${output}" | cut -d \; -f 2) + + env 1>&2 + + release=$(< "${verfile}") + [ ${release} == "${got_release}" ] + + vcsid=$(git rev-parse --short HEAD 2>/dev/null || true) + [ x"${vcsid}" == x"${got_vcsid}" ] +} diff --git a/src/tests/buildinfo.c b/src/tests/buildinfo.c new file mode 100644 index 0000000..fbcdea0 --- /dev/null +++ b/src/tests/buildinfo.c @@ -0,0 +1,19 @@ +#include + +#include + +int main() +{ + struct lfp_buildinfo info; + int ret = lfp_buildinfo(&info); + if (ret != 0) { + perror("lfp_buildinfo()"); + return 1; + } + + unsigned major = (info.release >> 16) & 0xff; + unsigned minor = (info.release >> 8) & 0xff; + unsigned micro = info.release & 0xff; + printf("%u.%u.%u;%s\n", major, minor, micro, info.vcsid); + return 0; +} diff --git a/src/tests/lib/LICENSE b/src/tests/lib/LICENSE new file mode 100644 index 0000000..bac4eb2 --- /dev/null +++ b/src/tests/lib/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014 Sam Stephenson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/tests/lib/bats b/src/tests/lib/bats new file mode 100755 index 0000000..71f392f --- /dev/null +++ b/src/tests/lib/bats @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +set -e + +version() { + echo "Bats 0.4.0" +} + +usage() { + version + echo "Usage: bats [-c] [-p | -t] [ ...]" +} + +help() { + usage + echo + echo " is the path to a Bats test file, or the path to a directory" + echo " containing Bats test files." + echo + echo " -c, --count Count the number of test cases without running any tests" + echo " -h, --help Display this help message" + echo " -p, --pretty Show results in pretty format (default for terminals)" + echo " -t, --tap Show results in TAP format" + echo " -v, --version Display the version number" + echo + echo " For more information, see https://github.com/sstephenson/bats" + echo +} + +resolve_link() { + $(type -p greadlink readlink | head -1) "$1" +} + +abs_dirname() { + local cwd="$(pwd)" + local path="$1" + + while [ -n "$path" ]; do + cd "${path%/*}" + local name="${path##*/}" + path="$(resolve_link "$name" || true)" + done + + pwd + cd "$cwd" +} + +expand_path() { + { cd "$(dirname "$1")" 2>/dev/null + local dirname="$PWD" + cd "$OLDPWD" + echo "$dirname/$(basename "$1")" + } || echo "$1" +} + +BATS_LIBEXEC="$(abs_dirname "$0")" +export BATS_PREFIX="$(abs_dirname "$BATS_LIBEXEC")" +export BATS_CWD="$(abs_dirname .)" +export PATH="$BATS_LIBEXEC:$PATH" + +options=() +arguments=() +for arg in "$@"; do + if [ "${arg:0:1}" = "-" ]; then + if [ "${arg:1:1}" = "-" ]; then + options[${#options[*]}]="${arg:2}" + else + index=1 + while option="${arg:$index:1}"; do + [ -n "$option" ] || break + options[${#options[*]}]="$option" + let index+=1 + done + fi + else + arguments[${#arguments[*]}]="$arg" + fi +done + +unset count_flag pretty +[ -t 0 ] && [ -t 1 ] && pretty="1" +[ -n "$CI" ] && pretty="" + +for option in "${options[@]}"; do + case "$option" in + "h" | "help" ) + help + exit 0 + ;; + "v" | "version" ) + version + exit 0 + ;; + "c" | "count" ) + count_flag="-c" + ;; + "t" | "tap" ) + pretty="" + ;; + "p" | "pretty" ) + pretty="1" + ;; + * ) + usage >&2 + exit 1 + ;; + esac +done + +if [ "${#arguments[@]}" -eq 0 ]; then + usage >&2 + exit 1 +fi + +filenames=() +for filename in "${arguments[@]}"; do + if [ -d "$filename" ]; then + shopt -s nullglob + for suite_filename in "$(expand_path "$filename")"/*.bats; do + filenames["${#filenames[@]}"]="$suite_filename" + done + shopt -u nullglob + else + filenames["${#filenames[@]}"]="$(expand_path "$filename")" + fi +done + +if [ "${#filenames[@]}" -eq 1 ]; then + command="bats-exec-test" +else + command="bats-exec-suite" +fi + +if [ -n "$pretty" ]; then + extended_syntax_flag="-x" + formatter="bats-format-tap-stream" +else + extended_syntax_flag="" + formatter="cat" +fi + +set -o pipefail execfail +exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter" diff --git a/src/tests/lib/bats-exec-suite b/src/tests/lib/bats-exec-suite new file mode 100755 index 0000000..29ab255 --- /dev/null +++ b/src/tests/lib/bats-exec-suite @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -e + +count_only_flag="" +if [ "$1" = "-c" ]; then + count_only_flag=1 + shift +fi + +extended_syntax_flag="" +if [ "$1" = "-x" ]; then + extended_syntax_flag="-x" + shift +fi + +trap "kill 0; exit 1" int + +count=0 +for filename in "$@"; do + let count+="$(bats-exec-test -c "$filename")" +done + +if [ -n "$count_only_flag" ]; then + echo "$count" + exit +fi + +echo "1..$count" +status=0 +offset=0 +for filename in "$@"; do + index=0 + { + IFS= read -r # 1..n + while IFS= read -r line; do + case "$line" in + "begin "* ) + let index+=1 + echo "${line/ $index / $(($offset + $index)) }" + ;; + "ok "* | "not ok "* ) + [ -n "$extended_syntax_flag" ] || let index+=1 + echo "${line/ $index / $(($offset + $index)) }" + [ "${line:0:6}" != "not ok" ] || status=1 + ;; + * ) + echo "$line" + ;; + esac + done + } < <( bats-exec-test $extended_syntax_flag "$filename" ) + offset=$(($offset + $index)) +done + +exit "$status" diff --git a/src/tests/lib/bats-exec-test b/src/tests/lib/bats-exec-test new file mode 100755 index 0000000..8f3bd51 --- /dev/null +++ b/src/tests/lib/bats-exec-test @@ -0,0 +1,346 @@ +#!/usr/bin/env bash +set -e +set -E +set -T + +BATS_COUNT_ONLY="" +if [ "$1" = "-c" ]; then + BATS_COUNT_ONLY=1 + shift +fi + +BATS_EXTENDED_SYNTAX="" +if [ "$1" = "-x" ]; then + BATS_EXTENDED_SYNTAX="$1" + shift +fi + +BATS_TEST_FILENAME="$1" +if [ -z "$BATS_TEST_FILENAME" ]; then + echo "usage: bats-exec " >&2 + exit 1 +elif [ ! -f "$BATS_TEST_FILENAME" ]; then + echo "bats: $BATS_TEST_FILENAME does not exist" >&2 + exit 1 +else + shift +fi + +BATS_TEST_DIRNAME="$(dirname "$BATS_TEST_FILENAME")" +BATS_TEST_NAMES=() + +load() { + local name="$1" + local filename + + if [ "${name:0:1}" = "/" ]; then + filename="${name}" + else + filename="$BATS_TEST_DIRNAME/${name}.bash" + fi + + [ -f "$filename" ] || { + echo "bats: $filename does not exist" >&2 + exit 1 + } + + source "${filename}" +} + +run() { + local e E T oldIFS + [[ ! "$-" =~ e ]] || e=1 + [[ ! "$-" =~ E ]] || E=1 + [[ ! "$-" =~ T ]] || T=1 + set +e + set +E + set +T + output="$("$@" 2>&1)" + status="$?" + oldIFS=$IFS + IFS=$'\n' lines=($output) + [ -z "$e" ] || set -e + [ -z "$E" ] || set -E + [ -z "$T" ] || set -T + IFS=$oldIFS +} + +setup() { + true +} + +teardown() { + true +} + +skip() { + BATS_TEST_SKIPPED=${1:-1} + BATS_TEST_COMPLETED=1 + exit 0 +} + +bats_test_begin() { + BATS_TEST_DESCRIPTION="$1" + if [ -n "$BATS_EXTENDED_SYNTAX" ]; then + echo "begin $BATS_TEST_NUMBER $BATS_TEST_DESCRIPTION" >&3 + fi + setup +} + +bats_test_function() { + local test_name="$1" + BATS_TEST_NAMES["${#BATS_TEST_NAMES[@]}"]="$test_name" +} + +bats_capture_stack_trace() { + BATS_PREVIOUS_STACK_TRACE=( "${BATS_CURRENT_STACK_TRACE[@]}" ) + BATS_CURRENT_STACK_TRACE=() + + local test_pattern=" $BATS_TEST_NAME $BATS_TEST_SOURCE" + local setup_pattern=" setup $BATS_TEST_SOURCE" + local teardown_pattern=" teardown $BATS_TEST_SOURCE" + + local frame + local index=1 + + while frame="$(caller "$index")"; do + BATS_CURRENT_STACK_TRACE["${#BATS_CURRENT_STACK_TRACE[@]}"]="$frame" + if [[ "$frame" = *"$test_pattern" || \ + "$frame" = *"$setup_pattern" || \ + "$frame" = *"$teardown_pattern" ]]; then + break + else + let index+=1 + fi + done + + BATS_SOURCE="$(bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}")" + BATS_LINENO="$(bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}")" +} + +bats_print_stack_trace() { + local frame + local index=1 + local count="${#@}" + + for frame in "$@"; do + local filename="$(bats_trim_filename "$(bats_frame_filename "$frame")")" + local lineno="$(bats_frame_lineno "$frame")" + + if [ $index -eq 1 ]; then + echo -n "# (" + else + echo -n "# " + fi + + local fn="$(bats_frame_function "$frame")" + if [ "$fn" != "$BATS_TEST_NAME" ]; then + echo -n "from function \`$fn' " + fi + + if [ $index -eq $count ]; then + echo "in test file $filename, line $lineno)" + else + echo "in file $filename, line $lineno," + fi + + let index+=1 + done +} + +bats_print_failed_command() { + local frame="$1" + local status="$2" + local filename="$(bats_frame_filename "$frame")" + local lineno="$(bats_frame_lineno "$frame")" + + local failed_line="$(bats_extract_line "$filename" "$lineno")" + local failed_command="$(bats_strip_string "$failed_line")" + echo -n "# \`${failed_command}' " + + if [ $status -eq 1 ]; then + echo "failed" + else + echo "failed with status $status" + fi +} + +bats_frame_lineno() { + local frame="$1" + local lineno="${frame%% *}" + echo "$lineno" +} + +bats_frame_function() { + local frame="$1" + local rest="${frame#* }" + local fn="${rest%% *}" + echo "$fn" +} + +bats_frame_filename() { + local frame="$1" + local rest="${frame#* }" + local filename="${rest#* }" + + if [ "$filename" = "$BATS_TEST_SOURCE" ]; then + echo "$BATS_TEST_FILENAME" + else + echo "$filename" + fi +} + +bats_extract_line() { + local filename="$1" + local lineno="$2" + sed -n "${lineno}p" "$filename" +} + +bats_strip_string() { + local string="$1" + printf "%s" "$string" | sed -e "s/^[ "$'\t'"]*//" -e "s/[ "$'\t'"]*$//" +} + +bats_trim_filename() { + local filename="$1" + local length="${#BATS_CWD}" + + if [ "${filename:0:length+1}" = "${BATS_CWD}/" ]; then + echo "${filename:length+1}" + else + echo "$filename" + fi +} + +bats_debug_trap() { + if [ "$BASH_SOURCE" != "$1" ]; then + bats_capture_stack_trace + fi +} + +bats_error_trap() { + BATS_ERROR_STATUS="$?" + BATS_ERROR_STACK_TRACE=( "${BATS_PREVIOUS_STACK_TRACE[@]}" ) + trap - debug +} + +bats_teardown_trap() { + trap "bats_exit_trap" exit + local status=0 + teardown >>"$BATS_OUT" 2>&1 || status="$?" + + if [ $status -eq 0 ]; then + BATS_TEARDOWN_COMPLETED=1 + elif [ -n "$BATS_TEST_COMPLETED" ]; then + BATS_ERROR_STATUS="$status" + BATS_ERROR_STACK_TRACE=( "${BATS_CURRENT_STACK_TRACE[@]}" ) + fi + + bats_exit_trap +} + +bats_exit_trap() { + local status + local skipped + trap - err exit + + skipped="" + if [ -n "$BATS_TEST_SKIPPED" ]; then + skipped=" # skip" + if [ "1" != "$BATS_TEST_SKIPPED" ]; then + skipped+=" ($BATS_TEST_SKIPPED)" + fi + fi + + if [ -z "$BATS_TEST_COMPLETED" ] || [ -z "$BATS_TEARDOWN_COMPLETED" ]; then + echo "not ok $BATS_TEST_NUMBER $BATS_TEST_DESCRIPTION" >&3 + bats_print_stack_trace "${BATS_ERROR_STACK_TRACE[@]}" >&3 + bats_print_failed_command "${BATS_ERROR_STACK_TRACE[${#BATS_ERROR_STACK_TRACE[@]}-1]}" "$BATS_ERROR_STATUS" >&3 + sed -e "s/^/# /" < "$BATS_OUT" >&3 + status=1 + else + echo "ok ${BATS_TEST_NUMBER}${skipped} ${BATS_TEST_DESCRIPTION}" >&3 + status=0 + fi + + rm -f "$BATS_OUT" + exit "$status" +} + +bats_perform_tests() { + echo "1..$#" + test_number=1 + status=0 + for test_name in "$@"; do + "$0" $BATS_EXTENDED_SYNTAX "$BATS_TEST_FILENAME" "$test_name" "$test_number" || status=1 + let test_number+=1 + done + exit "$status" +} + +bats_perform_test() { + BATS_TEST_NAME="$1" + if [ "$(type -t "$BATS_TEST_NAME" || true)" = "function" ]; then + BATS_TEST_NUMBER="$2" + if [ -z "$BATS_TEST_NUMBER" ]; then + echo "1..1" + BATS_TEST_NUMBER="1" + fi + + BATS_TEST_COMPLETED="" + BATS_TEARDOWN_COMPLETED="" + trap "bats_debug_trap \"\$BASH_SOURCE\"" debug + trap "bats_error_trap" err + trap "bats_teardown_trap" exit + "$BATS_TEST_NAME" >>"$BATS_OUT" 2>&1 + BATS_TEST_COMPLETED=1 + + else + echo "bats: unknown test name \`$BATS_TEST_NAME'" >&2 + exit 1 + fi +} + +if [ -z "$TMPDIR" ]; then + BATS_TMPDIR="/tmp" +else + BATS_TMPDIR="${TMPDIR%/}" +fi + +BATS_TMPNAME="$BATS_TMPDIR/bats.$$" +BATS_PARENT_TMPNAME="$BATS_TMPDIR/bats.$PPID" +BATS_OUT="${BATS_TMPNAME}.out" + +bats_preprocess_source() { + BATS_TEST_SOURCE="${BATS_TMPNAME}.src" + { tr -d '\r' < "$BATS_TEST_FILENAME"; echo; } | bats-preprocess > "$BATS_TEST_SOURCE" + trap "bats_cleanup_preprocessed_source" err exit + trap "bats_cleanup_preprocessed_source; exit 1" int +} + +bats_cleanup_preprocessed_source() { + rm -f "$BATS_TEST_SOURCE" +} + +bats_evaluate_preprocessed_source() { + if [ -z "$BATS_TEST_SOURCE" ]; then + BATS_TEST_SOURCE="${BATS_PARENT_TMPNAME}.src" + fi + source "$BATS_TEST_SOURCE" +} + +exec 3<&1 + +if [ "$#" -eq 0 ]; then + bats_preprocess_source + bats_evaluate_preprocessed_source + + if [ -n "$BATS_COUNT_ONLY" ]; then + echo "${#BATS_TEST_NAMES[@]}" + else + bats_perform_tests "${BATS_TEST_NAMES[@]}" + fi +else + bats_evaluate_preprocessed_source + bats_perform_test "$@" +fi diff --git a/src/tests/lib/bats-format-tap-stream b/src/tests/lib/bats-format-tap-stream new file mode 100755 index 0000000..614768f --- /dev/null +++ b/src/tests/lib/bats-format-tap-stream @@ -0,0 +1,165 @@ +#!/usr/bin/env bash +set -e + +# Just stream the TAP output (sans extended syntax) if tput is missing +command -v tput >/dev/null || exec grep -v "^begin " + +header_pattern='[0-9]+\.\.[0-9]+' +IFS= read -r header + +if [[ "$header" =~ $header_pattern ]]; then + count="${header:3}" + index=0 + failures=0 + skipped=0 + name="" + count_column_width=$(( ${#count} * 2 + 2 )) +else + # If the first line isn't a TAP plan, print it and pass the rest through + printf "%s\n" "$header" + exec cat +fi + +update_screen_width() { + screen_width="$(tput cols)" + count_column_left=$(( $screen_width - $count_column_width )) +} + +trap update_screen_width WINCH +update_screen_width + +begin() { + go_to_column 0 + printf_with_truncation $(( $count_column_left - 1 )) " %s" "$name" + clear_to_end_of_line + go_to_column $count_column_left + printf "%${#count}s/${count}" "$index" + go_to_column 1 +} + +pass() { + go_to_column 0 + printf " ✓ %s" "$name" + advance +} + +skip() { + local reason="$1" + [ -z "$reason" ] || reason=": $reason" + go_to_column 0 + printf " - %s (skipped%s)" "$name" "$reason" + advance +} + +fail() { + go_to_column 0 + set_color 1 bold + printf " ✗ %s" "$name" + advance +} + +log() { + set_color 1 + printf " %s\n" "$1" + clear_color +} + +summary() { + printf "\n%d test%s" "$count" "$(plural "$count")" + + printf ", %d failure%s" "$failures" "$(plural "$failures")" + + if [ "$skipped" -gt 0 ]; then + printf ", %d skipped" "$skipped" + fi + + printf "\n" +} + +printf_with_truncation() { + local width="$1" + shift + local string="$(printf "$@")" + + if [ "${#string}" -gt "$width" ]; then + printf "%s..." "${string:0:$(( $width - 4 ))}" + else + printf "%s" "$string" + fi +} + +go_to_column() { + local column="$1" + printf "\x1B[%dG" $(( $column + 1 )) +} + +clear_to_end_of_line() { + printf "\x1B[K" +} + +advance() { + clear_to_end_of_line + echo + clear_color +} + +set_color() { + local color="$1" + local weight="$2" + printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )" +} + +clear_color() { + printf "\x1B[0m" +} + +plural() { + [ "$1" -eq 1 ] || echo "s" +} + +_buffer="" + +buffer() { + _buffer="${_buffer}$("$@")" +} + +flush() { + printf "%s" "$_buffer" + _buffer="" +} + +finish() { + flush + printf "\n" +} + +trap finish EXIT + +while IFS= read -r line; do + case "$line" in + "begin "* ) + let index+=1 + name="${line#* $index }" + buffer begin + flush + ;; + "ok "* ) + skip_expr="ok $index # skip (\(([^)]*)\))?" + if [[ "$line" =~ $skip_expr ]]; then + let skipped+=1 + buffer skip "${BASH_REMATCH[2]}" + else + buffer pass + fi + ;; + "not ok "* ) + let failures+=1 + buffer fail + ;; + "# "* ) + buffer log "${line:2}" + ;; + esac +done + +buffer summary diff --git a/src/tests/lib/bats-preprocess b/src/tests/lib/bats-preprocess new file mode 100755 index 0000000..04297ed --- /dev/null +++ b/src/tests/lib/bats-preprocess @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +set -e + +encode_name() { + local name="$1" + local result="test_" + + if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then + name="${name//_/-5f}" + name="${name//-/-2d}" + name="${name// /_}" + result+="$name" + else + local length="${#name}" + local char i + + for ((i=0; i +#include +#include +#include +#include + +#define CHILDREN 128 +#define NTEMPFILES (TMP_MAX/CHILDREN) + +char **allocStrings(int, int); +void *stuff(void *arg); + +char **allocStrings(int nstrings, int length) +{ + char **out=malloc(sizeof(char *) *nstrings); + char *buf=malloc(length*nstrings); + char *p=buf; + for(int i=0;i -int main() +int main(void) { fd_set rset, wset, eset; + printf("1..1\n"); + lfp_fd_zero(&rset); lfp_fd_zero(&wset); lfp_fd_zero(&eset); @@ -16,5 +18,6 @@ int main() } } + printf("ok 1\n"); return 0; } diff --git a/src/tests/spawn.c b/src/tests/spawn.c index 13968a9..1a43886 100644 --- a/src/tests/spawn.c +++ b/src/tests/spawn.c @@ -1,12 +1,4 @@ #include -#include -#include -#include -#include - -#include -#include -#include #include @@ -21,8 +13,9 @@ void error_abort (const char* msg, int perrorp) abort(); } -int main () +int main (void) { + printf("1..1\n"); // Not implemented yet pid_t pid; char *path = "/bin/sh"; @@ -60,7 +53,7 @@ int main () err = lfp_spawn_file_actions_addclose(&file_actions,10); err = lfp_spawn_file_actions_addopen(&file_actions,1,tempnam2,O_WRONLY|O_APPEND,0); err = lfp_spawn_file_actions_adddup2(&file_actions,1,2); - err = lfp_spawn(&pid,path,myargv,environ,&file_actions,&attr); + err = lfp_spawn(&pid, path, myargv, lfp_get_environ(), &file_actions, &attr); if (err) { error_abort("failed to spawn", true); } fprintf(stderr,"spawned child %d\n",pid); err = lfp_spawn_file_actions_destroy(&file_actions); @@ -88,5 +81,6 @@ int main () unlink(tempnam2); if (err == -1) { error_abort("failed to remove the output file", true); } fprintf(stderr,"spawn test successful\n"); - exit(0); + printf("ok 1\n"); + return 0; } -- 2.20.1