mirror of
https://github.com/shadow-maint/shadow.git
synced 2026-01-27 06:14:09 +00:00
Compare commits
No commits in common. "master" and "4.18.0" have entirely different histories.
@ -22,5 +22,5 @@ runs:
|
||||
sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed
|
||||
sudo apt-get update
|
||||
sudo apt-get -y dist-upgrade
|
||||
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect libtool libbsd-dev libltdl-dev libsystemd-dev pkgconf
|
||||
sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect libtool libbsd-dev libltdl-dev pkgconf
|
||||
sudo apt-get -y build-dep shadow
|
||||
|
||||
7
.github/workflows/runner.yml
vendored
7
.github/workflows/runner.yml
vendored
@ -10,10 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, ubuntu-22.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: debug
|
||||
@ -65,7 +62,7 @@ jobs:
|
||||
tar -zxf $f
|
||||
d=$(basename $f .tar.gz)
|
||||
cd $d
|
||||
./configure --disable-logind
|
||||
./configure
|
||||
make -j5
|
||||
make check
|
||||
|
||||
|
||||
46
.github/workflows/static-code-analysis.yml
vendored
46
.github/workflows/static-code-analysis.yml
vendored
@ -56,49 +56,3 @@ jobs:
|
||||
with:
|
||||
severity: warning
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
python-linter:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup virtual environment
|
||||
working-directory: ./tests/system
|
||||
run: |
|
||||
sudo apt-get update
|
||||
|
||||
pip3 install virtualenv
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip3 install -r ./requirements.txt
|
||||
pip3 install flake8 pycodestyle isort mypy black
|
||||
|
||||
- name: flake8
|
||||
if: always()
|
||||
working-directory: ./tests/system
|
||||
run: source .venv/bin/activate && flake8 .
|
||||
|
||||
- name: pycodestyle
|
||||
if: always()
|
||||
working-directory: ./tests/system
|
||||
run: source .venv/bin/activate && pycodestyle .
|
||||
|
||||
- name: isort
|
||||
if: always()
|
||||
working-directory: ./tests/system
|
||||
run: source .venv/bin/activate && isort --check-only .
|
||||
|
||||
- name: black
|
||||
if: always()
|
||||
working-directory: ./tests/system
|
||||
run: source .venv/bin/activate && black --check --diff .
|
||||
|
||||
- name: mypy
|
||||
if: always()
|
||||
working-directory: ./tests/system
|
||||
run: source .venv/bin/activate && mypy --install-types --non-interactive tests
|
||||
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@ -21,16 +21,24 @@ test-driver
|
||||
/ABOUT-NLS
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
/compile
|
||||
/config.cache
|
||||
/config.guess
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.rpath
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/m4
|
||||
/build-aux/
|
||||
/missing
|
||||
/stamp-h1
|
||||
/test-driver
|
||||
/ylwrap
|
||||
|
||||
/po/*.header
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = lib
|
||||
|
||||
|
||||
10
autogen.sh
10
autogen.sh
@ -5,21 +5,12 @@ autoreconf -v -f --install "$(dirname "$0")" || exit 1
|
||||
CFLAGS="-O2"
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
CFLAGS="$CFLAGS -Wextra"
|
||||
CFLAGS="$CFLAGS -Werror=discarded-qualifiers"
|
||||
CFLAGS="$CFLAGS -Werror=implicit-function-declaration"
|
||||
CFLAGS="$CFLAGS -Werror=implicit-int"
|
||||
CFLAGS="$CFLAGS -Werror=incompatible-pointer-types"
|
||||
CFLAGS="$CFLAGS -Werror=int-conversion"
|
||||
CFLAGS="$CFLAGS -Werror=sign-compare"
|
||||
CFLAGS="$CFLAGS -Werror=sizeof-pointer-div"
|
||||
CFLAGS="$CFLAGS -Werror=unused-but-set-parameter"
|
||||
CFLAGS="$CFLAGS -Werror=unused-function"
|
||||
CFLAGS="$CFLAGS -Werror=unused-label"
|
||||
CFLAGS="$CFLAGS -Werror=unused-local-typedefs"
|
||||
CFLAGS="$CFLAGS -Werror=unused-parameter"
|
||||
CFLAGS="$CFLAGS -Werror=unused-variable"
|
||||
CFLAGS="$CFLAGS -Werror=unused-const-variable=1"
|
||||
CFLAGS="$CFLAGS -Werror=unused-value"
|
||||
CFLAGS="$CFLAGS -Wno-expansion-to-defined"
|
||||
CFLAGS="$CFLAGS -Wno-unknown-attributes"
|
||||
CFLAGS="$CFLAGS -Wno-unknown-warning-option"
|
||||
@ -27,7 +18,6 @@ CFLAGS="$CFLAGS -Wno-unknown-warning-option"
|
||||
"$(dirname "$0")"/configure \
|
||||
CFLAGS="$CFLAGS" \
|
||||
--enable-lastlog \
|
||||
--disable-logind \
|
||||
--enable-man \
|
||||
--enable-maintainer-mode \
|
||||
--enable-shared \
|
||||
|
||||
518
configure.ac
518
configure.ac
@ -1,20 +1,15 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ([2.69])
|
||||
m4_define([libsubid_abi_major], [5])
|
||||
m4_define([libsubid_abi_minor], [0])
|
||||
m4_define([libsubid_abi_micro], [0])
|
||||
m4_define([libsubid_abi_major], 5)
|
||||
m4_define([libsubid_abi_minor], 0)
|
||||
m4_define([libsubid_abi_micro], 0)
|
||||
m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
|
||||
|
||||
AC_INIT([shadow], [4.19.0], [pkg-shadow-devel@lists.alioth.debian.org], [],
|
||||
AC_INIT([shadow], [4.18.0], [pkg-shadow-devel@lists.alioth.debian.org], [],
|
||||
[https://github.com/shadow-maint/shadow])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects tar-pax])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_SUBST([AM_DISTCHECK_CONFIGURE_FLAGS], ["$ac_configure_args"])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major])
|
||||
AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor])
|
||||
@ -22,8 +17,8 @@ AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro])
|
||||
AC_SUBST([LIBSUBID_ABI], [libsubid_abi])
|
||||
|
||||
dnl Some hacks...
|
||||
test "x$prefix" = "xNONE" && prefix="/usr"
|
||||
test "X$prefix" = "X/usr" && exec_prefix=""
|
||||
test "$prefix" = "NONE" && prefix="/usr"
|
||||
test "$prefix" = "/usr" && exec_prefix=""
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
@ -41,15 +36,15 @@ LT_LIB_DLLOAD
|
||||
dnl Checks for libraries.
|
||||
|
||||
dnl shadow now uses the libc's shadow implementation
|
||||
AC_CHECK_HEADER([shadow.h],[],[AC_MSG_ERROR([You need a libc with shadow.h])])
|
||||
AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
|
||||
|
||||
AC_CHECK_FUNCS([arc4random_buf \
|
||||
AC_CHECK_FUNCS(arc4random_buf \
|
||||
getentropy getrandom \
|
||||
lckpwdf lutimes \
|
||||
updwtmpx innetgr \
|
||||
getspnam_r \
|
||||
rpmatch \
|
||||
memset_explicit explicit_bzero stpecpy stpeprintf])
|
||||
memset_explicit explicit_bzero stpecpy stpeprintf)
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
@ -60,230 +55,227 @@ AC_CHECK_MEMBERS([struct utmpx.ut_name,
|
||||
struct utmpx.ut_addr,
|
||||
struct utmpx.ut_addr_v6,
|
||||
struct utmpx.ut_time,
|
||||
struct utmpx.ut_xtime],[],[],[[#include <utmpx.h>]])
|
||||
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_REPLACE_FUNCS([putgrent putpwent putspent])
|
||||
AC_REPLACE_FUNCS([sgetgrent sgetpwent sgetspent])
|
||||
AC_REPLACE_FUNCS(putgrent putpwent putspent)
|
||||
AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent)
|
||||
|
||||
AC_CHECK_FUNC([setpgrp])
|
||||
AC_CHECK_FUNC([secure_getenv],
|
||||
[AC_DEFINE([HAS_SECURE_GETENV],[1],[Defined to 1 if you have the declaration of 'secure_getenv'])]
|
||||
)
|
||||
AC_CHECK_FUNC(setpgrp)
|
||||
AC_CHECK_FUNC(secure_getenv, [AC_DEFINE(HAS_SECURE_GETENV,
|
||||
1,
|
||||
[Defined to 1 if you have the declaration of 'secure_getenv'])])
|
||||
|
||||
AC_CACHE_CHECK([location of shared mail directory], [shadow_cv_maildir],
|
||||
AC_CACHE_CHECK([location of shared mail directory], shadow_cv_maildir,
|
||||
[for shadow_cv_maildir in /var/mail /var/spool/mail /usr/spool/mail /usr/mail none; do
|
||||
if test -d $shadow_cv_maildir; then
|
||||
break
|
||||
fi
|
||||
done])
|
||||
if test $shadow_cv_maildir != none; then
|
||||
AC_DEFINE_UNQUOTED([MAIL_SPOOL_DIR], ["$shadow_cv_maildir"],
|
||||
AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIR, "$shadow_cv_maildir",
|
||||
[Location of system mail spool directory.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([location of user mail file], [shadow_cv_mailfile],
|
||||
AC_CACHE_CHECK([location of user mail file], shadow_cv_mailfile,
|
||||
[for shadow_cv_mailfile in Mailbox mailbox Mail mail .mail none; do
|
||||
if test -f $HOME/$shadow_cv_mailfile; then
|
||||
break
|
||||
fi
|
||||
done])
|
||||
if test $shadow_cv_mailfile != none; then
|
||||
AC_DEFINE_UNQUOTED([MAIL_SPOOL_FILE], ["$shadow_cv_mailfile"],
|
||||
AC_DEFINE_UNQUOTED(MAIL_SPOOL_FILE, "$shadow_cv_mailfile",
|
||||
[Name of user's mail spool file if stored in user's home directory.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], [shadow_cv_logdir],
|
||||
AC_CACHE_CHECK([location of faillog/lastlog/wtmp], shadow_cv_logdir,
|
||||
[for shadow_cv_logdir in /var/log /var/adm /usr/adm /etc; do
|
||||
if test -d $shadow_cv_logdir; then
|
||||
break
|
||||
fi
|
||||
done])
|
||||
AC_DEFINE_UNQUOTED([FAILLOG_FILE], ["$shadow_cv_logdir/faillog"],
|
||||
AC_DEFINE_UNQUOTED(_WTMP_FILE, "$shadow_cv_logdir/wtmp",
|
||||
[Path for wtmp file.])
|
||||
AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$shadow_cv_logdir/lastlog",
|
||||
[Path for lastlog file.])
|
||||
AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$shadow_cv_logdir/faillog",
|
||||
[Path for faillog file.])
|
||||
|
||||
AC_DEFINE_UNQUOTED([PASSWD_PROGRAM], ["$exec_prefix/bin/passwd"],
|
||||
AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$exec_prefix/bin/passwd",
|
||||
[Path to passwd program.])
|
||||
|
||||
AC_ARG_ENABLE([shadowgrp],
|
||||
AC_ARG_ENABLE(shadowgrp,
|
||||
[AS_HELP_STRING([--enable-shadowgrp], [enable shadow group support @<:@default=yes@:>@])],
|
||||
[case "${enableval}" in
|
||||
yes) enable_shadowgrp="yes" ;;
|
||||
no) enable_shadowgrp="no" ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-shadowgrp]) ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-shadowgrp) ;;
|
||||
esac],
|
||||
[enable_shadowgrp="yes"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([man],
|
||||
AC_ARG_ENABLE(man,
|
||||
[AS_HELP_STRING([--enable-man],
|
||||
[regenerate roff man pages from Docbook @<:@default=no@:>@])],
|
||||
[enable_man="${enableval}"],
|
||||
[enable_man="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([account-tools-setuid],
|
||||
AC_ARG_ENABLE(account-tools-setuid,
|
||||
[AS_HELP_STRING([--enable-account-tools-setuid],
|
||||
[Install the user and group management tools setuid and authenticate the callers. This requires --with-libpam.])],
|
||||
[case "${enableval}" in
|
||||
yes) enable_acct_tools_setuid="yes" ;;
|
||||
no) enable_acct_tools_setuid="no" ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-account-tools-setuid])
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-account-tools-setuid)
|
||||
;;
|
||||
esac],
|
||||
[enable_acct_tools_setuid="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([subordinate-ids],
|
||||
AC_ARG_ENABLE(subordinate-ids,
|
||||
[AS_HELP_STRING([--enable-subordinate-ids],
|
||||
[support subordinate ids @<:@default=yes@:>@])],
|
||||
[enable_subids="${enableval}"],
|
||||
[enable_subids="maybe"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([lastlog],
|
||||
AC_ARG_ENABLE(lastlog,
|
||||
[AS_HELP_STRING([--enable-lastlog],
|
||||
[enable lastlog @<:@default=no@:>@])],
|
||||
[enable_lastlog="${enableval}"],
|
||||
[enable_lastlog="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([logind],
|
||||
[AS_HELP_STRING([--disable-logind],
|
||||
[disable logind integration])],
|
||||
[
|
||||
AS_CASE([${enableval}],
|
||||
[yes],[],
|
||||
[no],[],
|
||||
[AC_MSG_ERROR([bad parameter value for --enable-logind=${enableval}. ]dnl
|
||||
[Supported values are: --enable-logind (or --enable-logind=yes) and --disable-logind (or --enable-logind=no).])]
|
||||
)
|
||||
],
|
||||
AC_ARG_ENABLE(logind,
|
||||
[AS_HELP_STRING([--enable-logind],
|
||||
[enable logind @<:@default=yes@:>@])],
|
||||
[enable_logind="${enableval}"],
|
||||
[enable_logind="yes"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([audit],
|
||||
AC_ARG_WITH(audit,
|
||||
[AS_HELP_STRING([--with-audit], [use auditing support @<:@default=yes if found@:>@])],
|
||||
[with_audit=$withval], [with_audit=maybe])
|
||||
AC_ARG_WITH([libpam],
|
||||
AC_ARG_WITH(libpam,
|
||||
[AS_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
|
||||
[with_libpam=$withval], [with_libpam=maybe])
|
||||
AC_ARG_WITH([btrfs],
|
||||
AC_ARG_WITH(btrfs,
|
||||
[AS_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if found@:>@])],
|
||||
[with_btrfs=$withval], [with_btrfs=maybe])
|
||||
AC_ARG_WITH([selinux],
|
||||
AC_ARG_WITH(selinux,
|
||||
[AS_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
|
||||
[with_selinux=$withval], [with_selinux=maybe])
|
||||
AC_ARG_WITH([acl],
|
||||
AC_ARG_WITH(acl,
|
||||
[AS_HELP_STRING([--with-acl], [use ACL support @<:@default=yes if found@:>@])],
|
||||
[with_acl=$withval], [with_acl=maybe])
|
||||
AC_ARG_WITH([attr],
|
||||
AC_ARG_WITH(attr,
|
||||
[AS_HELP_STRING([--with-attr], [use Extended Attribute support @<:@default=yes if found@:>@])],
|
||||
[with_attr=$withval], [with_attr=maybe])
|
||||
AC_ARG_WITH([skey],
|
||||
AC_ARG_WITH(skey,
|
||||
[AS_HELP_STRING([--with-skey], [use S/Key support @<:@default=no@:>@])],
|
||||
[with_skey=$withval], [with_skey=no])
|
||||
AC_ARG_WITH([tcb],
|
||||
AC_ARG_WITH(tcb,
|
||||
[AS_HELP_STRING([--with-tcb], [use tcb support (incomplete) @<:@default=yes if found@:>@])],
|
||||
[with_tcb=$withval], [with_tcb=maybe])
|
||||
AC_ARG_WITH([sha-crypt],
|
||||
AC_ARG_WITH(sha-crypt,
|
||||
[AS_HELP_STRING([--with-sha-crypt], [allow the SHA256 and SHA512 password encryption algorithms @<:@default=yes@:>@])],
|
||||
[with_sha_crypt=$withval], [with_sha_crypt=yes])
|
||||
AC_ARG_WITH([bcrypt],
|
||||
AC_ARG_WITH(bcrypt,
|
||||
[AS_HELP_STRING([--with-bcrypt], [allow the bcrypt password encryption algorithm @<:@default=no@:>@])],
|
||||
[with_bcrypt=$withval], [with_bcrypt=no])
|
||||
AC_ARG_WITH([yescrypt],
|
||||
AC_ARG_WITH(yescrypt,
|
||||
[AS_HELP_STRING([--with-yescrypt], [allow the yescrypt password encryption algorithm @<:@default=no@:>@])],
|
||||
[with_yescrypt=$withval], [with_yescrypt=no])
|
||||
AC_ARG_WITH([nscd],
|
||||
AC_ARG_WITH(nscd,
|
||||
[AS_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
|
||||
[with_nscd=$withval], [with_nscd=yes])
|
||||
AC_ARG_WITH([sssd],
|
||||
AC_ARG_WITH(sssd,
|
||||
[AS_HELP_STRING([--with-sssd], [enable support for flushing sssd caches @<:@default=yes@:>@])],
|
||||
[with_sssd=$withval], [with_sssd=yes])
|
||||
AC_ARG_WITH([group-name-max-length],
|
||||
AC_ARG_WITH(group-name-max-length,
|
||||
[AS_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=32@:>@])],
|
||||
[with_group_name_max_length=$withval], [with_group_name_max_length=yes])
|
||||
AC_ARG_WITH([su],
|
||||
AC_ARG_WITH(su,
|
||||
[AS_HELP_STRING([--with-su], [build and install su program and man page @<:@default=yes@:>@])],
|
||||
[with_su=$withval], [with_su=yes])
|
||||
AC_ARG_WITH([libbsd],
|
||||
AC_ARG_WITH(libbsd,
|
||||
[AS_HELP_STRING([--with-libbsd], [use libbsd support @<:@default=yes if found@:>@])],
|
||||
[with_libbsd=$withval], [with_libbsd=yes])
|
||||
|
||||
if test "X$with_group_name_max_length" = "Xno" ; then
|
||||
if test "$with_group_name_max_length" = "no" ; then
|
||||
with_group_name_max_length=0
|
||||
elif test "X$with_group_name_max_length" = "Xyes" ; then
|
||||
elif test "$with_group_name_max_length" = "yes" ; then
|
||||
with_group_name_max_length=32
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([GROUP_NAME_MAX_LENGTH], [$with_group_name_max_length], [max group name length])
|
||||
AC_SUBST([GROUP_NAME_MAX_LENGTH])
|
||||
AC_DEFINE_UNQUOTED(GROUP_NAME_MAX_LENGTH, $with_group_name_max_length, [max group name length])
|
||||
AC_SUBST(GROUP_NAME_MAX_LENGTH)
|
||||
GROUP_NAME_MAX_LENGTH="$with_group_name_max_length"
|
||||
|
||||
|
||||
AM_CONDITIONAL([USE_SHA_CRYPT], [test "x$with_sha_crypt" = "xyes"])
|
||||
if test "X$with_sha_crypt" = "Xyes"; then
|
||||
AC_DEFINE([USE_SHA_CRYPT], [1], [Define to allow the SHA256 and SHA512 password encryption algorithms])
|
||||
AM_CONDITIONAL(USE_SHA_CRYPT, test "x$with_sha_crypt" = "xyes")
|
||||
if test "$with_sha_crypt" = "yes"; then
|
||||
AC_DEFINE(USE_SHA_CRYPT, 1, [Define to allow the SHA256 and SHA512 password encryption algorithms])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([USE_BCRYPT], [test "x$with_bcrypt" = "xyes"])
|
||||
if test "X$with_bcrypt" = "Xyes"; then
|
||||
AC_DEFINE([USE_BCRYPT], [1], [Define to allow the bcrypt password encryption algorithm])
|
||||
AM_CONDITIONAL(USE_BCRYPT, test "x$with_bcrypt" = "xyes")
|
||||
if test "$with_bcrypt" = "yes"; then
|
||||
AC_DEFINE(USE_BCRYPT, 1, [Define to allow the bcrypt password encryption algorithm])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([USE_YESCRYPT], [test "x$with_yescrypt" = "xyes"])
|
||||
if test "X$with_yescrypt" = "Xyes"; then
|
||||
AC_DEFINE([USE_YESCRYPT], [1], [Define to allow the yescrypt password encryption algorithm])
|
||||
AM_CONDITIONAL(USE_YESCRYPT, test "x$with_yescrypt" = "xyes")
|
||||
if test "$with_yescrypt" = "yes"; then
|
||||
AC_DEFINE(USE_YESCRYPT, 1, [Define to allow the yescrypt password encryption algorithm])
|
||||
fi
|
||||
|
||||
if test "X$with_nscd" = "Xyes"; then
|
||||
AC_CHECK_FUNC([posix_spawn],
|
||||
[AC_DEFINE([USE_NSCD], [1], [Define to support flushing of nscd caches])],
|
||||
if test "$with_nscd" = "yes"; then
|
||||
AC_CHECK_FUNC(posix_spawn,
|
||||
[AC_DEFINE(USE_NSCD, 1, [Define to support flushing of nscd caches])],
|
||||
[AC_MSG_ERROR([posix_spawn is needed for nscd support])])
|
||||
fi
|
||||
|
||||
if test "X$with_sssd" = "Xyes"; then
|
||||
AC_CHECK_FUNC([posix_spawn],
|
||||
[AC_DEFINE([USE_SSSD], [1], [Define to support flushing of sssd caches])],
|
||||
if test "$with_sssd" = "yes"; then
|
||||
AC_CHECK_FUNC(posix_spawn,
|
||||
[AC_DEFINE(USE_SSSD, 1, [Define to support flushing of sssd caches])],
|
||||
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
|
||||
fi
|
||||
|
||||
AS_IF([test "$with_su" != "no"], [AC_DEFINE([WITH_SU], [1], [Build with su])])
|
||||
AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su]))
|
||||
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
|
||||
|
||||
dnl Check for some functions in libc first, only if not found check for
|
||||
dnl other libraries. This should prevent linking libnsl if not really
|
||||
dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
|
||||
|
||||
AC_SEARCH_LIBS([gethostbyname], [nsl])
|
||||
AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||
|
||||
PKG_CHECK_MODULES([CMOCKA], [cmocka], [have_cmocka="yes"],
|
||||
[AC_MSG_WARN([libcmocka not found, cmocka tests will not be built])])
|
||||
AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
|
||||
|
||||
AC_ARG_ENABLE([vendordir],
|
||||
[AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files])],[],[])
|
||||
AC_CHECK_LIB([econf],[econf_readDirs],[LIBECONF="-leconf"],[LIBECONF=""])
|
||||
if test -n "$LIBECONF"; then
|
||||
AC_DEFINE_UNQUOTED([VENDORDIR], ["$enable_vendordir"],
|
||||
[Directory for distribution provided configuration files])
|
||||
ECONF_CPPFLAGS="-DUSE_ECONF=1"
|
||||
AC_ARG_ENABLE([vendordir],
|
||||
AS_HELP_STRING([--enable-vendordir=DIR], [Directory for distribution provided configuration files]),,[])
|
||||
fi
|
||||
AC_SUBST([ECONF_CPPFLAGS])
|
||||
AC_SUBST([LIBECONF])
|
||||
AC_SUBST(ECONF_CPPFLAGS)
|
||||
AC_SUBST(LIBECONF)
|
||||
AC_SUBST([VENDORDIR], [$enable_vendordir])
|
||||
if test "x$enable_vendordir" != x; then
|
||||
AC_DEFINE([HAVE_VENDORDIR], [1], [Define to support vendor settings.])
|
||||
AC_DEFINE(HAVE_VENDORDIR, 1, [Define to support vendor settings.])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_VENDORDIR], [test "x$enable_vendordir" != x])
|
||||
|
||||
if test "X$enable_shadowgrp" = "Xyes"; then
|
||||
AC_DEFINE([SHADOWGRP], [1], [Define to support the shadow group file.])
|
||||
if test "$enable_shadowgrp" = "yes"; then
|
||||
AC_DEFINE(SHADOWGRP, 1, [Define to support the shadow group file.])
|
||||
fi
|
||||
AM_CONDITIONAL([SHADOWGRP], [test "x$enable_shadowgrp" = "xyes"])
|
||||
AM_CONDITIONAL(SHADOWGRP, test "x$enable_shadowgrp" = "xyes")
|
||||
|
||||
if test "X$enable_man" = "Xyes"; then
|
||||
if test "$enable_man" = "yes"; then
|
||||
dnl
|
||||
dnl Check for xsltproc
|
||||
dnl
|
||||
@ -295,21 +287,21 @@ if test "X$enable_man" = "Xyes"; then
|
||||
|
||||
dnl check for DocBook DTD and stylesheets in the local catalog.
|
||||
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.5//EN],
|
||||
[DocBook XML DTD V4.5], [], [enable_man=no])
|
||||
[DocBook XML DTD V4.5], [], enable_man=no)
|
||||
JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl],
|
||||
[DocBook XSL Stylesheets >= 1.70.1], [], [enable_man=no])
|
||||
[DocBook XSL Stylesheets >= 1.70.1], [], enable_man=no)
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_REGENERATE_MAN], [test "x$enable_man" != "xno"])
|
||||
AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
|
||||
|
||||
if test "$enable_subids" != "no"; then
|
||||
dnl
|
||||
dnl FIXME: check if 32 bit UIDs/GIDs are supported by libc
|
||||
dnl
|
||||
AC_CHECK_SIZEOF([uid_t],[], [[#include "sys/types.h"]])
|
||||
AC_CHECK_SIZEOF([gid_t],[], [[#include "sys/types.h"]])
|
||||
AC_CHECK_SIZEOF([uid_t],, [#include "sys/types.h"])
|
||||
AC_CHECK_SIZEOF([gid_t],, [#include "sys/types.h"])
|
||||
|
||||
if test "$ac_cv_sizeof_uid_t" -ge 4 && test "$ac_cv_sizeof_gid_t" -ge 4; then
|
||||
AC_DEFINE([ENABLE_SUBIDS], [1], [Define to support the subordinate IDs.])
|
||||
AC_DEFINE(ENABLE_SUBIDS, 1, [Define to support the subordinate IDs.])
|
||||
enable_subids="yes"
|
||||
else
|
||||
if test "x$enable_subids" = "xyes"; then
|
||||
@ -318,54 +310,55 @@ if test "$enable_subids" != "no"; then
|
||||
enable_subids="no"
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_SUBIDS], [test "x$enable_subids" != "xno"])
|
||||
AM_CONDITIONAL(ENABLE_SUBIDS, test "x$enable_subids" != "xno")
|
||||
|
||||
if test "X$enable_lastlog" = "Xyes" && test "X$ac_cv_header_lastlog_h" = "Xyes"; then
|
||||
AC_CACHE_CHECK([for ll_host in struct lastlog],
|
||||
[ac_cv_struct_lastlog_ll_host],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <lastlog.h>]],
|
||||
[struct lastlog ll; char *cp = ll.ll_host;])],
|
||||
if test "$enable_lastlog" = "yes" && test "$ac_cv_header_lastlog_h" = "yes"; then
|
||||
AC_CACHE_CHECK(for ll_host in struct lastlog,
|
||||
ac_cv_struct_lastlog_ll_host,
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <lastlog.h>],
|
||||
[struct lastlog ll; char *cp = ll.ll_host;]
|
||||
)],
|
||||
[ac_cv_struct_lastlog_ll_host=yes],
|
||||
[ac_cv_struct_lastlog_ll_host=no])
|
||||
]
|
||||
[ac_cv_struct_lastlog_ll_host=no]
|
||||
)
|
||||
)
|
||||
|
||||
if test "X$ac_cv_struct_lastlog_ll_host" = "Xyes"; then
|
||||
AC_DEFINE([HAVE_LL_HOST], [1],
|
||||
if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then
|
||||
AC_DEFINE(HAVE_LL_HOST, 1,
|
||||
[Define if struct lastlog has ll_host])
|
||||
AC_DEFINE([ENABLE_LASTLOG], [1], [Define to support lastlog.])
|
||||
AC_DEFINE(ENABLE_LASTLOG, 1, [Define to support lastlog.])
|
||||
enable_lastlog="yes"
|
||||
else
|
||||
AC_MSG_ERROR([Cannot enable support for lastlog on systems where the data structures aren't available])
|
||||
enable_lastlog="no"
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_LASTLOG], [test "x$enable_lastlog" != "xno"])
|
||||
AM_CONDITIONAL(ENABLE_LASTLOG, test "x$enable_lastlog" != "xno")
|
||||
|
||||
AC_SUBST([LIBSYSTEMD])
|
||||
if test "X$enable_logind" = "Xyes"; then
|
||||
AC_CHECK_LIB([systemd], [sd_session_get_remote_host],
|
||||
[
|
||||
LIBSYSTEMD=-lsystemd
|
||||
AC_DEFINE([ENABLE_LOGIND], [1], [Define to manage session support with logind.])
|
||||
],[
|
||||
AC_MSG_ERROR([libsystemd not found. If logind integration is not required, disable it using the --disable-logind option. ]dnl
|
||||
[ If logind integration is required, consider installing systemd or another package that provides libsystemd.])
|
||||
]
|
||||
)
|
||||
AC_SUBST(LIBSYSTEMD)
|
||||
if test "$enable_logind" = "yes"; then
|
||||
AC_CHECK_LIB(systemd, sd_session_get_remote_host,
|
||||
[enable_logind="yes"; [LIBSYSTEMD=-lsystemd];
|
||||
AC_DEFINE(ENABLE_LOGIND, 1,
|
||||
[Define to manage session support with logind.])],
|
||||
[enable_logind="no"])
|
||||
fi
|
||||
AM_CONDITIONAL([ENABLE_LOGIND], [test "X$enable_logind" = "Xyes"])
|
||||
AM_CONDITIONAL(ENABLE_LOGIND, test "x$enable_logind" != "xno")
|
||||
|
||||
AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT=-lcrypt],
|
||||
AC_SUBST(LIBCRYPT)
|
||||
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT=-lcrypt],
|
||||
[AC_MSG_ERROR([crypt() not found])])
|
||||
AC_SUBST([LIBCRYPT])
|
||||
|
||||
AC_SUBST([LIBBSD])
|
||||
AC_SUBST(LIYESCRYPT)
|
||||
AC_CHECK_LIB(crypt, crypt, [LIYESCRYPT=-lcrypt],
|
||||
[AC_MSG_ERROR([crypt() not found])])
|
||||
|
||||
AC_SUBST(LIBBSD)
|
||||
if test "$with_libbsd" != "no"; then
|
||||
AC_SEARCH_LIBS([readpassphrase], [bsd], [], [
|
||||
AC_MSG_ERROR([readpassphrase() is missing, either from libc or libbsd])
|
||||
])
|
||||
AS_IF([test "X$ac_cv_search_readpassphrase" = "X-lbsd"], [
|
||||
AS_IF([test "$ac_cv_search_readpassphrase" = "-lbsd"], [
|
||||
PKG_CHECK_MODULES([LIBBSD], [libbsd-overlay])
|
||||
])
|
||||
dnl Make sure either the libc or libbsd provide the header.
|
||||
@ -376,29 +369,29 @@ if test "$with_libbsd" != "no"; then
|
||||
AC_MSG_ERROR([readpassphrase.h is missing])
|
||||
])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
AC_DEFINE([WITH_LIBBSD], [1], [Build shadow with libbsd support])
|
||||
AC_DEFINE(WITH_LIBBSD, 1, [Build shadow with libbsd support])
|
||||
else
|
||||
AC_DEFINE([WITH_LIBBSD], [0], [Build shadow without libbsd support])
|
||||
AC_DEFINE(WITH_LIBBSD, 0, [Build shadow without libbsd support])
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_LIBBSD], [test x$with_libbsd = xyes])
|
||||
AM_CONDITIONAL(WITH_LIBBSD, test x$with_libbsd = xyes)
|
||||
|
||||
AC_SUBST([LIBACL])
|
||||
AC_SUBST(LIBACL)
|
||||
if test "$with_acl" != "no"; then
|
||||
AC_CHECK_HEADERS([acl/libacl.h attr/error_context.h], [acl_header="yes"], [acl_header="no"])
|
||||
if test "X$acl_header$with_acl" = "Xnoyes" ; then
|
||||
AC_CHECK_HEADERS(acl/libacl.h attr/error_context.h, [acl_header="yes"], [acl_header="no"])
|
||||
if test "$acl_header$with_acl" = "noyes" ; then
|
||||
AC_MSG_ERROR([acl/libacl.h or attr/error_context.h is missing])
|
||||
elif test "X$acl_header" = "Xyes" ; then
|
||||
AC_CHECK_LIB([acl], [perm_copy_file],
|
||||
[AC_CHECK_LIB([acl], [perm_copy_fd],
|
||||
elif test "$acl_header" = "yes" ; then
|
||||
AC_CHECK_LIB(acl, perm_copy_file,
|
||||
[AC_CHECK_LIB(acl, perm_copy_fd,
|
||||
[acl_lib="yes"],
|
||||
[acl_lib="no"])],
|
||||
[acl_lib="no"])
|
||||
if test "X$acl_lib$with_acl" = "Xnoyes" ; then
|
||||
if test "$acl_lib$with_acl" = "noyes" ; then
|
||||
AC_MSG_ERROR([libacl not found])
|
||||
elif test "X$acl_lib" = "Xno" ; then
|
||||
elif test "$acl_lib" = "no" ; then
|
||||
with_acl="no"
|
||||
else
|
||||
AC_DEFINE([WITH_ACL], [1],
|
||||
AC_DEFINE(WITH_ACL, 1,
|
||||
[Build shadow with ACL support])
|
||||
LIBACL="-lacl"
|
||||
with_acl="yes"
|
||||
@ -408,29 +401,55 @@ if test "$with_acl" != "no"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST([LIBAUDIT])
|
||||
AC_SUBST(LIBATTR)
|
||||
if test "$with_attr" != "no"; then
|
||||
AC_CHECK_HEADERS(attr/libattr.h attr/error_context.h, [attr_header="yes"], [attr_header="no"])
|
||||
if test "$attr_header$with_attr" = "noyes" ; then
|
||||
AC_MSG_ERROR([attr/libattr.h or attr/error_context.h is missing])
|
||||
elif test "$attr_header" = "yes" ; then
|
||||
AC_CHECK_LIB(attr, attr_copy_file,
|
||||
[AC_CHECK_LIB(attr, attr_copy_fd,
|
||||
[attr_lib="yes"],
|
||||
[attr_lib="no"])],
|
||||
[attr_lib="no"])
|
||||
if test "$attr_lib$with_attr" = "noyes" ; then
|
||||
AC_MSG_ERROR([libattr not found])
|
||||
elif test "$attr_lib" = "no" ; then
|
||||
with_attr="no"
|
||||
else
|
||||
AC_DEFINE(WITH_ATTR, 1,
|
||||
[Build shadow with Extended Attributes support])
|
||||
LIBATTR="-lattr"
|
||||
with_attr="yes"
|
||||
fi
|
||||
else
|
||||
with_attr="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(LIBAUDIT)
|
||||
if test "$with_audit" != "no"; then
|
||||
AC_CHECK_HEADER([libaudit.h], [audit_header="yes"], [audit_header="no"])
|
||||
if test "X$audit_header$with_audit" = "Xnoyes" ; then
|
||||
AC_CHECK_HEADER(libaudit.h, [audit_header="yes"], [audit_header="no"])
|
||||
if test "$audit_header$with_audit" = "noyes" ; then
|
||||
AC_MSG_ERROR([libaudit.h is missing])
|
||||
elif test "X$audit_header" = "Xyes"; then
|
||||
AC_CHECK_DECL([AUDIT_ADD_USER],[],[audit_header="no"],[[#include <libaudit.h>]])
|
||||
AC_CHECK_DECL([AUDIT_DEL_USER],[],[audit_header="no"],[[#include <libaudit.h>]])
|
||||
AC_CHECK_DECL([AUDIT_ADD_GROUP],[],[audit_header="no"],[[#include <libaudit.h>]])
|
||||
AC_CHECK_DECL([AUDIT_DEL_GROUP],[],[audit_header="no"],[[#include <libaudit.h>]])
|
||||
if test "X$audit_header$with_audit" = "Xnoyes" ; then
|
||||
elif test "$audit_header" = "yes"; then
|
||||
AC_CHECK_DECL(AUDIT_ADD_USER,,[audit_header="no"],[#include <libaudit.h>])
|
||||
AC_CHECK_DECL(AUDIT_DEL_USER,,[audit_header="no"],[#include <libaudit.h>])
|
||||
AC_CHECK_DECL(AUDIT_ADD_GROUP,,[audit_header="no"],[#include <libaudit.h>])
|
||||
AC_CHECK_DECL(AUDIT_DEL_GROUP,,[audit_header="no"],[#include <libaudit.h>])
|
||||
if test "$audit_header$with_audit" = "noyes" ; then
|
||||
AC_MSG_ERROR([AUDIT_ADD_USER AUDIT_DEL_USER AUDIT_ADD_GROUP or AUDIT_DEL_GROUP missing from libaudit.h])
|
||||
fi
|
||||
fi
|
||||
if test "X$audit_header" = "Xyes"; then
|
||||
AC_CHECK_LIB([audit], [audit_log_acct_message],
|
||||
if test "$audit_header" = "yes"; then
|
||||
AC_CHECK_LIB(audit, audit_log_acct_message,
|
||||
[audit_lib="yes"], [audit_lib="no"])
|
||||
if test "X$audit_lib$with_audit" = "Xnoyes" ; then
|
||||
if test "$audit_lib$with_audit" = "noyes" ; then
|
||||
AC_MSG_ERROR([libaudit not found])
|
||||
elif test "X$audit_lib" = "Xno" ; then
|
||||
elif test "$audit_lib" = "no" ; then
|
||||
with_audit="no"
|
||||
else
|
||||
AC_DEFINE([WITH_AUDIT], [1],
|
||||
AC_DEFINE(WITH_AUDIT, 1,
|
||||
[Define if you want to enable Audit messages])
|
||||
LIBAUDIT="-laudit"
|
||||
with_audit="yes"
|
||||
@ -443,43 +462,43 @@ fi
|
||||
if test "$with_btrfs" != "no"; then
|
||||
AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
|
||||
[btrfs_headers="yes"], [btrfs_headers="no"])
|
||||
if test "X$btrfs_headers$with_btrfs" = "Xnoyes" ; then
|
||||
if test "$btrfs_headers$with_btrfs" = "noyes" ; then
|
||||
AC_MSG_ERROR([One of sys/statfs.h linux/magic.h linux/btrfs_tree.h is missing])
|
||||
fi
|
||||
|
||||
if test "X$btrfs_headers" = "Xyes" ; then
|
||||
AC_DEFINE([WITH_BTRFS], [1], [Build shadow with BtrFS support])
|
||||
if test "$btrfs_headers" = "yes" ; then
|
||||
AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
|
||||
with_btrfs="yes"
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_BTRFS], [test x$with_btrfs = xyes])
|
||||
AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
|
||||
|
||||
AC_SUBST([LIBSELINUX])
|
||||
AC_SUBST([LIBSEMANAGE])
|
||||
AC_SUBST(LIBSELINUX)
|
||||
AC_SUBST(LIBSEMANAGE)
|
||||
if test "$with_selinux" != "no"; then
|
||||
AC_CHECK_HEADERS([selinux/selinux.h], [selinux_header="yes"], [selinux_header="no"])
|
||||
if test "X$selinux_header$with_selinux" = "Xnoyes" ; then
|
||||
AC_CHECK_HEADERS(selinux/selinux.h, [selinux_header="yes"], [selinux_header="no"])
|
||||
if test "$selinux_header$with_selinux" = "noyes" ; then
|
||||
AC_MSG_ERROR([selinux/selinux.h is missing])
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS([semanage/semanage.h], [semanage_header="yes"], [semanage_header="no"])
|
||||
if test "X$semanage_header$with_selinux" = "Xnoyes" ; then
|
||||
AC_CHECK_HEADERS(semanage/semanage.h, [semanage_header="yes"], [semanage_header="no"])
|
||||
if test "$semanage_header$with_selinux" = "noyes" ; then
|
||||
AC_MSG_ERROR([semanage/semanage.h is missing])
|
||||
fi
|
||||
|
||||
if test "X$selinux_header$semanage_header" = "Xyesyes" ; then
|
||||
AC_CHECK_LIB([selinux], [is_selinux_enabled], [selinux_lib="yes"], [selinux_lib="no"])
|
||||
if test "X$selinux_lib$with_selinux" = "Xnoyes" ; then
|
||||
if test "$selinux_header$semanage_header" = "yesyes" ; then
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled, [selinux_lib="yes"], [selinux_lib="no"])
|
||||
if test "$selinux_lib$with_selinux" = "noyes" ; then
|
||||
AC_MSG_ERROR([libselinux not found])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([semanage], [semanage_connect], [semanage_lib="yes"], [semanage_lib="no"])
|
||||
if test "X$semanage_lib$with_selinux" = "Xnoyes" ; then
|
||||
AC_CHECK_LIB(semanage, semanage_connect, [semanage_lib="yes"], [semanage_lib="no"])
|
||||
if test "$semanage_lib$with_selinux" = "noyes" ; then
|
||||
AC_MSG_ERROR([libsemanage not found])
|
||||
fi
|
||||
|
||||
if test "X$selinux_lib$semanage_lib" = "Xyesyes" ; then
|
||||
AC_DEFINE([WITH_SELINUX], [1],
|
||||
if test "$selinux_lib$semanage_lib" = "yesyes" ; then
|
||||
AC_DEFINE(WITH_SELINUX, 1,
|
||||
[Build shadow with SELinux support])
|
||||
LIBSELINUX="-lselinux"
|
||||
LIBSEMANAGE="-lsemanage"
|
||||
@ -492,19 +511,19 @@ if test "$with_selinux" != "no"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST([LIBTCB])
|
||||
AC_SUBST(LIBTCB)
|
||||
if test "$with_tcb" != "no"; then
|
||||
AC_CHECK_HEADERS([tcb.h], [tcb_header="yes"], [tcb_header="no"])
|
||||
if test "X$tcb_header$with_tcb" = "Xnoyes" ; then
|
||||
AC_CHECK_HEADERS(tcb.h, [tcb_header="yes"], [tcb_header="no"])
|
||||
if test "$tcb_header$with_tcb" = "noyes" ; then
|
||||
AC_MSG_ERROR([tcb.h is missing])
|
||||
elif test "X$tcb_header" = "Xyes" ; then
|
||||
AC_CHECK_LIB([tcb], [tcb_is_suspect], [tcb_lib="yes"], [tcb_lib="no"])
|
||||
if test "X$tcb_lib$with_tcb" = "Xnoyes" ; then
|
||||
elif test "$tcb_header" = "yes" ; then
|
||||
AC_CHECK_LIB(tcb, tcb_is_suspect, [tcb_lib="yes"], [tcb_lib="no"])
|
||||
if test "$tcb_lib$with_tcb" = "noyes" ; then
|
||||
AC_MSG_ERROR([libtcb not found])
|
||||
elif test "X$tcb_lib" = "Xno" ; then
|
||||
elif test "$tcb_lib" = "no" ; then
|
||||
with_tcb="no"
|
||||
else
|
||||
AC_DEFINE([WITH_TCB], [1], [Build shadow with tcb support (incomplete)])
|
||||
AC_DEFINE(WITH_TCB, 1, [Build shadow with tcb support (incomplete)])
|
||||
LIBTCB="-ltcb"
|
||||
with_tcb="yes"
|
||||
fi
|
||||
@ -512,39 +531,39 @@ if test "$with_tcb" != "no"; then
|
||||
with_tcb="no"
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_TCB], [test x$with_tcb = xyes])
|
||||
AM_CONDITIONAL(WITH_TCB, test x$with_tcb = xyes)
|
||||
|
||||
AC_SUBST([LIBPAM])
|
||||
AC_SUBST(LIBPAM)
|
||||
if test "$with_libpam" != "no"; then
|
||||
AC_CHECK_LIB([pam], [pam_start],
|
||||
AC_CHECK_LIB(pam, pam_start,
|
||||
[pam_lib="yes"], [pam_lib="no"])
|
||||
if test "X$pam_lib$with_libpam" = "Xnoyes" ; then
|
||||
AC_MSG_ERROR([libpam not found])
|
||||
if test "$pam_lib$with_libpam" = "noyes" ; then
|
||||
AC_MSG_ERROR(libpam not found)
|
||||
fi
|
||||
|
||||
LIBPAM="-lpam"
|
||||
pam_conv_function="no"
|
||||
|
||||
AC_CHECK_LIB([pam], [openpam_ttyconv],
|
||||
AC_CHECK_LIB(pam, openpam_ttyconv,
|
||||
[pam_conv_function="openpam_ttyconv"],
|
||||
[AC_CHECK_LIB([pam_misc], [misc_conv],
|
||||
[pam_conv_function="misc_conv"; LIBPAM="$LIBPAM -lpam_misc"])]
|
||||
AC_CHECK_LIB(pam_misc, misc_conv,
|
||||
[pam_conv_function="misc_conv"; LIBPAM="$LIBPAM -lpam_misc"])
|
||||
)
|
||||
|
||||
if test "X$pam_conv_function$with_libpam" = "Xnoyes" ; then
|
||||
AC_MSG_ERROR([PAM conversation function not found])
|
||||
if test "$pam_conv_function$with_libpam" = "noyes" ; then
|
||||
AC_MSG_ERROR(PAM conversation function not found)
|
||||
fi
|
||||
|
||||
pam_headers_found=no
|
||||
AC_CHECK_HEADERS( [security/openpam.h security/pam_misc.h],
|
||||
[ pam_headers_found=yes ; break ], [],
|
||||
[[#include <security/pam_appl.h>]] )
|
||||
if test "X$pam_headers_found$with_libpam" = "Xnoyes" ; then
|
||||
AC_MSG_ERROR([PAM headers not found])
|
||||
[ #include <security/pam_appl.h> ] )
|
||||
if test "$pam_headers_found$with_libpam" = "noyes" ; then
|
||||
AC_MSG_ERROR(PAM headers not found)
|
||||
fi
|
||||
|
||||
|
||||
if test "X$pam_lib$pam_headers_found" = "Xyesyes" && test "$pam_conv_function" != "no" ; then
|
||||
if test "$pam_lib$pam_headers_found" = "yesyes" -a "$pam_conv_function" != "no" ; then
|
||||
with_libpam="yes"
|
||||
else
|
||||
with_libpam="no"
|
||||
@ -552,86 +571,87 @@ if test "$with_libpam" != "no"; then
|
||||
fi
|
||||
fi
|
||||
dnl Now with_libpam is either yes or no
|
||||
if test "X$with_libpam" = "Xyes"; then
|
||||
if test "$with_libpam" = "yes"; then
|
||||
AC_CHECK_DECLS([PAM_ESTABLISH_CRED,
|
||||
PAM_DELETE_CRED,
|
||||
PAM_NEW_AUTHTOK_REQD,
|
||||
PAM_DATA_SILENT],
|
||||
[], [], [[#include <security/pam_appl.h>]])
|
||||
[], [], [#include <security/pam_appl.h>])
|
||||
|
||||
|
||||
save_libs=$LIBS
|
||||
LIBS="$LIBS $LIBPAM"
|
||||
# We do not use AC_CHECK_FUNCS to avoid duplicated definition with
|
||||
# Linux PAM.
|
||||
AC_CHECK_FUNC([pam_fail_delay], [AC_DEFINE([HAS_PAM_FAIL_DELAY], [1], [Define to 1 if you have the declaration of 'pam_fail_delay'])])
|
||||
AC_CHECK_FUNC(pam_fail_delay, [AC_DEFINE(HAS_PAM_FAIL_DELAY, 1, [Define to 1 if you have the declaration of 'pam_fail_delay'])])
|
||||
LIBS=$save_libs
|
||||
|
||||
AC_DEFINE([USE_PAM], [1], [Define to support Pluggable Authentication Modules])
|
||||
AC_DEFINE_UNQUOTED([SHADOW_PAM_CONVERSATION], [$pam_conv_function],[PAM conversation to use])
|
||||
AC_DEFINE(USE_PAM, 1, [Define to support Pluggable Authentication Modules])
|
||||
AC_DEFINE_UNQUOTED(SHADOW_PAM_CONVERSATION, [$pam_conv_function],[PAM conversation to use])
|
||||
AM_CONDITIONAL(USE_PAM, [true])
|
||||
|
||||
AC_MSG_CHECKING([use login and su access checking if PAM not used])
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_DEFINE([SU_ACCESS], [1], [Define to support /etc/suauth su access control.])
|
||||
AC_MSG_CHECKING([use login and su access checking if PAM not used])
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(SU_ACCESS, 1, [Define to support /etc/suauth su access control.])
|
||||
AM_CONDITIONAL(USE_PAM, [false])
|
||||
AC_MSG_CHECKING(use login and su access checking if PAM not used)
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
AM_CONDITIONAL([USE_PAM], [test "X$with_libpam" = "Xyes"])
|
||||
|
||||
if test "$enable_acct_tools_setuid" != "no"; then
|
||||
if test "$with_libpam" != "yes"; then
|
||||
if test "X$enable_acct_tools_setuid" = "Xyes"; then
|
||||
AC_MSG_ERROR([PAM support is required for --enable-account-tools-setuid])
|
||||
if test "$enable_acct_tools_setuid" = "yes"; then
|
||||
AC_MSG_ERROR(PAM support is required for --enable-account-tools-setuid)
|
||||
else
|
||||
enable_acct_tools_setuid="no"
|
||||
fi
|
||||
else
|
||||
enable_acct_tools_setuid="yes"
|
||||
fi
|
||||
if test "X$enable_acct_tools_setuid" = "Xyes"; then
|
||||
AC_DEFINE([ACCT_TOOLS_SETUID],
|
||||
[1],
|
||||
if test "$enable_acct_tools_setuid" = "yes"; then
|
||||
AC_DEFINE(ACCT_TOOLS_SETUID,
|
||||
1,
|
||||
[Define if account management tools should be installed setuid and authenticate the callers])
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([ACCT_TOOLS_SETUID], [test "x$enable_acct_tools_setuid" = "xyes"])
|
||||
AM_CONDITIONAL(ACCT_TOOLS_SETUID, test "x$enable_acct_tools_setuid" = "xyes")
|
||||
|
||||
|
||||
AC_ARG_WITH([fcaps],
|
||||
AC_ARG_WITH(fcaps,
|
||||
[AS_HELP_STRING([--with-fcaps], [use file capabilities instead of suid binaries for newuidmap/newgidmap @<:@default=no@:>@])],
|
||||
[with_fcaps=$withval], [with_fcaps=no])
|
||||
AM_CONDITIONAL([FCAPS], [test "x$with_fcaps" = "xyes"])
|
||||
AM_CONDITIONAL(FCAPS, test "x$with_fcaps" = "xyes")
|
||||
|
||||
if test "x$with_fcaps" = "xyes"; then
|
||||
AC_CHECK_PROGS([capcmd], ["setcap"])
|
||||
AC_CHECK_PROGS(capcmd, "setcap")
|
||||
if test "x$capcmd" = "x" ; then
|
||||
AC_MSG_ERROR([setcap command not available])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST([LIBSKEY])
|
||||
AC_SUBST([LIBMD])
|
||||
if test "X$with_skey" = "Xyes"; then
|
||||
AC_CHECK_LIB([md], [MD5Init], [LIBMD=-lmd])
|
||||
AC_CHECK_LIB([skey], [skeychallenge], [LIBSKEY=-lskey],
|
||||
AC_SUBST(LIBSKEY)
|
||||
AC_SUBST(LIBMD)
|
||||
if test "$with_skey" = "yes"; then
|
||||
AC_CHECK_LIB(md, MD5Init, [LIBMD=-lmd])
|
||||
AC_CHECK_LIB(skey, skeychallenge, [LIBSKEY=-lskey],
|
||||
[AC_MSG_ERROR([libskey missing. You can download S/Key source code from http://rsync1.it.gentoo.org/gentoo/distfiles/skey-1.1.5.tar.bz2])])
|
||||
AC_DEFINE([SKEY], [1], [Define to support S/Key logins.])
|
||||
AC_DEFINE(SKEY, 1, [Define to support S/Key logins.])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdio.h>
|
||||
#include <skey.h>
|
||||
]], [[
|
||||
skeychallenge((void*)0, (void*)0, (void*)0, 0);
|
||||
]])],[AC_DEFINE([SKEY_BSD_STYLE], [1], [Define to support newer BSD S/Key API])],[])
|
||||
]])],[AC_DEFINE(SKEY_BSD_STYLE, 1, [Define to support newer BSD S/Key API])],[])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNC([fgetpwent_r], [AC_DEFINE([HAVE_FGETPWENT_R], [1], [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
|
||||
AC_CHECK_FUNC(fgetpwent_r, [AC_DEFINE(HAVE_FGETPWENT_R, 1, [Defined to 1 if you have the declaration of 'fgetpwent_r'])])
|
||||
|
||||
AC_DEFINE_UNQUOTED([SHELL], ["$SHELL"], [The default shell.])
|
||||
AC_DEFINE_UNQUOTED(SHELL, ["$SHELL"], [The default shell.])
|
||||
|
||||
AM_GNU_GETTEXT_VERSION([0.19])
|
||||
AM_GNU_GETTEXT([external], [need-ngettext])
|
||||
AM_CONDITIONAL([USE_NLS], [test "x$USE_NLS" = "xyes"])
|
||||
AM_CONDITIONAL(USE_NLS, test "x$USE_NLS" = "xyes")
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
@ -670,28 +690,30 @@ AC_CONFIG_FILES([
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_NOTICE([shadow ${PACKAGE_VERSION} has been configured with the following features:
|
||||
|
||||
auditing support: $with_audit
|
||||
PAM support: $with_libpam
|
||||
suid account management tools: $enable_acct_tools_setuid
|
||||
SELinux support: $with_selinux
|
||||
BtrFS support: $with_btrfs
|
||||
ACL support: $with_acl
|
||||
Extended Attributes support: $with_attr
|
||||
tcb support (incomplete): $with_tcb
|
||||
shadow group support: $enable_shadowgrp
|
||||
S/Key support: $with_skey
|
||||
SHA passwords encryption: $with_sha_crypt
|
||||
bcrypt passwords encryption: $with_bcrypt
|
||||
yescrypt passwords encryption: $with_yescrypt
|
||||
nscd support: $with_nscd
|
||||
sssd support: $with_sssd
|
||||
subordinate IDs support: $enable_subids
|
||||
enable lastlog: $enable_lastlog
|
||||
enable logind: $enable_logind
|
||||
use file caps: $with_fcaps
|
||||
install su: $with_su
|
||||
enabled vendor dir: $enable_vendordir
|
||||
|
||||
])
|
||||
echo
|
||||
echo "shadow will be compiled with the following features:"
|
||||
echo
|
||||
echo " auditing support: $with_audit"
|
||||
echo " PAM support: $with_libpam"
|
||||
if test "$with_libpam" = "yes"; then
|
||||
echo " suid account management tools: $enable_acct_tools_setuid"
|
||||
fi
|
||||
echo " SELinux support: $with_selinux"
|
||||
echo " BtrFS support: $with_btrfs"
|
||||
echo " ACL support: $with_acl"
|
||||
echo " Extended Attributes support: $with_attr"
|
||||
echo " tcb support (incomplete): $with_tcb"
|
||||
echo " shadow group support: $enable_shadowgrp"
|
||||
echo " S/Key support: $with_skey"
|
||||
echo " SHA passwords encryption: $with_sha_crypt"
|
||||
echo " bcrypt passwords encryption: $with_bcrypt"
|
||||
echo " yescrypt passwords encryption: $with_yescrypt"
|
||||
echo " nscd support: $with_nscd"
|
||||
echo " sssd support: $with_sssd"
|
||||
echo " subordinate IDs support: $enable_subids"
|
||||
echo " enable lastlog: $enable_lastlog"
|
||||
echo " enable logind: $enable_logind"
|
||||
echo " use file caps: $with_fcaps"
|
||||
echo " install su: $with_su"
|
||||
echo " enabled vendor dir: $enable_vendordir"
|
||||
echo
|
||||
|
||||
@ -346,7 +346,7 @@
|
||||
return value points to static data whose content is overwritten by
|
||||
each call.
|
||||
|
||||
Warning: the key space consists of 2**56 equal 7.2e16 possible values.
|
||||
Warning: The key space consists of 2**56 equal 7.2e16 possible values.
|
||||
Exhaustive searches of this key space are possible using massively
|
||||
parallel computers. Software, such as crack(1), is available which
|
||||
will search the portion of this key space that is generally used by
|
||||
@ -996,7 +996,7 @@
|
||||
sudo for the shadow suite, is available as at:
|
||||
<ftp://sunsite.unc.edu/pub/Linux/system/Admin/sudo-1.2-shadow.tgz>
|
||||
|
||||
Warning: when you install sudo your /etc/sudoers file will be replaced
|
||||
Warning: When you install sudo your /etc/sudoers file will be replaced
|
||||
with a default one, so you need to make a backup of it if you have
|
||||
added anything to the default one. (you could also edit the Makefile
|
||||
and remove the line that copies the default file to /etc).
|
||||
|
||||
@ -73,31 +73,3 @@ were running some of the CI checks locally:
|
||||
```
|
||||
share/container-build.sh
|
||||
```
|
||||
|
||||
### Container troubleshooting
|
||||
|
||||
When working with containers for testing or development,
|
||||
you may encounter issues.
|
||||
Here are common troubleshooting steps:
|
||||
|
||||
**Post-test inspection:**
|
||||
- **Container persistence**: after tests complete, containers are left running
|
||||
to allow inspection of the test environment and debugging of any failures.
|
||||
This enables you to examine logs, file states, and system configuration
|
||||
that existed when tests ran.
|
||||
|
||||
**Container management:**
|
||||
- **List containers**: `docker ps -a` to see all containers and their status.
|
||||
- **Access container**: `docker exec -it <container-name> bash` to get shell access.
|
||||
- **Container logs**: `docker logs <container-name>` to view container output.
|
||||
- **Remove containers**: `docker rm <container-name>` to clean up stopped containers.
|
||||
|
||||
**Common issues:**
|
||||
- **Container not found**: ensure you've run the Ansible playbook
|
||||
to create the required containers.
|
||||
- **Permission issues**: verify the container has proper privileges
|
||||
for user/group operations.
|
||||
- **Network connectivity**: check that containers can communicate
|
||||
if tests involve network operations.
|
||||
- **Resource constraints**: ensure sufficient disk space and memory
|
||||
for container operations.
|
||||
|
||||
@ -12,27 +12,9 @@ be triggered locally by following the instructions specified in the
|
||||
|
||||
## System tests
|
||||
|
||||
The project runs system tests to verify functionality
|
||||
across different environments
|
||||
using two complementary approaches:
|
||||
|
||||
### Bash system tests
|
||||
|
||||
Legacy Bash system tests run on Ubuntu in a VM environment.
|
||||
These provide coverage for Ubuntu-specific scenarios and legacy test cases.
|
||||
You can run this step locally by following the instructions provided
|
||||
in the [Tests](tests.md#bash-system-tests) page.
|
||||
|
||||
### Python system tests
|
||||
|
||||
The new Python system tests use pytest and pytest-mh,
|
||||
running across multiple distributions (Fedora, Debian, Alpine, openSUSE)
|
||||
in containerized environments.
|
||||
These tests provide cross-distribution compatibility
|
||||
and improved environment management compared to the Bash tests.
|
||||
|
||||
For local execution of Python system tests,
|
||||
follow the instructions in the [Tests](tests.md#python-system-tests) page.
|
||||
The project is tested on Ubuntu. For that purpose it is built & installed in
|
||||
this distribution in a VM. You can run this step locally by following the
|
||||
instructions provided in the [Tests](tests.md#system-tests) page.
|
||||
|
||||
## Static code analysis
|
||||
|
||||
|
||||
@ -1,96 +1,12 @@
|
||||
# Coding style
|
||||
|
||||
The Shadow project is developed in C,
|
||||
with Python used for testing purposes.
|
||||
Each language follows its own established conventions and style guidelines.
|
||||
|
||||
## C code
|
||||
|
||||
* For a general guidance refer to the
|
||||
[Linux kernel coding style](https://www.kernel.org/doc/html/latest/process/coding-style.html)
|
||||
|
||||
* Patches that change the existing coding style are not welcome, as they make
|
||||
downstream porting harder for the distributions
|
||||
|
||||
### Indentation
|
||||
## Indentation
|
||||
|
||||
Tabs are preferred over spaces for indentation. Loading the `.editorconfig`
|
||||
file in your preferred IDE may help you configure it.
|
||||
|
||||
## Python code
|
||||
|
||||
Python code in the Shadow project is primarily found
|
||||
in the system test framework (`tests/system/`).
|
||||
Follow these conventions for consistency:
|
||||
|
||||
### General conventions
|
||||
|
||||
* **PEP 8 compliance**: follow [PEP 8](https://pep8.org/) style guidelines.
|
||||
* **Code quality enforcement**: all Python code must pass flake8, pycodestyle, isort, mypy, and black checks.
|
||||
* **Import organization**: use absolute imports with `from __future__ import annotations`.
|
||||
* **Type hints**: use modern type hints (e.g., `str | None` instead of `Optional[str]`).
|
||||
* **Line length**: maximum 119 characters per line.
|
||||
* **Configuration**: all formatting and linting settings are defined in `tests/system/pyproject.toml`.
|
||||
|
||||
### Test code style
|
||||
|
||||
**File and test naming:**
|
||||
* Test files: `test_<command>.py` (e.g., `test_useradd.py`).
|
||||
* Test functions: `test_<command>__<specific_behavior>` using double underscores.
|
||||
* Use descriptive names that clearly indicate what is being tested.
|
||||
|
||||
**Test structure (AAA pattern):**
|
||||
```python
|
||||
@pytest.mark.topology(KnownTopology.Shadow)
|
||||
def test_useradd__add_user(shadow: Shadow):
|
||||
"""
|
||||
:title: Descriptive test title
|
||||
:setup:
|
||||
1. Setup steps
|
||||
:steps:
|
||||
1. Test steps
|
||||
:expectedresults:
|
||||
1. Expected outcomes
|
||||
:customerscenario: False
|
||||
"""
|
||||
# Arrange
|
||||
setup_code_here()
|
||||
|
||||
# Act
|
||||
result = shadow.command_to_test()
|
||||
|
||||
# Assert
|
||||
assert result is not None, "Descriptive failure message"
|
||||
```
|
||||
|
||||
**Avoiding flakiness:**
|
||||
* Use deterministic test data (avoid random values).
|
||||
* Clean up test artifacts properly (handled automatically by framework).
|
||||
* Use appropriate timeouts for time-sensitive operations.
|
||||
* Leverage the framework's automatic backup/restore functionality.
|
||||
|
||||
### Formatting and imports
|
||||
|
||||
**Required tools:**
|
||||
* **flake8**: for style guide enforcement and error detection.
|
||||
* **pycodestyle**: for PEP 8 style checking.
|
||||
* **isort**: for import sorting with profiles that work well with Black.
|
||||
* **Black**: for consistent code formatting.
|
||||
* **mypy**: for static type checking.
|
||||
|
||||
**Import order:**
|
||||
1. Standard library imports.
|
||||
2. Third-party imports (`pytest`, `pytest_mh`).
|
||||
3. Local framework imports (`framework.*`).
|
||||
|
||||
### Error handling and logging
|
||||
|
||||
**Error handling:**
|
||||
* Prefer explicit exceptions over silent failures.
|
||||
* Use `ProcessError` for command execution failures.
|
||||
* Provide context in error messages.
|
||||
|
||||
**Logging guidance:**
|
||||
* Use structured logging for test utilities in `tests/system/framework/`.
|
||||
* Include relevant context (command, parameters, expected vs actual results).
|
||||
* Leverage the framework's automatic artifact collection for debugging.
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
# Tests
|
||||
|
||||
Currently, shadow provides unit tests and system tests.
|
||||
System tests are split in two:
|
||||
Bash system tests and Python system tests.
|
||||
Currently, shadow provides unit and system tests.
|
||||
|
||||
## Unit tests
|
||||
|
||||
@ -22,243 +20,15 @@ make check
|
||||
|
||||
## System tests
|
||||
|
||||
System tests verify the behavior of shadow utilities
|
||||
in a complete system environment.
|
||||
There are two types of system tests available.
|
||||
These type of tests are written in shell. Unfortunately, the testing framework
|
||||
is tightly coupled to the Ubuntu distribution and it can only be run in this
|
||||
distribution. Besides, if anything fails during the execution the system can
|
||||
be left in an unstable state. Taking that into account you shouldn't run this
|
||||
workflow in your host machine, we recommend to use a disposable system like a
|
||||
VM or a container instead.
|
||||
|
||||
### Bash system tests
|
||||
|
||||
These tests are written in shell
|
||||
and are tightly coupled to the Ubuntu distribution.
|
||||
They can only be run on Ubuntu,
|
||||
and if anything fails during execution,
|
||||
the system can be left in an unstable state.
|
||||
You shouldn't run this workflow on your host machine—we recommend using a disposable system
|
||||
like a VM or a container instead.
|
||||
|
||||
You can execute Bash system tests by running:
|
||||
You can execute system tests by running:
|
||||
|
||||
```
|
||||
cd tests && ./run_all
|
||||
```
|
||||
|
||||
### Python system tests
|
||||
|
||||
The new system tests use Python,
|
||||
[pytest](https://pytest.org/)
|
||||
and [pytest-mh](https://pytest-mh.readthedocs.io/).
|
||||
The Python framework provides several advantages over Bash tests:
|
||||
|
||||
• **Cross-distribution compatibility**: works on all distributions in CI
|
||||
(Alpine, Debian, Fedora and openSUSE)
|
||||
unlike Bash tests which only run on Ubuntu.
|
||||
• **Proper environment management**: ensures clean setup and teardown
|
||||
with environment restoration even when tests fail.
|
||||
• **Improved test maintainability**: provides a rich, high-level API
|
||||
that reduces complex test code
|
||||
and makes tests easier to understand.
|
||||
• **Automated artifact collection**: automatically collects logs and artifacts
|
||||
when tests finish (even if they fail).
|
||||
• **Flexible infrastructure**: supports both VMs and containers for testing
|
||||
with local execution capabilities.
|
||||
• **Future extensibility**: enables potential filtering by ticket
|
||||
or importance and other advanced features.
|
||||
|
||||
[Read more about the benefits and rationale](https://github.com/shadow-maint/shadow/issues/835).
|
||||
|
||||
**For all new contributions,
|
||||
we recommend using the Python system test framework.**
|
||||
|
||||
#### Contribution guidance
|
||||
|
||||
The framework is under active development
|
||||
and welcomes contributions for missing features.
|
||||
When contributing:
|
||||
|
||||
1. **Framework improvements**: enhance the infrastructure in `tests/system/framework/`.
|
||||
2. **Proposing new tests**: place them in `tests/system/tests/`.
|
||||
Review existing examples in `tests/system/tests/`
|
||||
to understand the established patterns and conventions.
|
||||
3. **Missing features**: if you're comfortable implementing missing pytest-mh features,
|
||||
contributions are encouraged.
|
||||
|
||||
#### Running tests
|
||||
|
||||
##### Environment setup
|
||||
|
||||
A testing environment is required to run the system test framework.
|
||||
While the same system can be used,
|
||||
a disposable environment (container or VM) is recommended.
|
||||
|
||||
The default configuration relies on a pre-built container named `builder`
|
||||
that must be available in your container environment.
|
||||
This container contains:
|
||||
|
||||
- A complete shadow-utils installation
|
||||
- All required system dependencies
|
||||
|
||||
**Setup steps:**
|
||||
|
||||
1. **Build the container environment**: follow the instructions in [build_install.md](build_install.md)
|
||||
to create the required `builder` container.
|
||||
2. **Verify container availability**: ensure the `builder` container is accessible via Docker.
|
||||
|
||||
The default `mhc.yaml` configuration expects this container
|
||||
to be available as `builder`.
|
||||
|
||||
To ensure dependency isolation and system protection,
|
||||
run the tests within a Python virtual environment:
|
||||
|
||||
```bash
|
||||
cd tests/system
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r ./requirements.txt
|
||||
```
|
||||
|
||||
##### Configuration
|
||||
|
||||
The default configuration located in `tests/system` should be enough
|
||||
if you are using containers.
|
||||
If you run another environment you'll need to tune `tests/system/mhc.yaml`.
|
||||
Instructions are available in the
|
||||
[pytest-mh mhc.yaml documentation](https://pytest-mh.readthedocs.io/en/latest/articles/mhc-yaml.html).
|
||||
|
||||
##### Execution
|
||||
|
||||
Run all Python system tests:
|
||||
|
||||
```bash
|
||||
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v
|
||||
```
|
||||
|
||||
Run tests in a file:
|
||||
|
||||
```bash
|
||||
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v tests/test_useradd.py
|
||||
```
|
||||
|
||||
Run a single test case:
|
||||
|
||||
```bash
|
||||
pytest --mh-config=mhc.yaml --mh-lazy-ssh -v -k test_useradd__add_user
|
||||
```
|
||||
|
||||
**Command options explained:**
|
||||
- `--mh-config=mhc.yaml`: specifies the multihost configuration file
|
||||
- `--mh-lazy-ssh`: enables lazy SSH connections for better performance
|
||||
- `-v`: verbose output showing individual test results
|
||||
- `-k`: filters tests by name pattern
|
||||
|
||||
For additional running options,
|
||||
see the [pytest-mh running tests documentation](https://pytest-mh.readthedocs.io/en/latest/articles/running-tests.html).
|
||||
|
||||
#### Advanced testing features
|
||||
|
||||
The Python testing framework includes several advanced features
|
||||
for comprehensive testing:
|
||||
|
||||
**Test markers:**
|
||||
- `@pytest.mark.topology(KnownTopology.Shadow)`: specifies the test topology.
|
||||
- `@pytest.mark.builtwith("gshadow")`: skips tests when specific features are unavailable.
|
||||
- `@pytest.mark.parametrize()`: extensive parameterized testing
|
||||
for edge cases and different inputs.
|
||||
|
||||
**Rich command parsing:**
|
||||
All shadow command outputs are parsed into structured Python objects
|
||||
using the `jc` library:
|
||||
- `PasswdEntry`, `ShadowEntry`, `GroupEntry`, `GShadowEntry` for file entries
|
||||
- `ID` command parsing with group membership verification
|
||||
- Structured error handling and validation
|
||||
|
||||
#### Test development patterns
|
||||
|
||||
When writing new Python tests,
|
||||
follow these established patterns:
|
||||
|
||||
**Basic test structure:**
|
||||
```python
|
||||
@pytest.mark.topology(KnownTopology.Shadow)
|
||||
def test_command__specific_behavior(shadow: Shadow):
|
||||
"""
|
||||
:title: Descriptive test title
|
||||
:setup:
|
||||
1. Setup steps
|
||||
:steps:
|
||||
1. Test steps
|
||||
:expectedresults:
|
||||
1. Expected outcomes
|
||||
:customerscenario: False
|
||||
"""
|
||||
# Arrange
|
||||
shadow.useradd("testuser")
|
||||
|
||||
# Act
|
||||
result = shadow.tools.getent.passwd("testuser")
|
||||
|
||||
# Assert
|
||||
assert result is not None, "User should exist"
|
||||
assert result.name == "testuser", "Username should match"
|
||||
```
|
||||
|
||||
**Distribution-specific testing:**
|
||||
```python
|
||||
if "Debian" in shadow.host.distro_name:
|
||||
assert result.shell == "/bin/sh"
|
||||
else:
|
||||
assert result.shell == "/bin/bash"
|
||||
```
|
||||
|
||||
**Parameterized testing:**
|
||||
```python
|
||||
@pytest.mark.parametrize(
|
||||
"input_date, expected_epoch",
|
||||
[
|
||||
("1970-01-01", 0),
|
||||
("2025-01-01", 20089),
|
||||
("0", 0),
|
||||
],
|
||||
)
|
||||
def test_date_handling(shadow: Shadow, input_date: str, expected_epoch: int):
|
||||
# Test implementation
|
||||
```
|
||||
|
||||
#### Debugging information
|
||||
|
||||
**Test artifacts:**
|
||||
- **Location**: `tests/system/artifacts/` directory.
|
||||
- **Content**: automatically collected logs and system state information.
|
||||
- **Collection**: happens automatically when tests finish,
|
||||
regardless of success or failure.
|
||||
|
||||
**System state management:**
|
||||
The framework automatically manages shadow system files:
|
||||
- **Backup**: complete backup of `/etc/passwd`, `/etc/shadow`, `/etc/group`, `/etc/gshadow`, `/home`
|
||||
before tests.
|
||||
- **Restore**: automatic restoration after each test.
|
||||
- **Verification**: file mismatch detection
|
||||
to ensure unmodified files remain unchanged.
|
||||
|
||||
**Common debugging steps:**
|
||||
1. **Check container status**: ensure the `builder` container is running and accessible.
|
||||
2. **Verify artifacts**: examine collected logs in the `artifacts/` directory.
|
||||
3. **Manual testing**: access the container directly
|
||||
to reproduce issues manually.
|
||||
4. **File state**: check if unexpected file modifications caused test failures.
|
||||
|
||||
#### Troubleshooting & FAQs
|
||||
|
||||
**Common pitfalls:**
|
||||
- **Missing virtual environment**: always activate the Python virtual environment
|
||||
before running tests.
|
||||
- **Mismatched environment**: ensure your `mhc.yaml` configuration matches your testing environment.
|
||||
- **Container vs host confusion**: remember that tests run inside containers by default;
|
||||
adjust expectations accordingly.
|
||||
|
||||
**Tips for disposable environments:**
|
||||
- Use containers or VMs to avoid system state pollution.
|
||||
- Ensure proper cleanup in the framework between test runs.
|
||||
- Verify container/VM has necessary privileges for user/group operations.
|
||||
|
||||
For additional information about the testing framework,
|
||||
see the [pytest-mh documentation](https://pytest-mh.readthedocs.io).
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
#
|
||||
# Delay in seconds before being allowed another attempt after a login failure
|
||||
# Note: when PAM is used, some modules may enforce a minimum delay (e.g.
|
||||
# Note: When PAM is used, some modules may enforce a minimum delay (e.g.
|
||||
# pam_unix(8) enforces a 2s delay)
|
||||
#
|
||||
FAIL_DELAY 3
|
||||
@ -276,7 +276,7 @@ PASS_ALWAYS_WARN yes
|
||||
#
|
||||
# Number of significant characters in the password for crypt().
|
||||
# Default is 8, don't change unless your crypt() is better.
|
||||
# Only used for DES encryption algorithm.
|
||||
# Ignored if MD5_CRYPT_ENAB set to "yes".
|
||||
#
|
||||
#PASS_MAX_LEN 8
|
||||
|
||||
@ -308,7 +308,7 @@ CHFN_RESTRICT rwh
|
||||
# Set to "no" if you need to copy encrypted passwords to other systems
|
||||
# which don't understand the new algorithm. Default is "no".
|
||||
#
|
||||
# Note: if you use PAM, it is recommended to use a value consistent with
|
||||
# Note: If you use PAM, it is recommended to use a value consistent with
|
||||
# the PAM modules configuration.
|
||||
#
|
||||
# This variable is deprecated. You should use ENCRYPT_METHOD instead.
|
||||
@ -326,7 +326,7 @@ CHFN_RESTRICT rwh
|
||||
# MD5 and DES should not be used for new hashes, see crypt(5) for recommendations.
|
||||
# Overrides the MD5_CRYPT_ENAB option
|
||||
#
|
||||
# Note: if you use PAM, it is recommended to use a value consistent with
|
||||
# Note: If you use PAM, it is recommended to use a value consistent with
|
||||
# the PAM modules configuration.
|
||||
#
|
||||
#ENCRYPT_METHOD DES
|
||||
@ -467,7 +467,7 @@ PREVENT_NO_AUTH superuser
|
||||
# Used in pam_timestamp module to calculate the keyed-hash message
|
||||
# authentication code.
|
||||
#
|
||||
# Note: it is recommended to check hmac(3) to see the possible algorithms
|
||||
# Note: It is recommended to check hmac(3) to see the possible algorithms
|
||||
# that are available in your system.
|
||||
#
|
||||
#HMAC_CRYPTO_ALGO SHA512
|
||||
|
||||
@ -37,10 +37,30 @@ libshadow_la_SOURCES = \
|
||||
alloc/realloc.h \
|
||||
alloc/reallocf.c \
|
||||
alloc/reallocf.h \
|
||||
atoi/a2i.c \
|
||||
atoi/a2i.h \
|
||||
alloc/x/xcalloc.c \
|
||||
alloc/x/xcalloc.h \
|
||||
alloc/x/xmalloc.c \
|
||||
alloc/x/xmalloc.h \
|
||||
alloc/x/xrealloc.c \
|
||||
alloc/x/xrealloc.h \
|
||||
atoi/a2i/a2i.c \
|
||||
atoi/a2i/a2i.h \
|
||||
atoi/a2i/a2s.c \
|
||||
atoi/a2i/a2s.h \
|
||||
atoi/a2i/a2s_c.c \
|
||||
atoi/a2i/a2s_c.h \
|
||||
atoi/a2i/a2s_nc.c \
|
||||
atoi/a2i/a2s_nc.h \
|
||||
atoi/a2i/a2u.c \
|
||||
atoi/a2i/a2u.h \
|
||||
atoi/a2i/a2u_c.c \
|
||||
atoi/a2i/a2u_c.h \
|
||||
atoi/a2i/a2u_nc.c \
|
||||
atoi/a2i/a2u_nc.h \
|
||||
atoi/getnum.c \
|
||||
atoi/getnum.h \
|
||||
atoi/str2i.c \
|
||||
atoi/str2i.h \
|
||||
atoi/strtoi/strtoi.c \
|
||||
atoi/strtoi/strtoi.h \
|
||||
atoi/strtoi/strtou.c \
|
||||
@ -55,8 +75,6 @@ libshadow_la_SOURCES = \
|
||||
cast.h \
|
||||
chkname.c \
|
||||
chkname.h \
|
||||
chkhash.c \
|
||||
chkhash.h \
|
||||
chowndir.c \
|
||||
chowntty.c \
|
||||
cleanup.c \
|
||||
@ -70,8 +88,6 @@ libshadow_la_SOURCES = \
|
||||
defines.h \
|
||||
encrypt.c \
|
||||
env.c \
|
||||
exit_if_null.c \
|
||||
exit_if_null.h \
|
||||
exitcodes.h \
|
||||
faillog.h \
|
||||
failure.c \
|
||||
@ -83,6 +99,7 @@ libshadow_la_SOURCES = \
|
||||
find_new_uid.c \
|
||||
find_new_sub_gids.c \
|
||||
find_new_sub_uids.c \
|
||||
fputsx.c \
|
||||
fs/mkstemp/fmkomstemp.c \
|
||||
fs/mkstemp/fmkomstemp.h \
|
||||
fs/mkstemp/mkomstemp.c \
|
||||
@ -100,6 +117,7 @@ libshadow_la_SOURCES = \
|
||||
groupio.c \
|
||||
groupmem.c \
|
||||
groupio.h \
|
||||
gshadow.c \
|
||||
hushed.c \
|
||||
idmapping.h \
|
||||
idmapping.c \
|
||||
@ -147,38 +165,18 @@ libshadow_la_SOURCES = \
|
||||
semanage.c \
|
||||
setugid.c \
|
||||
setupenv.c \
|
||||
sgetgrent.c \
|
||||
sgetpwent.c \
|
||||
sgetspent.c \
|
||||
sgroupio.c \
|
||||
sgroupio.h \
|
||||
shadow/group/sgetgrent.c \
|
||||
shadow/group/sgetgrent.h \
|
||||
sgroupio.h\
|
||||
shadow/grp/agetgroups.c \
|
||||
shadow/grp/agetgroups.h \
|
||||
shadow/gshadow/endsgent.c \
|
||||
shadow/gshadow/endsgent.h \
|
||||
shadow/gshadow/fgetsgent.c \
|
||||
shadow/gshadow/fgetsgent.h \
|
||||
shadow/gshadow/getsgent.c \
|
||||
shadow/gshadow/getsgent.h \
|
||||
shadow/gshadow/getsgnam.c \
|
||||
shadow/gshadow/getsgnam.h \
|
||||
shadow/gshadow/gshadow.c \
|
||||
shadow/gshadow/gshadow.h \
|
||||
shadow/gshadow/putsgent.c \
|
||||
shadow/gshadow/putsgent.h \
|
||||
shadow/gshadow/setsgent.c \
|
||||
shadow/gshadow/setsgent.h \
|
||||
shadow/gshadow/sgetsgent.c \
|
||||
shadow/gshadow/sgetsgent.h \
|
||||
shadow/gshadow/sgrp.c \
|
||||
shadow/gshadow/sgrp.h \
|
||||
shadow/passwd/sgetpwent.c \
|
||||
shadow/passwd/sgetpwent.h \
|
||||
shadow/shadow/sgetspent.c \
|
||||
shadow/shadow/sgetspent.h \
|
||||
shadowio.c \
|
||||
shadowio.h \
|
||||
shadowlog.c \
|
||||
shadowlog.h \
|
||||
shadowlog_internal.h \
|
||||
shadowmem.c \
|
||||
shell.c \
|
||||
sizeof.h \
|
||||
@ -201,6 +199,8 @@ libshadow_la_SOURCES = \
|
||||
string/sprintf/snprintf.h \
|
||||
string/sprintf/stpeprintf.c \
|
||||
string/sprintf/stpeprintf.h \
|
||||
string/sprintf/xaprintf.c \
|
||||
string/sprintf/xaprintf.h \
|
||||
string/strchr/strchrcnt.c \
|
||||
string/strchr/strchrcnt.h \
|
||||
string/strchr/strchrscnt.c \
|
||||
@ -213,8 +213,6 @@ libshadow_la_SOURCES = \
|
||||
string/strcmp/strcaseprefix.h \
|
||||
string/strcmp/streq.c \
|
||||
string/strcmp/streq.h \
|
||||
string/strcmp/strneq.c \
|
||||
string/strcmp/strneq.h \
|
||||
string/strcmp/strprefix.c \
|
||||
string/strcmp/strprefix.h \
|
||||
string/strcpy/stpecpy.c \
|
||||
@ -225,14 +223,12 @@ libshadow_la_SOURCES = \
|
||||
string/strcpy/strncpy.h \
|
||||
string/strcpy/strtcpy.c \
|
||||
string/strcpy/strtcpy.h \
|
||||
string/strdup/strdup.c \
|
||||
string/strdup/strdup.h \
|
||||
string/strdup/strndupa.c \
|
||||
string/strdup/strndupa.h \
|
||||
string/strdup/strndup.c \
|
||||
string/strdup/strndup.h \
|
||||
string/strerrno.c \
|
||||
string/strerrno.h \
|
||||
string/strdup/xstrdup.c \
|
||||
string/strdup/xstrdup.h \
|
||||
string/strdup/xstrndup.c \
|
||||
string/strdup/xstrndup.h \
|
||||
string/strftime.c \
|
||||
string/strftime.h \
|
||||
string/strspn/stpspn.c \
|
||||
@ -253,6 +249,8 @@ libshadow_la_SOURCES = \
|
||||
string/strtok/strsep2arr.h \
|
||||
string/strtok/strsep2ls.c \
|
||||
string/strtok/strsep2ls.h \
|
||||
string/strtok/xastrsep2ls.c \
|
||||
string/strtok/xastrsep2ls.h \
|
||||
strtoday.c \
|
||||
sub.c \
|
||||
subordinateio.h \
|
||||
@ -308,4 +306,5 @@ endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
.indent.pro \
|
||||
gshadow_.h \
|
||||
xgetXXbyYY.c
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#if !defined(USE_PAM)
|
||||
|
||||
@ -24,8 +24,6 @@
|
||||
#include "shadow/grp/agetgroups.h"
|
||||
#include "shadowlog.h"
|
||||
#include "string/strchr/strchrscnt.h"
|
||||
#include "string/strcmp/streq.h"
|
||||
#include "string/strerrno.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -36,7 +34,8 @@
|
||||
int
|
||||
add_groups(const char *list)
|
||||
{
|
||||
char *dup;
|
||||
char *g, *p, *dup;
|
||||
FILE *shadow_logfd = log_get_logfd();
|
||||
gid_t *gids;
|
||||
size_t n;
|
||||
|
||||
@ -44,34 +43,29 @@ add_groups(const char *list)
|
||||
if (gids == NULL)
|
||||
return -1;
|
||||
|
||||
gids = reallocf_T(gids, n + strchrscnt(list, ",:") + 1, gid_t);
|
||||
gids = REALLOCF(gids, n + strchrscnt(list, ",:") + 1, gid_t);
|
||||
if (gids == NULL)
|
||||
return -1;
|
||||
|
||||
dup = strdup(list);
|
||||
p = dup = strdup(list);
|
||||
if (dup == NULL)
|
||||
goto free_gids;
|
||||
|
||||
if (!streq(dup, "")) {
|
||||
char *g, *p;
|
||||
while (NULL != (g = strsep(&p, ",:"))) {
|
||||
struct group *grp;
|
||||
|
||||
p = dup;
|
||||
while (NULL != (g = strsep(&p, ",:"))) {
|
||||
struct group *grp;
|
||||
|
||||
grp = getgrnam(g); /* local, no need for xgetgrnam */
|
||||
if (NULL == grp) {
|
||||
fprintf(log_get_logfd(), _("Warning: unknown group %s\n"), g);
|
||||
continue;
|
||||
}
|
||||
|
||||
LSEARCH(gid_t, &grp->gr_gid, gids, &n);
|
||||
grp = getgrnam(g); /* local, no need for xgetgrnam */
|
||||
if (NULL == grp) {
|
||||
fprintf(shadow_logfd, _("Warning: unknown group %s\n"), g);
|
||||
continue;
|
||||
}
|
||||
|
||||
LSEARCH(&grp->gr_gid, gids, &n);
|
||||
}
|
||||
free(dup);
|
||||
|
||||
if (setgroups(n, gids) == -1) {
|
||||
fprintf(log_get_logfd(), "setgroups: %s\n", strerrno());
|
||||
fprintf(shadow_logfd, "setgroups: %s\n", strerror(errno));
|
||||
goto free_gids;
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "adds.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_ADDS_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
@ -55,7 +55,7 @@ addslN(size_t n, long addend[n])
|
||||
|
||||
e = errno;
|
||||
while (n > 1) {
|
||||
QSORT(long, addend, n);
|
||||
QSORT(addend, n);
|
||||
|
||||
errno = 0;
|
||||
addend[0] = addsl2(addend[0], addend[--n]);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
@ -20,7 +20,6 @@
|
||||
#include "defines.h"
|
||||
#include "exitcodes.h"
|
||||
#include "prototypes.h"
|
||||
#include "shadow/gshadow/endsgent.h"
|
||||
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "agetpass.h"
|
||||
|
||||
@ -106,7 +106,7 @@ agetpass_internal(const char *prompt, int flags)
|
||||
* Let's add one more byte, and if the password uses it, it
|
||||
* means the introduced password was longer than PASS_MAX.
|
||||
*/
|
||||
pass = malloc_T(PASS_MAX + 2, char);
|
||||
pass = MALLOC(PASS_MAX + 2, char);
|
||||
if (pass == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -135,7 +135,7 @@ agetpass(const char *prompt)
|
||||
char *
|
||||
agetpass_stdin()
|
||||
{
|
||||
return agetpass_internal("", RPP_STDIN);
|
||||
return agetpass_internal(NULL, RPP_STDIN);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_AGETPASS_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "attr.h"
|
||||
#include "defines.h"
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/calloc.h"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
@ -6,24 +6,15 @@
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exit_if_null.h"
|
||||
#include "sizeof.h"
|
||||
|
||||
|
||||
// calloc_T - calloc type-safe
|
||||
#define calloc_T(n, T) calloc_T_(n, typeas(T))
|
||||
#define calloc_T_(n, T) \
|
||||
({ \
|
||||
(T *){calloc(n, sizeof(T))}; \
|
||||
})
|
||||
|
||||
|
||||
// xcalloc_T - exit-on-error calloc type-safe
|
||||
#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T))
|
||||
#define CALLOC(n, type) \
|
||||
( \
|
||||
(type *) calloc(n, sizeof(type)) \
|
||||
)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/malloc.h"
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
@ -6,28 +6,19 @@
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "attr.h"
|
||||
#include "exit_if_null.h"
|
||||
#include "sizeof.h"
|
||||
|
||||
|
||||
// malloc_T - malloc type-safe
|
||||
#define malloc_T(n, T) malloc_T_(n, typeas(T))
|
||||
#define malloc_T_(n, T) \
|
||||
({ \
|
||||
(T *){mallocarray(n, sizeof(T))}; \
|
||||
})
|
||||
#define MALLOC(n, type) \
|
||||
( \
|
||||
(type *) mallocarray(n, sizeof(type)) \
|
||||
)
|
||||
|
||||
|
||||
// xmalloc_T - exit-on-error malloc type-safe
|
||||
#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T))
|
||||
|
||||
|
||||
// mallocarray - malloc array
|
||||
ATTR_ALLOC_SIZE(1, 2)
|
||||
ATTR_MALLOC(free)
|
||||
inline void *mallocarray(size_t nmemb, size_t size);
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/realloc.h"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
@ -6,27 +6,15 @@
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exit_if_null.h"
|
||||
#include "sizeof.h"
|
||||
|
||||
|
||||
// realloc_T - realloc type-safe
|
||||
#define realloc_T(p, n, T) realloc_T_(p, n, typeas(T))
|
||||
#define realloc_T_(p, n, T) \
|
||||
({ \
|
||||
_Generic(p, T *: (void)0); \
|
||||
(T *){reallocarray_(p, n, sizeof(T))}; \
|
||||
})
|
||||
|
||||
#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1)
|
||||
|
||||
|
||||
// xrealloc_T - exit-on-error realloc type-safe
|
||||
#define xrealloc_T(p, n, T) exit_if_null(realloc_T(p, n, T))
|
||||
#define REALLOC(p, n, type) \
|
||||
( \
|
||||
_Generic(p, type *: (type *) reallocarray(p, (n) ?: 1, sizeof(type))) \
|
||||
)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/reallocf.h"
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
@ -6,27 +6,20 @@
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "attr.h"
|
||||
#include "sizeof.h"
|
||||
|
||||
|
||||
// reallocf_T - realloc free-on-error type-safe
|
||||
#define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T))
|
||||
#define reallocf_T_(p, n, T) \
|
||||
({ \
|
||||
_Generic(p, T *: (void)0); \
|
||||
(T *){reallocarrayf_(p, n, sizeof(T))}; \
|
||||
})
|
||||
|
||||
#define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1)
|
||||
#define REALLOCF(p, n, type) \
|
||||
( \
|
||||
_Generic(p, type *: (type *) reallocarrayf(p, (n) ?: 1, sizeof(type)))\
|
||||
)
|
||||
|
||||
|
||||
// reallocarrayf - realloc array free-on-error
|
||||
ATTR_ALLOC_SIZE(2, 3)
|
||||
ATTR_MALLOC(free)
|
||||
inline void *reallocarrayf(void *p, size_t nmemb, size_t size);
|
||||
|
||||
36
lib/alloc/x/xcalloc.c
Normal file
36
lib/alloc/x/xcalloc.c
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
|
||||
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
|
||||
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
|
||||
// SPDX-FileCopyrightText: 2008 , Nicolas François
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/x/xcalloc.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "shadowlog.h"
|
||||
|
||||
|
||||
void *
|
||||
xcalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = calloc(nmemb, size);
|
||||
if (p == NULL)
|
||||
goto x;
|
||||
|
||||
return p;
|
||||
|
||||
x:
|
||||
fprintf(log_get_logfd(), _("%s: %s\n"),
|
||||
log_get_progname(), strerror(errno));
|
||||
exit(13);
|
||||
}
|
||||
28
lib/alloc/x/xcalloc.h
Normal file
28
lib/alloc/x/xcalloc.h
Normal file
@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_X_XCALLOC_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
#define XCALLOC(n, type) \
|
||||
( \
|
||||
(type *) xcalloc(n, sizeof(type)) \
|
||||
)
|
||||
|
||||
|
||||
ATTR_ALLOC_SIZE(1, 2)
|
||||
ATTR_MALLOC(free)
|
||||
void *xcalloc(size_t nmemb, size_t size);
|
||||
|
||||
|
||||
#endif // include guard
|
||||
16
lib/alloc/x/xmalloc.c
Normal file
16
lib/alloc/x/xmalloc.c
Normal file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
|
||||
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
|
||||
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
|
||||
// SPDX-FileCopyrightText: 2008 , Nicolas François
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/x/xmalloc.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
extern inline void *xmallocarray(size_t nmemb, size_t size);
|
||||
35
lib/alloc/x/xmalloc.h
Normal file
35
lib/alloc/x/xmalloc.h
Normal file
@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
|
||||
#define SHADOW_INCLUDE_LIB_ALLOC_X_XMALLOC_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "alloc/x/xrealloc.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
#define XMALLOC(n, type) \
|
||||
( \
|
||||
(type *) xmallocarray(n, sizeof(type)) \
|
||||
)
|
||||
|
||||
|
||||
ATTR_ALLOC_SIZE(1, 2)
|
||||
ATTR_MALLOC(free)
|
||||
inline void *xmallocarray(size_t nmemb, size_t size);
|
||||
|
||||
|
||||
inline void *
|
||||
xmallocarray(size_t nmemb, size_t size)
|
||||
{
|
||||
return xreallocarray(NULL, nmemb, size);
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
35
lib/alloc/x/xrealloc.c
Normal file
35
lib/alloc/x/xrealloc.c
Normal file
@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh
|
||||
// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz
|
||||
// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko
|
||||
// SPDX-FileCopyrightText: 2008 , Nicolas François
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "alloc/x/xrealloc.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc/reallocf.h"
|
||||
#include "defines.h"
|
||||
#include "shadowlog.h"
|
||||
|
||||
|
||||
void *
|
||||
xreallocarray(void *p, size_t nmemb, size_t size)
|
||||
{
|
||||
p = reallocarrayf(p, nmemb, size);
|
||||
if (p == NULL)
|
||||
goto x;
|
||||
|
||||
return p;
|
||||
|
||||
x:
|
||||
fprintf(log_get_logfd(), _("%s: %s\n"),
|
||||
log_get_progname(), strerror(errno));
|
||||
exit(13);
|
||||
}
|
||||
31
lib/alloc/x/xrealloc.h
Normal file
31
lib/alloc/x/xrealloc.h
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_MALLOC_H_
|
||||
#define SHADOW_INCLUDE_LIB_MALLOC_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
#define XREALLOC(ptr, n, type) \
|
||||
( \
|
||||
_Generic(ptr, type *: (type *) xreallocarray(ptr, n, sizeof(type))) \
|
||||
)
|
||||
|
||||
|
||||
ATTR_ALLOC_SIZE(2, 3)
|
||||
ATTR_MALLOC(free)
|
||||
void *xreallocarray(void *p, size_t nmemb, size_t size);
|
||||
|
||||
|
||||
#endif // include guard
|
||||
@ -1,69 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "atoi/strtoi/strtoi.h"
|
||||
#include "atoi/strtoi/strtou_noneg.h"
|
||||
#include "typetraits.h"
|
||||
|
||||
|
||||
// a2i - alpha to integer
|
||||
#define a2i(T, n, s, endp, base, min, max) \
|
||||
({ \
|
||||
T *n_ = n; \
|
||||
QChar_of(s) **endp_ = endp; \
|
||||
T min_ = min; \
|
||||
T max_ = max; \
|
||||
\
|
||||
int status; \
|
||||
\
|
||||
*n_ = _Generic((T){0}, \
|
||||
short: strtoi_, \
|
||||
int: strtoi_, \
|
||||
long: strtoi_, \
|
||||
long long: strtoi_, \
|
||||
unsigned short: strtou_noneg, \
|
||||
unsigned int: strtou_noneg, \
|
||||
unsigned long: strtou_noneg, \
|
||||
unsigned long long: strtou_noneg \
|
||||
)(s, (char **) endp_, base, min_, max_, &status); \
|
||||
\
|
||||
if (status != 0) \
|
||||
errno = status; \
|
||||
-!!status; \
|
||||
})
|
||||
|
||||
|
||||
#define a2sh(...) a2i(short, __VA_ARGS__)
|
||||
#define a2si(...) a2i(int, __VA_ARGS__)
|
||||
#define a2sl(...) a2i(long, __VA_ARGS__)
|
||||
#define a2sll(...) a2i(long long, __VA_ARGS__)
|
||||
|
||||
#define a2uh(...) a2i(unsigned short, __VA_ARGS__)
|
||||
#define a2ui(...) a2i(unsigned int, __VA_ARGS__)
|
||||
#define a2ul(...) a2i(unsigned long, __VA_ARGS__)
|
||||
#define a2ull(...) a2i(unsigned long long, __VA_ARGS__)
|
||||
|
||||
#define str2i(T, ...) a2i(T, __VA_ARGS__, NULL, 0, type_min(T), type_max(T))
|
||||
|
||||
#define str2sh(...) str2i(short, __VA_ARGS__)
|
||||
#define str2si(...) str2i(int, __VA_ARGS__)
|
||||
#define str2sl(...) str2i(long, __VA_ARGS__)
|
||||
#define str2sll(...) str2i(long long, __VA_ARGS__)
|
||||
|
||||
#define str2uh(...) str2i(unsigned short, __VA_ARGS__)
|
||||
#define str2ui(...) str2i(unsigned int, __VA_ARGS__)
|
||||
#define str2ul(...) str2i(unsigned long, __VA_ARGS__)
|
||||
#define str2ull(...) str2i(unsigned long long, __VA_ARGS__)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
@ -2,6 +2,6 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "string/strdup/strdup.h"
|
||||
#include "atoi/a2i/a2i.h"
|
||||
62
lib/atoi/a2i/a2i.h
Normal file
62
lib/atoi/a2i/a2i.h
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2I_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2s_c.h"
|
||||
#include "atoi/a2i/a2s_nc.h"
|
||||
#include "atoi/a2i/a2u_c.h"
|
||||
#include "atoi/a2i/a2u_nc.h"
|
||||
|
||||
|
||||
/*
|
||||
* See the manual of these macros in liba2i's documentation:
|
||||
* <http://www.alejandro-colomar.es/share/dist/liba2i/git/HEAD/liba2i-HEAD.pdf>
|
||||
*/
|
||||
|
||||
|
||||
#define a2i(TYPE, n, s, ...) \
|
||||
( \
|
||||
_Generic((void (*)(TYPE, typeof(s))) 0, \
|
||||
void (*)(short, const char *): a2sh_c, \
|
||||
void (*)(short, const void *): a2sh_c, \
|
||||
void (*)(short, char *): a2sh_nc, \
|
||||
void (*)(short, void *): a2sh_nc, \
|
||||
void (*)(int, const char *): a2si_c, \
|
||||
void (*)(int, const void *): a2si_c, \
|
||||
void (*)(int, char *): a2si_nc, \
|
||||
void (*)(int, void *): a2si_nc, \
|
||||
void (*)(long, const char *): a2sl_c, \
|
||||
void (*)(long, const void *): a2sl_c, \
|
||||
void (*)(long, char *): a2sl_nc, \
|
||||
void (*)(long, void *): a2sl_nc, \
|
||||
void (*)(long long, const char *): a2sll_c, \
|
||||
void (*)(long long, const void *): a2sll_c, \
|
||||
void (*)(long long, char *): a2sll_nc, \
|
||||
void (*)(long long, void *): a2sll_nc, \
|
||||
void (*)(unsigned short, const char *): a2uh_c, \
|
||||
void (*)(unsigned short, const void *): a2uh_c, \
|
||||
void (*)(unsigned short, char *): a2uh_nc, \
|
||||
void (*)(unsigned short, void *): a2uh_nc, \
|
||||
void (*)(unsigned int, const char *): a2ui_c, \
|
||||
void (*)(unsigned int, const void *): a2ui_c, \
|
||||
void (*)(unsigned int, char *): a2ui_nc, \
|
||||
void (*)(unsigned int, void *): a2ui_nc, \
|
||||
void (*)(unsigned long, const char *): a2ul_c, \
|
||||
void (*)(unsigned long, const void *): a2ul_c, \
|
||||
void (*)(unsigned long, char *): a2ul_nc, \
|
||||
void (*)(unsigned long, void *): a2ul_nc, \
|
||||
void (*)(unsigned long long, const char *): a2ull_c, \
|
||||
void (*)(unsigned long long, const void *): a2ull_c, \
|
||||
void (*)(unsigned long long, char *): a2ull_nc, \
|
||||
void (*)(unsigned long long, void *): a2ull_nc \
|
||||
)(n, s, __VA_ARGS__) \
|
||||
)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
7
lib/atoi/a2i/a2s.c
Normal file
7
lib/atoi/a2i/a2s.c
Normal file
@ -0,0 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2s.h"
|
||||
20
lib/atoi/a2i/a2s.h
Normal file
20
lib/atoi/a2i/a2s.h
Normal file
@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2i.h"
|
||||
|
||||
|
||||
#define a2sh(...) a2i(short, __VA_ARGS__)
|
||||
#define a2si(...) a2i(int, __VA_ARGS__)
|
||||
#define a2sl(...) a2i(long, __VA_ARGS__)
|
||||
#define a2sll(...) a2i(long long, __VA_ARGS__)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
17
lib/atoi/a2i/a2s_c.c
Normal file
17
lib/atoi/a2i/a2s_c.c
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2s_c.h"
|
||||
|
||||
|
||||
extern inline int a2sh_c(short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, short min, short max);
|
||||
extern inline int a2si_c(int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, int min, int max);
|
||||
extern inline int a2sl_c(long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long min, long max);
|
||||
extern inline int a2sll_c(long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long long min, long long max);
|
||||
64
lib/atoi/a2i/a2s_c.h
Normal file
64
lib/atoi/a2i/a2s_c.h
Normal file
@ -0,0 +1,64 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_C_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "atoi/a2i/a2s_nc.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sh_c(short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, short min, short max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2si_c(int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, int min, int max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sl_c(long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long min, long max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sll_c(long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long long min, long long max);
|
||||
|
||||
|
||||
inline int
|
||||
a2sh_c(short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, short min, short max)
|
||||
{
|
||||
return a2sh_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2si_c(int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, int min, int max)
|
||||
{
|
||||
return a2si_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2sl_c(long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long min, long max)
|
||||
{
|
||||
return a2sl_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2sll_c(long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, long long min, long long max)
|
||||
{
|
||||
return a2sll_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
17
lib/atoi/a2i/a2s_nc.c
Normal file
17
lib/atoi/a2i/a2s_nc.c
Normal file
@ -0,0 +1,17 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2s_nc.h"
|
||||
|
||||
|
||||
extern inline int a2sh_nc(short *restrict n, char *s,
|
||||
char **restrict endp, int base, short min, short max);
|
||||
extern inline int a2si_nc(int *restrict n, char *s,
|
||||
char **restrict endp, int base, int min, int max);
|
||||
extern inline int a2sl_nc(long *restrict n, char *s,
|
||||
char **restrict endp, int base, long min, long max);
|
||||
extern inline int a2sll_nc(long long *restrict n, char *s,
|
||||
char **restrict endp, int base, long long min, long long max);
|
||||
91
lib/atoi/a2i/a2s_nc.h
Normal file
91
lib/atoi/a2i/a2s_nc.h
Normal file
@ -0,0 +1,91 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2S_NC_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "atoi/strtoi/strtoi.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sh_nc(short *restrict n, char *s,
|
||||
char **restrict endp, int base, short min, short max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2si_nc(int *restrict n, char *s,
|
||||
char **restrict endp, int base, int min, int max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sl_nc(long *restrict n, char *s,
|
||||
char **restrict endp, int base, long min, long max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2sll_nc(long long *restrict n, char *s,
|
||||
char **restrict endp, int base, long long min, long long max);
|
||||
|
||||
|
||||
inline int
|
||||
a2sh_nc(short *restrict n, char *s,
|
||||
char **restrict endp, int base, short min, short max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtoi_(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2si_nc(int *restrict n, char *s,
|
||||
char **restrict endp, int base, int min, int max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtoi_(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2sl_nc(long *restrict n, char *s,
|
||||
char **restrict endp, int base, long min, long max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtoi_(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2sll_nc(long long *restrict n, char *s,
|
||||
char **restrict endp, int base, long long min, long long max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtoi_(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
7
lib/atoi/a2i/a2u.c
Normal file
7
lib/atoi/a2i/a2u.c
Normal file
@ -0,0 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2u.h"
|
||||
20
lib/atoi/a2i/a2u.h
Normal file
20
lib/atoi/a2i/a2u.h
Normal file
@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2i.h"
|
||||
|
||||
|
||||
#define a2uh(...) a2i(unsigned short, __VA_ARGS__)
|
||||
#define a2ui(...) a2i(unsigned int, __VA_ARGS__)
|
||||
#define a2ul(...) a2i(unsigned long, __VA_ARGS__)
|
||||
#define a2ull(...) a2i(unsigned long long, __VA_ARGS__)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
19
lib/atoi/a2i/a2u_c.c
Normal file
19
lib/atoi/a2i/a2u_c.c
Normal file
@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2u_c.h"
|
||||
|
||||
|
||||
extern inline int a2uh_c(unsigned short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned short min,
|
||||
unsigned short max);
|
||||
extern inline int a2ui_c(unsigned int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned int min, unsigned int max);
|
||||
extern inline int a2ul_c(unsigned long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long min, unsigned long max);
|
||||
extern inline int a2ull_c(unsigned long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max);
|
||||
65
lib/atoi/a2i/a2u_c.h
Normal file
65
lib/atoi/a2i/a2u_c.h
Normal file
@ -0,0 +1,65 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_C_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2u_nc.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2uh_c(unsigned short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned short min,
|
||||
unsigned short max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ui_c(unsigned int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned int min, unsigned int max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ul_c(unsigned long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long min, unsigned long max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ull_c(unsigned long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max);
|
||||
|
||||
|
||||
inline int
|
||||
a2uh_c(unsigned short *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned short min,
|
||||
unsigned short max)
|
||||
{
|
||||
return a2uh_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ui_c(unsigned int *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned int min, unsigned int max)
|
||||
{
|
||||
return a2ui_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ul_c(unsigned long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long min, unsigned long max)
|
||||
{
|
||||
return a2ul_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ull_c(unsigned long long *restrict n, const char *s,
|
||||
const char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max)
|
||||
{
|
||||
return a2ull_nc(n, (char *) s, (char **) endp, base, min, max);
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
18
lib/atoi/a2i/a2u_nc.c
Normal file
18
lib/atoi/a2i/a2u_nc.c
Normal file
@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i/a2u_nc.h"
|
||||
|
||||
|
||||
extern inline int a2uh_nc(unsigned short *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned short min, unsigned short max);
|
||||
extern inline int a2ui_nc(unsigned int *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned int min, unsigned int max);
|
||||
extern inline int a2ul_nc(unsigned long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long min, unsigned long max);
|
||||
extern inline int a2ull_nc(unsigned long long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max);
|
||||
94
lib/atoi/a2i/a2u_nc.h
Normal file
94
lib/atoi/a2i/a2u_nc.h
Normal file
@ -0,0 +1,94 @@
|
||||
// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_A2I_A2U_NC_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "atoi/strtoi/strtou_noneg.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2uh_nc(unsigned short *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned short min, unsigned short max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ui_nc(unsigned int *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned int min, unsigned int max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ul_nc(unsigned long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long min, unsigned long max);
|
||||
ATTR_STRING(2) ATTR_ACCESS(write_only, 1) ATTR_ACCESS(write_only, 3)
|
||||
inline int a2ull_nc(unsigned long long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max);
|
||||
|
||||
|
||||
inline int
|
||||
a2uh_nc(unsigned short *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned short min,
|
||||
unsigned short max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtou_noneg(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ui_nc(unsigned int *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned int min, unsigned int max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtou_noneg(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ul_nc(unsigned long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long min, unsigned long max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtou_noneg(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
a2ull_nc(unsigned long long *restrict n, char *s,
|
||||
char **restrict endp, int base, unsigned long long min,
|
||||
unsigned long long max)
|
||||
{
|
||||
int status;
|
||||
|
||||
*n = strtou_noneg(s, endp, base, min, max, &status);
|
||||
if (status != 0) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
@ -3,7 +3,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
@ -7,13 +7,14 @@
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_GETNUM_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "atoi/a2i.h"
|
||||
#include "atoi/a2i/a2i.h"
|
||||
#include "atoi/a2i/a2s.h"
|
||||
#include "attr.h"
|
||||
#include "typetraits.h"
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/a2i.h"
|
||||
#include "atoi/str2i.h"
|
||||
31
lib/atoi/str2i.h
Normal file
31
lib/atoi/str2i.h
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2007-2009, Nicolas François
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_ATOI_STR2I_H_
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_STR2I_H_
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "atoi/a2i/a2i.h"
|
||||
#include "typetraits.h"
|
||||
|
||||
|
||||
#define str2i(T, ...) a2i(T, __VA_ARGS__, NULL, 0, type_min(T), type_max(T))
|
||||
|
||||
#define str2sh(...) str2i(short, __VA_ARGS__)
|
||||
#define str2si(...) str2i(int, __VA_ARGS__)
|
||||
#define str2sl(...) str2i(long, __VA_ARGS__)
|
||||
#define str2sll(...) str2i(long long, __VA_ARGS__)
|
||||
|
||||
#define str2uh(...) str2i(unsigned short, __VA_ARGS__)
|
||||
#define str2ui(...) str2i(unsigned int, __VA_ARGS__)
|
||||
#define str2ul(...) str2i(unsigned long, __VA_ARGS__)
|
||||
#define str2ull(...) str2i(unsigned long long, __VA_ARGS__)
|
||||
|
||||
|
||||
#endif // include guard
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/strtoi/strtoi.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOI_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/strtoi/strtou.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "atoi/strtoi/strtou_noneg.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_ATOI_STRTOI_STRTOU_NONEG_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
43
lib/attr.h
43
lib/attr.h
@ -5,38 +5,17 @@
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#if !defined(__has_c_attribute)
|
||||
# define __has_c_attribute(x) 0
|
||||
#endif
|
||||
|
||||
|
||||
#if __has_c_attribute(maybe_unused)
|
||||
# define MAYBE_UNUSED [[maybe_unused]]
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(noreturn)
|
||||
# define NORETURN [[noreturn]]
|
||||
#else
|
||||
# define NORETURN
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(gnu::format)
|
||||
#if (__GNUC__ >= 10)
|
||||
# define MAYBE_UNUSED [[gnu::unused]]
|
||||
# define NORETURN [[gnu::__noreturn__]]
|
||||
# define format_attr(type, fmt, va) [[gnu::format(type, fmt, va)]]
|
||||
#else
|
||||
# define format_attr(type, fmt, va)
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(gnu::access)
|
||||
# define ATTR_ACCESS(...) [[gnu::access(__VA_ARGS__)]]
|
||||
#else
|
||||
# define ATTR_ACCESS(...)
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(gnu::alloc_size)
|
||||
# define ATTR_ALLOC_SIZE(...) [[gnu::alloc_size(__VA_ARGS__)]]
|
||||
#else
|
||||
# define MAYBE_UNUSED
|
||||
# define NORETURN
|
||||
# define format_attr(type, fmt, va)
|
||||
# define ATTR_ACCESS(...)
|
||||
# define ATTR_ALLOC_SIZE(...)
|
||||
#endif
|
||||
|
||||
@ -46,17 +25,11 @@
|
||||
# define ATTR_MALLOC(deallocator)
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(gnu::null_terminated_string_arg)
|
||||
#if (__GNUC__ >= 14)
|
||||
# define ATTR_STRING(i) [[gnu::null_terminated_string_arg(i)]]
|
||||
#else
|
||||
# define ATTR_STRING(i)
|
||||
#endif
|
||||
|
||||
#if __has_c_attribute(gnu::nonstring)
|
||||
# define ATTR_NONSTRING [[gnu::nonstring]]
|
||||
#else
|
||||
# define ATTR_NONSTRING
|
||||
#endif
|
||||
|
||||
|
||||
#endif // include guard
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ifdef WITH_AUDIT
|
||||
|
||||
@ -56,12 +56,13 @@ void audit_help_open (void)
|
||||
*
|
||||
* type - type of message. A list of possible values is available in
|
||||
* "audit-records.h" file.
|
||||
* pgname - program's name
|
||||
* op - operation. "adding user", "changing finger info", "deleting group"
|
||||
* name - user's account or group name. If not available use NULL.
|
||||
* id - uid or gid that the operation is being performed on. This is used
|
||||
* only when user is NULL.
|
||||
*/
|
||||
void audit_logger (int type, const char *op,
|
||||
void audit_logger (int type, MAYBE_UNUSED const char *pgname, const char *op,
|
||||
const char *name, unsigned int id,
|
||||
shadow_audit_result result)
|
||||
{
|
||||
@ -104,10 +105,10 @@ audit_logger_with_group(int type, const char *op, const char *name,
|
||||
|
||||
len = strnlen(grp, sizeof(enc_group)/2);
|
||||
if (audit_value_needs_encoding(grp, len)) {
|
||||
stprintf_a(buf, "%s %s=%s", op, grp_type,
|
||||
SNPRINTF(buf, "%s %s=%s", op, grp_type,
|
||||
audit_encode_value(enc_group, grp, len));
|
||||
} else {
|
||||
stprintf_a(buf, "%s %s=\"%s\"", op, grp_type, grp);
|
||||
SNPRINTF(buf, "%s %s=\"%s\"", op, grp_type, grp);
|
||||
}
|
||||
|
||||
audit_log_acct_message(audit_fd, type, NULL, buf, name, id,
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
* --marekm
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_BIT_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_CAST_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#define const_cast(T, p) _Generic(p, const T: (T) (p))
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "chkhash.h"
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "string/strcmp/streq.h"
|
||||
#include "string/strcmp/strprefix.h"
|
||||
|
||||
|
||||
/*
|
||||
* match_regex - return true if match, false if not
|
||||
*/
|
||||
bool
|
||||
match_regex(const char *pattern, const char *string)
|
||||
{
|
||||
regex_t regex;
|
||||
int result;
|
||||
|
||||
if (regcomp(®ex, pattern, REG_EXTENDED) != 0)
|
||||
return false;
|
||||
|
||||
result = regexec(®ex, string, 0, NULL, 0);
|
||||
regfree(®ex);
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* is_valid_hash - check if the string is a valid shadow(5) 2nd field.
|
||||
*
|
||||
* regex from: https://man.archlinux.org/man/crypt.5.en
|
||||
*/
|
||||
bool
|
||||
is_valid_hash(const char *hash)
|
||||
{
|
||||
// Password temporarily locked
|
||||
hash = strprefix(hash, "!") ?: hash;
|
||||
|
||||
// Passwordless account; discouraged
|
||||
if (streq(hash, ""))
|
||||
return true;
|
||||
|
||||
// Password permanently locked (and forgotten)
|
||||
if (streq(hash, "*"))
|
||||
return true;
|
||||
|
||||
// Minimum hash length
|
||||
if (strlen(hash) < 13)
|
||||
return false;
|
||||
|
||||
// Yescrypt: $y$ + algorithm parameters + $ + salt + $ + 43-char (minimum) hash
|
||||
if (match_regex("^\\$y\\$[./A-Za-z0-9]+\\$[./A-Za-z0-9]{1,86}\\$[./A-Za-z0-9]{43}$", hash))
|
||||
return true;
|
||||
|
||||
// Bcrypt: $2[abxy]$ + 2-digit cost + $ + 53-char hash
|
||||
if (match_regex("^\\$2[abxy]\\$[0-9]{2}\\$[./A-Za-z0-9]{53}$", hash))
|
||||
return true;
|
||||
|
||||
// SHA-512: $6$ + salt + $ + 86-char hash
|
||||
if (match_regex("^\\$6\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{86}$", hash))
|
||||
return true;
|
||||
|
||||
// SHA-256: $5$ + salt + $ + 43-char hash
|
||||
if (match_regex("^\\$5\\$(rounds=[1-9][0-9]{3,8}\\$)?[^$:\\n]{1,16}\\$[./A-Za-z0-9]{43}$", hash))
|
||||
return true;
|
||||
|
||||
// MD5: $1$ + salt + $ + 22-char hash
|
||||
if (match_regex("^\\$1\\$[^$:\\n]{1,8}\\$[./A-Za-z0-9]{22}$", hash))
|
||||
return true;
|
||||
|
||||
// DES: exactly 13 characters from [A-Za-z0-9./]
|
||||
if (match_regex("^[./A-Za-z0-9]{13}$", hash))
|
||||
return true;
|
||||
|
||||
// Not a valid hash
|
||||
return false;
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
#ifndef SHADOW_INCLUDE_CHKHASH_H
|
||||
#define SHADOW_INCLUDE_CHKHASH_H
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
bool is_valid_hash(const char *hash);
|
||||
|
||||
|
||||
#endif
|
||||
@ -13,13 +13,12 @@
|
||||
* true - OK
|
||||
* false - bad name
|
||||
* errors:
|
||||
* EINVAL Invalid name
|
||||
* EILSEQ Invalid name character sequence (acceptable with --badname)
|
||||
* EINVAL Invalid name characters or sequences
|
||||
* EOVERFLOW Name longer than maximum size
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -28,15 +27,12 @@
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "chkname.h"
|
||||
#include "string/ctype/strchrisascii/strchriscntrl.h"
|
||||
#include "string/ctype/strisascii/strisdigit.h"
|
||||
#include "string/strcmp/streq.h"
|
||||
#include "string/strcmp/strcaseeq.h"
|
||||
|
||||
|
||||
#ifndef LOGIN_NAME_MAX
|
||||
@ -63,37 +59,35 @@ login_name_max_size(void)
|
||||
static bool
|
||||
is_valid_name(const char *name)
|
||||
{
|
||||
if (streq(name, "")
|
||||
|| streq(name, ".")
|
||||
|| streq(name, "..")
|
||||
|| strspn(name, "-")
|
||||
|| strpbrk(name, " \"#',/:;")
|
||||
|| strchriscntrl(name)
|
||||
|| strisdigit(name))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (allow_bad_names) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* User/group names must match BRE regex:
|
||||
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]*$\?
|
||||
*
|
||||
* as a non-POSIX, extension, allow "$" as the last char for
|
||||
* sake of Samba 3.x "add machine script"
|
||||
*/
|
||||
* User/group names must match BRE regex:
|
||||
* [a-zA-Z0-9_.][a-zA-Z0-9_.-]*$\?
|
||||
*
|
||||
* as a non-POSIX, extension, allow "$" as the last char for
|
||||
* sake of Samba 3.x "add machine script"
|
||||
*
|
||||
* Also do not allow fully numeric names or just "." or "..".
|
||||
*/
|
||||
|
||||
if (!((*name >= 'a' && *name <= 'z') ||
|
||||
if (strisdigit(name)) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (streq(name, "") ||
|
||||
streq(name, ".") ||
|
||||
streq(name, "..") ||
|
||||
!((*name >= 'a' && *name <= 'z') ||
|
||||
(*name >= 'A' && *name <= 'Z') ||
|
||||
(*name >= '0' && *name <= '9') ||
|
||||
*name == '_' ||
|
||||
*name == '.'))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -107,7 +101,7 @@ is_valid_name(const char *name)
|
||||
streq(name, "$")
|
||||
))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -53,8 +53,9 @@ void chown_tty (const struct passwd *info)
|
||||
if ( (fchown (STDIN_FILENO, info->pw_uid, gid) != 0)
|
||||
|| (fchmod (STDIN_FILENO, getdef_num ("TTYPERM", 0600)) != 0)) {
|
||||
int err = errno;
|
||||
FILE *shadow_logfd = log_get_logfd();
|
||||
|
||||
fprintf (log_get_logfd(),
|
||||
fprintf (shadow_logfd,
|
||||
_("Unable to change owner or mode of tty stdin: %s"),
|
||||
strerror (err));
|
||||
SYSLOG ((LOG_WARN,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -27,7 +27,7 @@ void cleanup_report_add_group (void *group_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add group %s", name));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_ADD_GROUP,
|
||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
||||
"",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -45,7 +45,7 @@ void cleanup_report_del_group (void *group_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to remove group %s", name));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_DEL_GROUP,
|
||||
audit_logger (AUDIT_DEL_GROUP, log_get_progname(),
|
||||
"",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -62,7 +62,7 @@ void cleanup_report_mod_group (void *cleanup_info)
|
||||
gr_dbname (),
|
||||
info->action));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_GRP_MGMT,
|
||||
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
|
||||
info->audit_msg,
|
||||
info->name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -80,7 +80,7 @@ void cleanup_report_mod_gshadow (void *cleanup_info)
|
||||
sgr_dbname (),
|
||||
info->action));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_GRP_MGMT,
|
||||
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
|
||||
info->audit_msg,
|
||||
info->name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -100,7 +100,7 @@ void cleanup_report_add_group_group (void *group_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, gr_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_ADD_GROUP,
|
||||
audit_logger (AUDIT_ADD_GROUP, log_get_progname(),
|
||||
"adding-group",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -120,7 +120,7 @@ void cleanup_report_add_group_gshadow (void *group_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add group %s to %s", name, sgr_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_GRP_MGMT,
|
||||
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
|
||||
"adding-shadow-group",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -143,7 +143,7 @@ void cleanup_report_del_group_group (void *group_name)
|
||||
"failed to remove group %s from %s",
|
||||
name, gr_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_DEL_GROUP,
|
||||
audit_logger (AUDIT_DEL_GROUP, log_get_progname(),
|
||||
"removing-group",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -166,7 +166,7 @@ void cleanup_report_del_group_gshadow (void *group_name)
|
||||
"failed to remove group %s from %s",
|
||||
name, sgr_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_GRP_MGMT,
|
||||
audit_logger (AUDIT_GRP_MGMT, log_get_progname(),
|
||||
"removing-shadow-group",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -179,11 +179,9 @@ void cleanup_report_del_group_gshadow (void *group_name)
|
||||
*
|
||||
* It should be registered after the group file is successfully locked.
|
||||
*/
|
||||
void cleanup_unlock_group (void *process_selinux)
|
||||
void cleanup_unlock_group (MAYBE_UNUSED void *arg)
|
||||
{
|
||||
bool process = *((bool *) process_selinux);
|
||||
|
||||
if (gr_unlock (process) == 0) {
|
||||
if (gr_unlock () == 0) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to unlock %s\n"),
|
||||
log_get_progname(), gr_dbname ());
|
||||
@ -201,11 +199,9 @@ void cleanup_unlock_group (void *process_selinux)
|
||||
*
|
||||
* It should be registered after the gshadow file is successfully locked.
|
||||
*/
|
||||
void cleanup_unlock_gshadow (void *process_selinux)
|
||||
void cleanup_unlock_gshadow (MAYBE_UNUSED void *arg)
|
||||
{
|
||||
bool process = *((bool *) process_selinux);
|
||||
|
||||
if (sgr_unlock (process) == 0) {
|
||||
if (sgr_unlock () == 0) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to unlock %s\n"),
|
||||
log_get_progname(), sgr_dbname ());
|
||||
|
||||
@ -4,11 +4,12 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "attr.h"
|
||||
#include "defines.h"
|
||||
#include "pwio.h"
|
||||
#include "shadowio.h"
|
||||
@ -26,7 +27,7 @@ void cleanup_report_add_user (void *user_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add user %s", name));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_ADD_USER,
|
||||
audit_logger (AUDIT_ADD_USER, log_get_progname(),
|
||||
"",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -43,7 +44,7 @@ void cleanup_report_mod_passwd (void *cleanup_info)
|
||||
pw_dbname (),
|
||||
info->action));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_USER_MGMT,
|
||||
audit_logger (AUDIT_USER_MGMT, log_get_progname(),
|
||||
info->audit_msg,
|
||||
info->name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -63,7 +64,7 @@ void cleanup_report_add_user_passwd (void *user_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, pw_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_ADD_USER,
|
||||
audit_logger (AUDIT_ADD_USER, log_get_progname(),
|
||||
"adding-user",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -83,7 +84,7 @@ void cleanup_report_add_user_shadow (void *user_name)
|
||||
|
||||
SYSLOG ((LOG_ERR, "failed to add user %s to %s", name, spw_dbname ()));
|
||||
#ifdef WITH_AUDIT
|
||||
audit_logger (AUDIT_USER_MGMT,
|
||||
audit_logger (AUDIT_USER_MGMT, log_get_progname(),
|
||||
"adding-shadow-user",
|
||||
name, AUDIT_NO_ID,
|
||||
SHADOW_AUDIT_FAILURE);
|
||||
@ -95,11 +96,9 @@ void cleanup_report_add_user_shadow (void *user_name)
|
||||
*
|
||||
* It should be registered after the passwd database is successfully locked.
|
||||
*/
|
||||
void cleanup_unlock_passwd (void *process_selinux)
|
||||
void cleanup_unlock_passwd (MAYBE_UNUSED void *arg)
|
||||
{
|
||||
bool process = *((bool *) process_selinux);
|
||||
|
||||
if (pw_unlock (process) == 0) {
|
||||
if (pw_unlock () == 0) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to unlock %s\n"),
|
||||
log_get_progname(), pw_dbname ());
|
||||
@ -116,11 +115,9 @@ void cleanup_unlock_passwd (void *process_selinux)
|
||||
*
|
||||
* It should be registered after the shadow database is successfully locked.
|
||||
*/
|
||||
void cleanup_unlock_shadow (void *process_selinux)
|
||||
void cleanup_unlock_shadow (MAYBE_UNUSED void *arg)
|
||||
{
|
||||
bool process = *((bool *) process_selinux);
|
||||
|
||||
if (spw_unlock (process) == 0) {
|
||||
if (spw_unlock () == 0) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to unlock %s\n"),
|
||||
log_get_progname(), spw_dbname ());
|
||||
|
||||
272
lib/commonio.c
272
lib/commonio.c
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
@ -24,31 +23,32 @@
|
||||
#include <utime.h>
|
||||
|
||||
#include "alloc/malloc.h"
|
||||
#include "alloc/reallocf.h"
|
||||
#include "atoi/getnum.h"
|
||||
#include "commonio.h"
|
||||
#include "defines.h"
|
||||
#include "fs/mkstemp/fmkomstemp.h"
|
||||
#include "nscd.h"
|
||||
#ifdef WITH_TCB
|
||||
#include <tcb.h>
|
||||
#endif /* WITH_TCB */
|
||||
#include "prototypes.h"
|
||||
#include "shadowlog.h"
|
||||
#include "shadowlog_internal.h"
|
||||
#include "sssd.h"
|
||||
#include "string/memset/memzero.h"
|
||||
#include "string/sprintf/aprintf.h"
|
||||
#include "string/sprintf/snprintf.h"
|
||||
#include "string/strcmp/streq.h"
|
||||
#include "string/strcmp/strprefix.h"
|
||||
#include "string/strerrno.h"
|
||||
#include "string/strtok/stpsep.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
static int lrename (const char *, const char *);
|
||||
static int check_link_count (const char *file, bool log);
|
||||
static int do_lock_file (const char *file, const char *lock, bool log);
|
||||
static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
|
||||
char *name,
|
||||
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
||||
const char *name,
|
||||
const char *mode,
|
||||
const struct stat *sb);
|
||||
static int create_backup (const char *, FILE *);
|
||||
static void free_linked_list (struct commonio_db *);
|
||||
@ -68,24 +68,50 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
|
||||
static int lock_count = 0;
|
||||
static bool nscd_need_reload = false;
|
||||
|
||||
/*
|
||||
* Simple rename(P) alternative that attempts to rename to symlink
|
||||
* target.
|
||||
*/
|
||||
int lrename (const char *old, const char *new)
|
||||
{
|
||||
int res;
|
||||
char *r = NULL;
|
||||
struct stat sb;
|
||||
|
||||
if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
|
||||
r = realpath (new, NULL);
|
||||
if (NULL == r) {
|
||||
perror ("realpath in lrename()");
|
||||
} else {
|
||||
new = r;
|
||||
}
|
||||
}
|
||||
|
||||
res = rename (old, new);
|
||||
|
||||
free (r);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int check_link_count (const char *file, bool log)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat (file, &sb) != 0) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: %s file stat error: %s\n",
|
||||
log_get_progname(), file, strerrno());
|
||||
shadow_progname, file, strerror (errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sb.st_nlink != 2) {
|
||||
if (log) {
|
||||
fprintf(log_get_logfd(),
|
||||
fprintf(shadow_logfd,
|
||||
"%s: %s: lock file already used (nlink: %ju)\n",
|
||||
log_get_progname(), file, (uintmax_t) sb.st_nlink);
|
||||
shadow_progname, file, (uintmax_t) sb.st_nlink);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -105,21 +131,21 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (-1 == fd) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: %s: %s\n",
|
||||
log_get_progname(), file, strerrno());
|
||||
shadow_progname, file, strerror (errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid = getpid ();
|
||||
stprintf_a(buf, "%lu", (unsigned long) pid);
|
||||
SNPRINTF(buf, "%lu", (unsigned long) pid);
|
||||
len = (ssize_t) strlen (buf) + 1;
|
||||
if (write_full(fd, buf, len) == -1) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: %s file write error: %s\n",
|
||||
log_get_progname(), file, strerrno());
|
||||
shadow_progname, file, strerror (errno));
|
||||
}
|
||||
(void) close (fd);
|
||||
unlink (file);
|
||||
@ -127,9 +153,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
}
|
||||
if (fdatasync (fd) == -1) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: %s file sync error: %s\n",
|
||||
log_get_progname(), file, strerrno());
|
||||
shadow_progname, file, strerror (errno));
|
||||
}
|
||||
(void) close (fd);
|
||||
unlink (file);
|
||||
@ -146,21 +172,21 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
fd = open (lock, O_RDWR);
|
||||
if (-1 == fd) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: %s: %s\n",
|
||||
log_get_progname(), lock, strerrno());
|
||||
shadow_progname, lock, strerror (errno));
|
||||
}
|
||||
unlink (file);
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
len = read(fd, buf, sizeof(buf) - 1);
|
||||
len = read (fd, buf, sizeof (buf) - 1);
|
||||
close (fd);
|
||||
if (len <= 0) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: existing lock file %s without a PID\n",
|
||||
log_get_progname(), lock);
|
||||
shadow_progname, lock);
|
||||
}
|
||||
unlink (file);
|
||||
errno = EINVAL;
|
||||
@ -169,9 +195,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
stpcpy(&buf[len], "");
|
||||
if (get_pid(buf, &pid) == -1) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: existing lock file %s with an invalid PID '%s'\n",
|
||||
log_get_progname(), lock, buf);
|
||||
shadow_progname, lock, buf);
|
||||
}
|
||||
unlink (file);
|
||||
errno = EINVAL;
|
||||
@ -179,9 +205,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
}
|
||||
if (kill (pid, 0) == 0) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: lock %s already used by PID %lu\n",
|
||||
log_get_progname(), lock, (unsigned long) pid);
|
||||
shadow_progname, lock, (unsigned long) pid);
|
||||
}
|
||||
unlink (file);
|
||||
errno = EEXIST;
|
||||
@ -189,9 +215,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
}
|
||||
if (unlink (lock) != 0) {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: cannot get lock %s: %s\n",
|
||||
log_get_progname(), lock, strerrno());
|
||||
shadow_progname, lock, strerror (errno));
|
||||
}
|
||||
unlink (file);
|
||||
return 0;
|
||||
@ -202,9 +228,9 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
retval = check_link_count (file, log);
|
||||
} else {
|
||||
if (log) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: cannot get lock %s: %s\n",
|
||||
log_get_progname(), lock, strerrno());
|
||||
shadow_progname, lock, strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,13 +239,17 @@ static int do_lock_file (const char *file, const char *lock, bool log)
|
||||
}
|
||||
|
||||
|
||||
static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
|
||||
char *name,
|
||||
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
||||
const char *name,
|
||||
const char *mode,
|
||||
const struct stat *sb)
|
||||
{
|
||||
FILE *fp;
|
||||
mode_t mask;
|
||||
|
||||
fp = fmkomstemp(name, 0, 0600);
|
||||
mask = umask (0777);
|
||||
fp = fopen (name, mode);
|
||||
(void) umask (mask);
|
||||
if (NULL == fp) {
|
||||
return NULL;
|
||||
}
|
||||
@ -235,26 +265,24 @@ static /*@null@*/ /*@dependent@*/FILE *fmkstemp_set_perms (
|
||||
|
||||
fail:
|
||||
(void) fclose (fp);
|
||||
/* fmkstemp_set_perms is used for intermediate files */
|
||||
/* fopen_set_perms is used for intermediate files */
|
||||
(void) unlink (name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int create_backup (const char *name, FILE * fp)
|
||||
static int create_backup (const char *backup, FILE * fp)
|
||||
{
|
||||
char tmpf[PATH_MAX], target[PATH_MAX];
|
||||
struct stat sb;
|
||||
struct utimbuf ub;
|
||||
FILE *bkfp;
|
||||
int c;
|
||||
|
||||
stprintf_a(tmpf, "%s.cioXXXXXX", name);
|
||||
if (fstat (fileno (fp), &sb) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bkfp = fmkstemp_set_perms(tmpf, &sb);
|
||||
bkfp = fopen_set_perms (backup, "w", &sb);
|
||||
if (NULL == bkfp) {
|
||||
return -1;
|
||||
}
|
||||
@ -270,28 +298,22 @@ static int create_backup (const char *name, FILE * fp)
|
||||
}
|
||||
if ((c != EOF) || (ferror (fp) != 0) || (fflush (bkfp) != 0)) {
|
||||
(void) fclose (bkfp);
|
||||
unlink(tmpf);
|
||||
/* FIXME: unlink the backup file? */
|
||||
return -1;
|
||||
}
|
||||
if (fsync (fileno (bkfp)) != 0) {
|
||||
(void) fclose (bkfp);
|
||||
unlink(tmpf);
|
||||
/* FIXME: unlink the backup file? */
|
||||
return -1;
|
||||
}
|
||||
if (fclose (bkfp) != 0) {
|
||||
unlink(tmpf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stprintf_a(target, "%s-", name);
|
||||
if (rename(tmpf, target) != 0) {
|
||||
unlink(tmpf);
|
||||
/* FIXME: unlink the backup file? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ub.actime = sb.st_atime;
|
||||
ub.modtime = sb.st_mtime;
|
||||
(void) utime(target, &ub);
|
||||
(void) utime (backup, &ub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -306,8 +328,9 @@ static void free_linked_list (struct commonio_db *db)
|
||||
|
||||
free (p->line);
|
||||
|
||||
if (NULL != p->eptr)
|
||||
db->ops->cio_free(p->eptr);
|
||||
if (NULL != p->eptr) {
|
||||
db->ops->free (p->eptr);
|
||||
}
|
||||
|
||||
free (p);
|
||||
}
|
||||
@ -317,7 +340,7 @@ static void free_linked_list (struct commonio_db *db)
|
||||
|
||||
int commonio_setname (struct commonio_db *db, const char *name)
|
||||
{
|
||||
stprintf_a(db->filename, "%s", name);
|
||||
SNPRINTF(db->filename, "%s", name);
|
||||
db->setname = true;
|
||||
return 1;
|
||||
}
|
||||
@ -379,9 +402,9 @@ int commonio_lock (struct commonio_db *db)
|
||||
if (0 == lock_count) {
|
||||
if (lckpwdf () == -1) {
|
||||
if (geteuid () != 0) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
"%s: Permission denied.\n",
|
||||
log_get_progname());
|
||||
shadow_progname);
|
||||
}
|
||||
return 0; /* failure */
|
||||
}
|
||||
@ -415,8 +438,8 @@ int commonio_lock (struct commonio_db *db)
|
||||
}
|
||||
/* no unnecessary retries on "permission denied" errors */
|
||||
if (geteuid () != 0) {
|
||||
(void) fprintf (log_get_logfd(), "%s: Permission denied.\n",
|
||||
log_get_progname());
|
||||
(void) fprintf (shadow_logfd, "%s: Permission denied.\n",
|
||||
shadow_progname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -444,13 +467,13 @@ static void dec_lock_count (void)
|
||||
}
|
||||
|
||||
|
||||
int commonio_unlock (struct commonio_db *db, bool process_selinux)
|
||||
int commonio_unlock (struct commonio_db *db)
|
||||
{
|
||||
char lock[1029];
|
||||
|
||||
if (db->isopen) {
|
||||
db->readonly = true;
|
||||
if (commonio_close (db, process_selinux) == 0) {
|
||||
if (commonio_close (db) == 0) {
|
||||
if (db->locked) {
|
||||
dec_lock_count ();
|
||||
}
|
||||
@ -463,7 +486,7 @@ int commonio_unlock (struct commonio_db *db, bool process_selinux)
|
||||
* then call ulckpwdf() (if used) on last unlock.
|
||||
*/
|
||||
db->locked = false;
|
||||
stprintf_a(lock, "%s.lock", db->filename);
|
||||
SNPRINTF(lock, "%s.lock", db->filename);
|
||||
unlink (lock);
|
||||
dec_lock_count ();
|
||||
return 1;
|
||||
@ -525,7 +548,7 @@ static void add_one_entry_nis (struct commonio_db *db,
|
||||
struct commonio_entry *p;
|
||||
|
||||
for (p = db->head; NULL != p; p = p->next) {
|
||||
if (name_is_nis (p->eptr ? db->ops->cio_getname(p->eptr)
|
||||
if (name_is_nis (p->eptr ? db->ops->getname (p->eptr)
|
||||
: p->line)) {
|
||||
/*@-mustfreeonly@*/
|
||||
newp->next = p;
|
||||
@ -544,9 +567,11 @@ static void add_one_entry_nis (struct commonio_db *db,
|
||||
}
|
||||
#endif /* KEEP_NIS_AT_END */
|
||||
|
||||
/* Initial buffer size, as well as increment if not sufficient
|
||||
(for reading very long lines in group files). */
|
||||
#define BUFLEN 4096
|
||||
|
||||
int
|
||||
commonio_open(struct commonio_db *db, int mode)
|
||||
int commonio_open (struct commonio_db *db, int mode)
|
||||
{
|
||||
char *buf;
|
||||
char *line;
|
||||
@ -608,12 +633,31 @@ commonio_open(struct commonio_db *db, int mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
while (getline(&buf, &buflen, db->fp) != -1) {
|
||||
buflen = BUFLEN;
|
||||
buf = MALLOC(buflen, char);
|
||||
if (NULL == buf)
|
||||
goto cleanup_errno;
|
||||
|
||||
while (db->ops->fgets (buf, buflen, db->fp) == buf) {
|
||||
struct commonio_entry *p;
|
||||
|
||||
if (stpsep(buf, "\n") == NULL)
|
||||
goto cleanup_buf;
|
||||
while ( (strrchr (buf, '\n') == NULL)
|
||||
&& (feof (db->fp) == 0)) {
|
||||
size_t len;
|
||||
|
||||
buflen += BUFLEN;
|
||||
buf = REALLOCF(buf, buflen, char);
|
||||
if (NULL == buf)
|
||||
goto cleanup_errno;
|
||||
|
||||
len = strlen (buf);
|
||||
if (db->ops->fgets (buf + len,
|
||||
(int) (buflen - len),
|
||||
db->fp) == NULL) {
|
||||
goto cleanup_buf;
|
||||
}
|
||||
}
|
||||
stpsep(buf, "\n");
|
||||
|
||||
line = strdup (buf);
|
||||
if (NULL == line) {
|
||||
@ -623,16 +667,16 @@ commonio_open(struct commonio_db *db, int mode)
|
||||
if (name_is_nis (line)) {
|
||||
eptr = NULL;
|
||||
} else {
|
||||
eptr = db->ops->cio_parse(line);
|
||||
eptr = db->ops->parse (line);
|
||||
if (NULL != eptr) {
|
||||
eptr = db->ops->cio_dup(eptr);
|
||||
eptr = db->ops->dup (eptr);
|
||||
if (NULL == eptr) {
|
||||
goto cleanup_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = malloc_T(1, struct commonio_entry);
|
||||
p = MALLOC(1, struct commonio_entry);
|
||||
if (NULL == p) {
|
||||
goto cleanup_entry;
|
||||
}
|
||||
@ -650,7 +694,7 @@ commonio_open(struct commonio_db *db, int mode)
|
||||
goto cleanup_errno;
|
||||
}
|
||||
|
||||
if ((NULL != db->ops->cio_open_hook) && (db->ops->cio_open_hook() == 0)) {
|
||||
if ((NULL != db->ops->open_hook) && (db->ops->open_hook () == 0)) {
|
||||
goto cleanup_errno;
|
||||
}
|
||||
|
||||
@ -658,8 +702,9 @@ commonio_open(struct commonio_db *db, int mode)
|
||||
return 1;
|
||||
|
||||
cleanup_entry:
|
||||
if (NULL != eptr)
|
||||
db->ops->cio_free(eptr);
|
||||
if (NULL != eptr) {
|
||||
db->ops->free (eptr);
|
||||
}
|
||||
cleanup_line:
|
||||
free (line);
|
||||
cleanup_buf:
|
||||
@ -674,7 +719,6 @@ commonio_open(struct commonio_db *db, int mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sort given db according to cmp function (usually compares uids)
|
||||
*/
|
||||
@ -708,7 +752,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
|
||||
return 0;
|
||||
}
|
||||
|
||||
entries = malloc_T(n, struct commonio_entry *);
|
||||
entries = MALLOC(n, struct commonio_entry *);
|
||||
if (entries == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@ -727,7 +771,7 @@ commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
|
||||
entries[n] = ptr;
|
||||
n++;
|
||||
}
|
||||
qsort(entries, n, sizeof(struct commonio_entry *), cmp);
|
||||
qsort (entries, n, sizeof (struct commonio_entry *), cmp);
|
||||
|
||||
/* Take care of the head and tail separately */
|
||||
db->head = entries[0];
|
||||
@ -776,14 +820,14 @@ int commonio_sort_wrt (struct commonio_db *shadow,
|
||||
if (NULL == pw_ptr->eptr) {
|
||||
continue;
|
||||
}
|
||||
name = passwd->ops->cio_getname(pw_ptr->eptr);
|
||||
name = passwd->ops->getname (pw_ptr->eptr);
|
||||
for (spw_ptr = shadow->head;
|
||||
NULL != spw_ptr;
|
||||
spw_ptr = spw_ptr->next) {
|
||||
if (NULL == spw_ptr->eptr) {
|
||||
continue;
|
||||
}
|
||||
if (streq(name, shadow->ops->cio_getname(spw_ptr->eptr)))
|
||||
if (streq(name, shadow->ops->getname(spw_ptr->eptr)))
|
||||
break;
|
||||
}
|
||||
if (NULL == spw_ptr) {
|
||||
@ -825,13 +869,13 @@ static int write_all (const struct commonio_db *db)
|
||||
if (p->changed) {
|
||||
eptr = p->eptr;
|
||||
assert (NULL != eptr);
|
||||
if (db->ops->cio_put(eptr, db->fp) != 0) {
|
||||
if (db->ops->put (eptr, db->fp) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if (NULL != p->line) {
|
||||
if (fputs(p->line, db->fp) == EOF)
|
||||
if (db->ops->fputs (p->line, db->fp) == EOF) {
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (putc ('\n', db->fp) == EOF) {
|
||||
return -1;
|
||||
}
|
||||
@ -841,11 +885,10 @@ static int write_all (const struct commonio_db *db)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
int commonio_close (struct commonio_db *db)
|
||||
{
|
||||
bool errors = false;
|
||||
char tmpf[PATH_MAX];
|
||||
char buf[1024];
|
||||
struct stat sb;
|
||||
|
||||
if (!db->isopen) {
|
||||
@ -862,11 +905,11 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
goto success;
|
||||
}
|
||||
|
||||
if ((NULL != db->ops->cio_close_hook) && (db->ops->cio_close_hook() == 0)) {
|
||||
if ((NULL != db->ops->close_hook) && (db->ops->close_hook () == 0)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memzero(&sb, sizeof(sb));
|
||||
memzero (&sb, sizeof sb);
|
||||
if (NULL != db->fp) {
|
||||
if (fstat (fileno (db->fp), &sb) != 0) {
|
||||
(void) fclose (db->fp);
|
||||
@ -877,13 +920,18 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
/*
|
||||
* Create backup file.
|
||||
*/
|
||||
if (SNPRINTF(buf, "%s-", db->filename) == -1) {
|
||||
(void) fclose (db->fp);
|
||||
db->fp = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (process_selinux
|
||||
&& set_selinux_file_context (db->filename, S_IFREG) != 0) {
|
||||
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
|
||||
errors = true;
|
||||
}
|
||||
#endif
|
||||
if (create_backup(db->filename, db->fp) != 0) {
|
||||
if (create_backup (buf, db->fp) != 0) {
|
||||
errors = true;
|
||||
}
|
||||
|
||||
@ -894,8 +942,7 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
db->fp = NULL;
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (process_selinux
|
||||
&& reset_selinux_file_context () != 0) {
|
||||
if (reset_selinux_file_context () != 0) {
|
||||
errors = true;
|
||||
}
|
||||
#endif
|
||||
@ -910,17 +957,16 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
sb.st_gid = db->st_gid;
|
||||
}
|
||||
|
||||
if (stprintf_a(tmpf, "%s.cioXXXXXX", db->filename) == -1)
|
||||
if (SNPRINTF(buf, "%s+", db->filename) == -1)
|
||||
goto fail;
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (process_selinux
|
||||
&& set_selinux_file_context (db->filename, S_IFREG) != 0) {
|
||||
if (set_selinux_file_context (db->filename, S_IFREG) != 0) {
|
||||
errors = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
db->fp = fmkstemp_set_perms(tmpf, &sb);
|
||||
db->fp = fopen_set_perms (buf, "w", &sb);
|
||||
if (NULL == db->fp) {
|
||||
goto fail;
|
||||
}
|
||||
@ -944,17 +990,16 @@ commonio_close(struct commonio_db *db, MAYBE_UNUSED bool process_selinux)
|
||||
db->fp = NULL;
|
||||
|
||||
if (errors) {
|
||||
unlink(tmpf);
|
||||
unlink (buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (rename(tmpf, db->filename) != 0) {
|
||||
if (lrename (buf, db->filename) != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef WITH_SELINUX
|
||||
if (process_selinux
|
||||
&& reset_selinux_file_context () != 0) {
|
||||
if (reset_selinux_file_context () != 0) {
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
@ -984,7 +1029,7 @@ static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
|
||||
for (p = pos; NULL != p; p = p->next) {
|
||||
ep = p->eptr;
|
||||
if ( (NULL != ep)
|
||||
&& streq(db->ops->cio_getname(ep), name)) {
|
||||
&& streq(db->ops->getname(ep), name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1008,19 +1053,19 @@ int commonio_update (struct commonio_db *db, const void *eptr)
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
nentry = db->ops->cio_dup(eptr);
|
||||
nentry = db->ops->dup (eptr);
|
||||
if (NULL == nentry) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
p = find_entry_by_name(db, db->ops->cio_getname(eptr));
|
||||
p = find_entry_by_name (db, db->ops->getname (eptr));
|
||||
if (NULL != p) {
|
||||
if (next_entry_by_name(db, p->next, db->ops->cio_getname(eptr)) != NULL) {
|
||||
fprintf(log_get_logfd(), _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->cio_getname(eptr), db->filename);
|
||||
db->ops->cio_free(nentry);
|
||||
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) {
|
||||
fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
|
||||
db->ops->free (nentry);
|
||||
return 0;
|
||||
}
|
||||
db->ops->cio_free(p->eptr);
|
||||
db->ops->free (p->eptr);
|
||||
p->eptr = nentry;
|
||||
p->changed = true;
|
||||
db->cursor = p;
|
||||
@ -1029,9 +1074,9 @@ int commonio_update (struct commonio_db *db, const void *eptr)
|
||||
return 1;
|
||||
}
|
||||
/* not found, new entry */
|
||||
p = malloc_T(1, struct commonio_entry);
|
||||
p = MALLOC(1, struct commonio_entry);
|
||||
if (NULL == p) {
|
||||
db->ops->cio_free(nentry);
|
||||
db->ops->free (nentry);
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
@ -1060,15 +1105,15 @@ int commonio_append (struct commonio_db *db, const void *eptr)
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
nentry = db->ops->cio_dup(eptr);
|
||||
nentry = db->ops->dup (eptr);
|
||||
if (NULL == nentry) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
/* new entry */
|
||||
p = malloc_T(1, struct commonio_entry);
|
||||
p = MALLOC(1, struct commonio_entry);
|
||||
if (NULL == p) {
|
||||
db->ops->cio_free(nentry);
|
||||
db->ops->free (nentry);
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
@ -1121,7 +1166,7 @@ int commonio_remove (struct commonio_db *db, const char *name)
|
||||
return 0;
|
||||
}
|
||||
if (next_entry_by_name (db, p->next, name) != NULL) {
|
||||
fprintf (log_get_logfd(), _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
|
||||
fprintf (shadow_logfd, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1129,8 +1174,9 @@ int commonio_remove (struct commonio_db *db, const char *name)
|
||||
|
||||
free (p->line);
|
||||
|
||||
if (NULL != p->eptr)
|
||||
db->ops->cio_free(p->eptr);
|
||||
if (NULL != p->eptr) {
|
||||
db->ops->free (p->eptr);
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
|
||||
@ -35,30 +35,39 @@ struct commonio_ops {
|
||||
* Make a copy of the object (for example, struct passwd)
|
||||
* and all strings pointed by it, in malloced memory.
|
||||
*/
|
||||
/*@null@*/ /*@only@*/void *(*cio_dup)(const void *);
|
||||
/*@null@*/ /*@only@*/void *(*dup) (const void *);
|
||||
|
||||
/*
|
||||
* free() the object including any strings pointed by it.
|
||||
*/
|
||||
void (*cio_free)(/*@only@*/void *);
|
||||
void (*free)(/*@only@*/void *);
|
||||
|
||||
/*
|
||||
* Return the name of the object (for example, pw_name
|
||||
* for struct passwd).
|
||||
*/
|
||||
const char *(*cio_getname)(const void *);
|
||||
const char *(*getname) (const void *);
|
||||
|
||||
/*
|
||||
* Parse a string, return object (in static area -
|
||||
* should be copied using the dup operation above).
|
||||
*/
|
||||
void *(*cio_parse)(const char *);
|
||||
void *(*parse) (const char *);
|
||||
|
||||
/*
|
||||
* Write the object to the file (this calls putpwent()
|
||||
* for struct passwd, for example).
|
||||
*/
|
||||
int (*cio_put)(const void *, FILE *);
|
||||
int (*put) (const void *, FILE *);
|
||||
|
||||
/*
|
||||
* fgets and fputs (can be replaced by versions that
|
||||
* understand line continuation conventions).
|
||||
*/
|
||||
ATTR_ACCESS(write_only, 1, 2)
|
||||
/*@null@*/char *(*fgets)(/*@returned@*/char *restrict s, int n,
|
||||
FILE *restrict stream);
|
||||
int (*fputs) (const char *, FILE *);
|
||||
|
||||
/*
|
||||
* open_hook and close_hook.
|
||||
@ -66,8 +75,8 @@ struct commonio_ops {
|
||||
* is open or before it is closed.
|
||||
* They return 0 on failure and 1 on success.
|
||||
*/
|
||||
/*@null@*/int (*cio_open_hook)(void);
|
||||
/*@null@*/int (*cio_close_hook)(void);
|
||||
/*@null@*/int (*open_hook) (void);
|
||||
/*@null@*/int (*close_hook) (void);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -94,7 +103,7 @@ struct commonio_db {
|
||||
#endif
|
||||
/*
|
||||
* Default permissions and owner for newly created data file.
|
||||
*/
|
||||
*/
|
||||
mode_t st_mode;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
@ -129,8 +138,8 @@ extern int commonio_append (struct commonio_db *, const void *);
|
||||
extern int commonio_remove (struct commonio_db *, const char *);
|
||||
extern int commonio_rewind (struct commonio_db *);
|
||||
extern /*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *);
|
||||
extern int commonio_close (struct commonio_db *, bool);
|
||||
extern int commonio_unlock (struct commonio_db *, bool);
|
||||
extern int commonio_close (struct commonio_db *);
|
||||
extern int commonio_unlock (struct commonio_db *);
|
||||
extern void commonio_del_entry (struct commonio_db *,
|
||||
const struct commonio_entry *);
|
||||
extern int commonio_sort_wrt (struct commonio_db *shadow,
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -52,7 +52,7 @@ is_listed(const char *cfgin, const char *tty, bool def)
|
||||
if (*cons != '/') {
|
||||
char *pbuf;
|
||||
|
||||
strtcpy_a(buf, cons);
|
||||
STRTCPY(buf, cons);
|
||||
pbuf = buf;
|
||||
while (NULL != (s = strsep(&pbuf, ":"))) {
|
||||
if (streq(s, tty)) {
|
||||
@ -76,7 +76,7 @@ is_listed(const char *cfgin, const char *tty, bool def)
|
||||
* See if this tty is listed in the console file.
|
||||
*/
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
while (fgets (buf, sizeof (buf), fp) != NULL) {
|
||||
stpsep(buf, "\n");
|
||||
if (streq(buf, tty)) {
|
||||
(void) fclose (fp);
|
||||
|
||||
162
lib/copydir.c
162
lib/copydir.c
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc/malloc.h"
|
||||
#include "alloc/x/xmalloc.h"
|
||||
#include "attr.h"
|
||||
#include "fs/readlink/areadlink.h"
|
||||
#include "prototypes.h"
|
||||
@ -27,16 +27,21 @@
|
||||
#ifdef WITH_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#endif /* WITH_SELINUX */
|
||||
#if defined(WITH_ACL)
|
||||
#if defined(WITH_ACL) || defined(WITH_ATTR)
|
||||
#include <stdarg.h>
|
||||
#include <attr/error_context.h>
|
||||
#endif /* WITH_ACL || WITH_ATTR */
|
||||
#ifdef WITH_ACL
|
||||
#include <acl/libacl.h>
|
||||
#endif /* WITH_ACL */
|
||||
#ifdef WITH_ATTR
|
||||
#include <attr/libattr.h>
|
||||
#endif /* WITH_ATTR */
|
||||
#include "shadowlog.h"
|
||||
#include "string/sprintf/aprintf.h"
|
||||
#include "string/sprintf/xaprintf.h"
|
||||
#include "string/strcmp/streq.h"
|
||||
#include "string/strcmp/strprefix.h"
|
||||
#include "string/strerrno.h"
|
||||
|
||||
|
||||
static /*@null@*/const char *src_orig;
|
||||
@ -58,23 +63,29 @@ struct path_info {
|
||||
};
|
||||
|
||||
static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
||||
MAYBE_UNUSED bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
static int copy_hardlink (const struct path_info *dst,
|
||||
MAYBE_UNUSED bool reset_selinux,
|
||||
struct link_name *lp);
|
||||
static int copy_special (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
@ -85,15 +96,15 @@ static int fchown_if_needed (int fdst, const struct stat *statp,
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid);
|
||||
|
||||
#if defined(WITH_ACL)
|
||||
#if defined(WITH_ACL) || defined(WITH_ATTR)
|
||||
/*
|
||||
* error_acl - format the error messages for the ACL and EQ libraries.
|
||||
*/
|
||||
format_attr(printf, 2, 3)
|
||||
static void
|
||||
error_acl(struct error_context *, const char *fmt, ...)
|
||||
static void error_acl (MAYBE_UNUSED struct error_context *ctx, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
FILE *shadow_logfd = log_get_logfd();
|
||||
|
||||
/* ignore the case when destination does not support ACLs
|
||||
* or extended attributes */
|
||||
@ -103,18 +114,18 @@ error_acl(struct error_context *, const char *fmt, ...)
|
||||
}
|
||||
|
||||
va_start (ap, fmt);
|
||||
(void) fprintf (log_get_logfd(), _("%s: "), log_get_progname());
|
||||
if (vfprintf (log_get_logfd(), fmt, ap) != 0) {
|
||||
(void) fputs (_(": "), log_get_logfd());
|
||||
(void) fprintf (shadow_logfd, _("%s: "), log_get_progname());
|
||||
if (vfprintf (shadow_logfd, fmt, ap) != 0) {
|
||||
(void) fputs (_(": "), shadow_logfd);
|
||||
}
|
||||
(void) fprintf(log_get_logfd(), "%s\n", strerrno());
|
||||
(void) fprintf (shadow_logfd, "%s\n", strerror (errno));
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
static struct error_context ctx = {
|
||||
error_acl, NULL, NULL
|
||||
};
|
||||
#endif /* WITH_ACL */
|
||||
#endif /* WITH_ACL || WITH_ATTR */
|
||||
|
||||
#ifdef WITH_ACL
|
||||
static int perm_copy_path(const struct path_info *src,
|
||||
@ -141,6 +152,32 @@ static int perm_copy_path(const struct path_info *src,
|
||||
}
|
||||
#endif /* WITH_ACL */
|
||||
|
||||
#ifdef WITH_ATTR
|
||||
static int attr_copy_path(const struct path_info *src,
|
||||
const struct path_info *dst,
|
||||
int (*callback) (const char *, struct error_context *),
|
||||
struct error_context *errctx)
|
||||
{
|
||||
int src_fd, dst_fd, ret;
|
||||
|
||||
src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
||||
if (src_fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
|
||||
if (dst_fd < 0) {
|
||||
(void) close (src_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = attr_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, callback, errctx);
|
||||
(void) close (src_fd);
|
||||
(void) close (dst_fd);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WITH_ATTR */
|
||||
|
||||
/*
|
||||
* remove_link - delete a link from the linked list
|
||||
*/
|
||||
@ -193,7 +230,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lp = xmalloc_T(1, struct link_name);
|
||||
lp = XMALLOC(1, struct link_name);
|
||||
lp->ln_dev = sb->st_dev;
|
||||
lp->ln_ino = sb->st_ino;
|
||||
lp->ln_count = sb->st_nlink;
|
||||
@ -205,7 +242,7 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
|
||||
}
|
||||
|
||||
static int copy_tree_impl (const struct path_info *src, const struct path_info *dst,
|
||||
bool copy_root,
|
||||
bool copy_root, bool reset_selinux,
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
{
|
||||
@ -233,7 +270,8 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
|
||||
return -1;
|
||||
}
|
||||
|
||||
return copy_entry (src, dst, old_uid, new_uid, old_gid, new_gid);
|
||||
return copy_entry (src, dst, reset_selinux,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -272,7 +310,7 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
|
||||
dst_orig = dst->full_path;
|
||||
set_orig = true;
|
||||
}
|
||||
while (0 == err && NULL != (ent = readdir(dir))) {
|
||||
while ((0 == err) && (ent = readdir (dir)) != NULL) {
|
||||
char *src_name = NULL;
|
||||
char *dst_name;
|
||||
struct path_info src_entry, dst_entry;
|
||||
@ -304,7 +342,7 @@ static int copy_tree_impl (const struct path_info *src, const struct path_info *
|
||||
dst_entry.dirfd = dst_fd;
|
||||
dst_entry.name = ent->d_name;
|
||||
|
||||
err = copy_entry(&src_entry, &dst_entry,
|
||||
err = copy_entry(&src_entry, &dst_entry, reset_selinux,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
|
||||
free(dst_name);
|
||||
@ -360,6 +398,7 @@ skip:
|
||||
* to -1.
|
||||
*/
|
||||
static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
{
|
||||
@ -381,7 +420,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
mt[1].tv_nsec = sb.st_mtim.tv_nsec;
|
||||
|
||||
if (S_ISDIR (sb.st_mode)) {
|
||||
err = copy_dir (src, dst, &sb, mt,
|
||||
err = copy_dir (src, dst, reset_selinux, &sb, mt,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
@ -398,7 +437,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
*/
|
||||
|
||||
else if (S_ISLNK (sb.st_mode)) {
|
||||
err = copy_symlink (src, dst, &sb, mt,
|
||||
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
@ -407,7 +446,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
*/
|
||||
|
||||
else if ((lp = check_link (src->full_path, &sb)) != NULL) {
|
||||
err = copy_hardlink (dst, lp);
|
||||
err = copy_hardlink (dst, reset_selinux, lp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -417,7 +456,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
*/
|
||||
|
||||
else if (!S_ISREG (sb.st_mode)) {
|
||||
err = copy_special (src, dst, &sb, mt,
|
||||
err = copy_special (src, dst, reset_selinux, &sb, mt,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
@ -427,7 +466,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
*/
|
||||
|
||||
else {
|
||||
err = copy_file (src, dst, &sb, mt,
|
||||
err = copy_file (src, dst, reset_selinux, &sb, mt,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
@ -445,6 +484,7 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||
* Return 0 on success, -1 on error.
|
||||
*/
|
||||
static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
@ -462,14 +502,14 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||
return -1;
|
||||
}
|
||||
#endif /* WITH_SELINUX */
|
||||
/*
|
||||
* If the destination is already a directory, don't change it
|
||||
* but copy into it (recursively).
|
||||
*/
|
||||
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
|
||||
return (copy_tree_impl (src, dst, false,
|
||||
old_uid, new_uid, old_gid, new_gid) != 0);
|
||||
}
|
||||
/*
|
||||
* If the destination is already a directory, don't change it
|
||||
* but copy into it (recursively).
|
||||
*/
|
||||
if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
|
||||
return (copy_tree_impl (src, dst, false, reset_selinux,
|
||||
old_uid, new_uid, old_gid, new_gid) != 0);
|
||||
}
|
||||
|
||||
if ( (mkdirat (dst->dirfd, dst->name, 0700) != 0)
|
||||
|| (chownat_if_needed (dst, statp,
|
||||
@ -479,7 +519,19 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||
|| ( (perm_copy_path (src, dst, &ctx) != 0)
|
||||
&& (errno != 0))
|
||||
#endif /* WITH_ACL */
|
||||
|| (copy_tree_impl (src, dst, false,
|
||||
#ifdef WITH_ATTR
|
||||
/*
|
||||
* If the third parameter is NULL, all extended attributes
|
||||
* except those that define Access Control Lists are copied.
|
||||
* ACLs are excluded by default because copying them between
|
||||
* file systems with and without ACL support needs some
|
||||
* additional logic so that no unexpected permissions result.
|
||||
*/
|
||||
|| ( !reset_selinux
|
||||
&& (attr_copy_path (src, dst, NULL, &ctx) != 0)
|
||||
&& (errno != 0))
|
||||
#endif /* WITH_ATTR */
|
||||
|| (copy_tree_impl (src, dst, false, reset_selinux,
|
||||
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||
|| (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
|
||||
err = -1;
|
||||
@ -499,6 +551,7 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||
* Return 0 on success, -1 on error.
|
||||
*/
|
||||
static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
||||
MAYBE_UNUSED bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
@ -569,6 +622,7 @@ static int copy_symlink (const struct path_info *src, const struct path_info *ds
|
||||
* Return 0 on success, -1 on error.
|
||||
*/
|
||||
static int copy_hardlink (const struct path_info *dst,
|
||||
MAYBE_UNUSED bool reset_selinux,
|
||||
struct link_name *lp)
|
||||
{
|
||||
/* FIXME: selinux, ACL, Extended Attributes needed? */
|
||||
@ -599,7 +653,8 @@ static int copy_hardlink (const struct path_info *dst,
|
||||
* Return 0 on success, -1 on error.
|
||||
*/
|
||||
static int
|
||||
copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *dst,
|
||||
copy_special(const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
@ -623,6 +678,20 @@ copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *d
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined(WITH_ATTR)
|
||||
/*
|
||||
* If the third parameter is NULL, all extended attributes
|
||||
* except those that define Access Control Lists are copied.
|
||||
* ACLs are excluded by default because copying them between
|
||||
* file systems with and without ACL support needs some
|
||||
* additional logic so that no unexpected permissions result.
|
||||
*/
|
||||
if (!reset_selinux) {
|
||||
if (attr_copy_path(src, dst, NULL, &ctx) == -1 && errno != 0)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (utimensat(dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) == -1)
|
||||
return -1;
|
||||
|
||||
@ -640,6 +709,7 @@ copy_special(MAYBE_UNUSED const struct path_info *src, const struct path_info *d
|
||||
* Return 0 on success, -1 on error.
|
||||
*/
|
||||
static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||
bool reset_selinux,
|
||||
const struct stat *statp, const struct timespec mt[],
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
@ -667,6 +737,18 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||
|| ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
|
||||
&& (errno != 0))
|
||||
#endif /* WITH_ACL */
|
||||
#ifdef WITH_ATTR
|
||||
/*
|
||||
* If the third parameter is NULL, all extended attributes
|
||||
* except those that define Access Control Lists are copied.
|
||||
* ACLs are excluded by default because copying them between
|
||||
* file systems with and without ACL support needs some
|
||||
* additional logic so that no unexpected permissions result.
|
||||
*/
|
||||
|| ( !reset_selinux
|
||||
&& (attr_copy_fd (src->full_path, ifd, dst->full_path, ofd, NULL, &ctx) != 0)
|
||||
&& (errno != 0))
|
||||
#endif /* WITH_ATTR */
|
||||
) {
|
||||
if (ofd >= 0) {
|
||||
(void) close (ofd);
|
||||
@ -679,7 +761,7 @@ static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||
char buf[8192];
|
||||
ssize_t cnt;
|
||||
|
||||
cnt = read(ifd, buf, sizeof(buf));
|
||||
cnt = read (ifd, buf, sizeof buf);
|
||||
if (cnt < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
@ -719,7 +801,7 @@ static int chown_function ## _if_needed (type_dst dst, \
|
||||
{ \
|
||||
uid_t tmpuid = (uid_t) -1; \
|
||||
gid_t tmpgid = (gid_t) -1; \
|
||||
\
|
||||
\
|
||||
/* Use new_uid if old_uid is set to -1 or if the file was \
|
||||
* owned by the user. */ \
|
||||
if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
|
||||
@ -730,14 +812,14 @@ static int chown_function ## _if_needed (type_dst dst, \
|
||||
if ((uid_t) -1 == tmpuid) { \
|
||||
tmpuid = statp->st_uid; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
|
||||
tmpgid = new_gid; \
|
||||
} \
|
||||
if ((gid_t) -1 == tmpgid) { \
|
||||
tmpgid = statp->st_gid; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
return chown_function (dst, tmpuid, tmpgid); \
|
||||
}
|
||||
|
||||
@ -778,6 +860,9 @@ static int chownat_if_needed (const struct path_info *dst,
|
||||
* copy_tree() walks a directory tree and copies ordinary files
|
||||
* as it goes.
|
||||
*
|
||||
* When reset_selinux is enabled, extended attributes (and thus
|
||||
* SELinux attributes) are not copied.
|
||||
*
|
||||
* old_uid and new_uid are used to set the ownership of the copied
|
||||
* files. Unless old_uid is set to -1, only the files owned by
|
||||
* old_uid have their ownership changed to new_uid. In addition, if
|
||||
@ -787,7 +872,7 @@ static int chownat_if_needed (const struct path_info *dst,
|
||||
* old_gid/new_gid.
|
||||
*/
|
||||
int copy_tree (const char *src_root, const char *dst_root,
|
||||
bool copy_root,
|
||||
bool copy_root, bool reset_selinux,
|
||||
uid_t old_uid, uid_t new_uid,
|
||||
gid_t old_gid, gid_t new_gid)
|
||||
{
|
||||
@ -802,5 +887,6 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||
.name = dst_root
|
||||
};
|
||||
|
||||
return copy_tree_impl(&src, &dst, copy_root, old_uid, new_uid, old_gid, new_gid);
|
||||
return copy_tree_impl(&src, &dst, copy_root, reset_selinux,
|
||||
old_uid, new_uid, old_gid, new_gid);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2022-2024, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
|
||||
@ -51,9 +51,20 @@
|
||||
#include <dirent.h>
|
||||
|
||||
#include <shadow.h>
|
||||
#if defined(SHADOWGRP)
|
||||
#include "gshadow_.h"
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef NGROUPS_MAX
|
||||
#ifdef NGROUPS
|
||||
#define NGROUPS_MAX NGROUPS
|
||||
#else
|
||||
#define NGROUPS_MAX 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
@ -68,6 +79,11 @@
|
||||
#define LOG_WARN LOG_WARNING
|
||||
#endif
|
||||
|
||||
/* LOG_NOWAIT is deprecated */
|
||||
#ifndef LOG_NOWAIT
|
||||
#define LOG_NOWAIT 0
|
||||
#endif
|
||||
|
||||
/* LOG_AUTH is deprecated, use LOG_AUTHPRIV instead */
|
||||
#ifndef LOG_AUTHPRIV
|
||||
#define LOG_AUTHPRIV LOG_AUTH
|
||||
@ -81,7 +97,7 @@
|
||||
syslogd should log the current system time for each event, and not
|
||||
trust the formatted time received from the unix domain (or worse,
|
||||
UDP) socket. -MM */
|
||||
/* Avoid translated PAM error messages: set LC_ALL to "C".
|
||||
/* Avoid translated PAM error messages: Set LC_ALL to "C".
|
||||
* --Nekral */
|
||||
#define SYSLOG(x) \
|
||||
do { \
|
||||
@ -107,7 +123,7 @@
|
||||
in just one place. */
|
||||
|
||||
#ifndef SYSLOG_OPTIONS
|
||||
/* #define SYSLOG_OPTIONS (LOG_PID | LOG_CONS) */
|
||||
/* #define SYSLOG_OPTIONS (LOG_PID | LOG_CONS | LOG_NOWAIT) */
|
||||
#define SYSLOG_OPTIONS (LOG_PID)
|
||||
#endif
|
||||
|
||||
@ -144,6 +160,10 @@
|
||||
#define GROUP_FILE "/etc/group"
|
||||
#endif
|
||||
|
||||
#ifndef SHADOW_FILE
|
||||
#define SHADOW_FILE "/etc/shadow"
|
||||
#endif
|
||||
|
||||
#ifndef SUBUID_FILE
|
||||
#define SUBUID_FILE "/etc/subuid"
|
||||
#endif
|
||||
@ -152,6 +172,12 @@
|
||||
#define SUBGID_FILE "/etc/subgid"
|
||||
#endif
|
||||
|
||||
#ifdef SHADOWGRP
|
||||
#ifndef SGROUP_FILE
|
||||
#define SGROUP_FILE "/etc/gshadow"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* string to use for the pw_passwd field in /etc/passwd when using
|
||||
* shadow passwords - most systems use "x" but there are a few
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "defines.h"
|
||||
#include "shadowlog.h"
|
||||
#include "shadowlog_internal.h"
|
||||
#include "string/strcmp/strprefix.h"
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
method = &nummethod[0];
|
||||
}
|
||||
}
|
||||
(void) fprintf (log_get_logfd(),
|
||||
(void) fprintf (shadow_logfd,
|
||||
_("crypt method not supported by libcrypt? (%s)\n"),
|
||||
method);
|
||||
errno = EINVAL;
|
||||
|
||||
23
lib/env.c
23
lib/env.c
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -16,16 +16,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alloc/malloc.h"
|
||||
#include "alloc/realloc.h"
|
||||
#include "alloc/x/xmalloc.h"
|
||||
#include "alloc/x/xrealloc.h"
|
||||
#include "prototypes.h"
|
||||
#include "defines.h"
|
||||
#include "shadowlog.h"
|
||||
#include "string/sprintf/aprintf.h"
|
||||
#include "string/sprintf/snprintf.h"
|
||||
#include "string/sprintf/aprintf.h"
|
||||
#include "string/sprintf/xaprintf.h"
|
||||
#include "string/strcmp/strprefix.h"
|
||||
#include "string/strdup/strdup.h"
|
||||
#include "string/strdup/xstrdup.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -68,7 +67,7 @@ static const char *const noslash[] = {
|
||||
*/
|
||||
void initenv (void)
|
||||
{
|
||||
newenvp = xmalloc_T(NEWENVP_STEP, char *);
|
||||
newenvp = XMALLOC(NEWENVP_STEP, char *);
|
||||
*newenvp = NULL;
|
||||
}
|
||||
|
||||
@ -135,7 +134,7 @@ void addenv (const char *string, /*@null@*/const char *value)
|
||||
|
||||
update_environ = (environ == newenvp);
|
||||
|
||||
newenvp = xrealloc_T(newenvp, newenvc + NEWENVP_STEP, char *);
|
||||
newenvp = XREALLOC(newenvp, newenvc + NEWENVP_STEP, char *);
|
||||
|
||||
/*
|
||||
* If this is our current environment, update
|
||||
@ -164,13 +163,13 @@ void set_env (int argc, char *const *argv)
|
||||
char *cp;
|
||||
|
||||
for (; argc > 0; argc--, argv++) {
|
||||
if (strlen(*argv) >= sizeof(variable)) {
|
||||
if (strlen (*argv) >= sizeof variable) {
|
||||
continue; /* ignore long entries */
|
||||
}
|
||||
|
||||
cp = strchr (*argv, '=');
|
||||
if (NULL == cp) {
|
||||
assert(stprintf_a(variable, "L%d", noname) != -1);
|
||||
assert(SNPRINTF(variable, "L%d", noname) != -1);
|
||||
noname++;
|
||||
addenv (variable, *argv);
|
||||
} else {
|
||||
@ -227,9 +226,9 @@ void sanitize_env (void)
|
||||
if (!strprefix(*cur, *bad)) {
|
||||
continue;
|
||||
}
|
||||
if (!strchr(*cur, '/'))
|
||||
if (strchr (*cur, '/') == NULL) {
|
||||
continue; /* OK */
|
||||
|
||||
}
|
||||
for (move = cur; NULL != *move; move++) {
|
||||
*move = *(move + 1);
|
||||
}
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "exit_if_null.h"
|
||||
|
||||
|
||||
extern inline void exit_if_null_(void *p);
|
||||
@ -1,48 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar <alx@kernel.org>
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#ifndef SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
|
||||
#define SHADOW_INCLUDE_LIB_EXIT_IF_NULL_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "shadowlog.h"
|
||||
#include "string/strerrno.h"
|
||||
|
||||
|
||||
/*
|
||||
* This macro is used for implementing x*() variants of functions that
|
||||
* allocate memory, such as xstrdup() for wrapping strdup(3). The macro
|
||||
* returns the input pointer transparently, with the same type, but
|
||||
* calls exit(3) if the input is a null pointer (thus, if the allocation
|
||||
* failed).
|
||||
*/
|
||||
#define exit_if_null(p) \
|
||||
({ \
|
||||
__auto_type p_ = p; \
|
||||
\
|
||||
exit_if_null_(p_); \
|
||||
p_; \
|
||||
})
|
||||
|
||||
|
||||
inline void exit_if_null_(void *p);
|
||||
|
||||
|
||||
inline void
|
||||
exit_if_null_(void *p)
|
||||
{
|
||||
if (p == NULL) {
|
||||
fprintf(log_get_logfd(), "%s: %s\n", log_get_progname(), strerrno());
|
||||
exit(13);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // include guard
|
||||
@ -7,7 +7,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ident "$Id$"
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
void failure (uid_t uid, const char *tty, struct faillog *fl)
|
||||
{
|
||||
int fd;
|
||||
off_t offset_uid = (off_t) sizeof(*fl) * uid;
|
||||
off_t offset_uid = (off_t) (sizeof *fl) * uid;
|
||||
|
||||
/*
|
||||
* Don't do anything if failure logging isn't set up.
|
||||
@ -59,7 +59,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
|
||||
*/
|
||||
|
||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
||||
|| (read(fd, fl, sizeof(*fl)) != (ssize_t) sizeof(*fl))) {
|
||||
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|
||||
/* This is not necessarily a failure. The file is
|
||||
* initially zero length.
|
||||
*
|
||||
@ -67,7 +67,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
|
||||
* might reset the counter. But the new failure will be
|
||||
* logged.
|
||||
*/
|
||||
memzero(fl, sizeof(*fl));
|
||||
memzero (fl, sizeof *fl);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -81,7 +81,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
|
||||
fl->fail_cnt++;
|
||||
}
|
||||
|
||||
strtcpy_a(fl->fail_line, tty);
|
||||
STRTCPY(fl->fail_line, tty);
|
||||
fl->fail_time = time(NULL);
|
||||
|
||||
/*
|
||||
@ -92,7 +92,7 @@ void failure (uid_t uid, const char *tty, struct faillog *fl)
|
||||
*/
|
||||
|
||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
||||
|| (write_full(fd, fl, sizeof(*fl)) == -1)) {
|
||||
|| (write_full(fd, fl, sizeof *fl) == -1)) {
|
||||
goto err_write;
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
|
||||
{
|
||||
int fd;
|
||||
struct faillog fail;
|
||||
off_t offset_uid = (off_t) sizeof(*fl) * uid;
|
||||
off_t offset_uid = (off_t) (sizeof *fl) * uid;
|
||||
|
||||
/*
|
||||
* Suppress the check if the log file isn't there.
|
||||
@ -182,7 +182,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
|
||||
*/
|
||||
|
||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
||||
|| (read(fd, fl, sizeof(*fl)) != (ssize_t) sizeof(*fl))) {
|
||||
|| (read (fd, fl, sizeof *fl) != (ssize_t) sizeof *fl)) {
|
||||
(void) close (fd);
|
||||
return 1;
|
||||
}
|
||||
@ -204,7 +204,7 @@ int failcheck (uid_t uid, struct faillog *fl, bool failed)
|
||||
fail.fail_cnt = 0;
|
||||
|
||||
if ( (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
|
||||
|| (write_full(fd, &fail, sizeof(fail)) == -1)) {
|
||||
|| (write_full(fd, &fail, sizeof fail) == -1)) {
|
||||
goto err_write;
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ void failprint (const struct faillog *fail)
|
||||
/*
|
||||
* Print all information we have.
|
||||
*/
|
||||
strftime_a(lasttimeb, "%c", tp);
|
||||
STRFTIME(lasttimeb, "%c", tp);
|
||||
|
||||
/*@-formatconst@*/
|
||||
(void) printf (ngettext ("%d failure since last login.\n"
|
||||
|
||||
12
lib/fields.c
12
lib/fields.c
@ -7,14 +7,13 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "fields.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "string/ctype/strisascii/strisprint.h"
|
||||
@ -63,14 +62,15 @@ change_field(char *buf, size_t maxsize, const char *prompt)
|
||||
char newf[200];
|
||||
char *cp;
|
||||
|
||||
if (maxsize > sizeof(newf)) {
|
||||
maxsize = sizeof(newf);
|
||||
if (maxsize > sizeof (newf)) {
|
||||
maxsize = sizeof (newf);
|
||||
}
|
||||
|
||||
printf ("\t%s [%s]: ", prompt, buf);
|
||||
(void) fflush (stdout);
|
||||
if (fgets(newf, maxsize, stdin) == NULL)
|
||||
if (fgets (newf, maxsize, stdin) != newf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stpsep(newf, "\n") == NULL)
|
||||
return;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#define _SHADOW_INCLUDE_LIB_FIELDS_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
@ -18,18 +18,16 @@
|
||||
#include "groupio.h"
|
||||
#include "getdef.h"
|
||||
#include "shadowlog.h"
|
||||
#include "string/strerrno.h"
|
||||
|
||||
|
||||
/*
|
||||
* get_ranges - Get the minimum and maximum ID ranges for the search
|
||||
*
|
||||
* This function will return the minimum and maximum ranges for IDs
|
||||
*
|
||||
* 0: the function completed successfully
|
||||
* EINVAL: the provided ranges are impossible (such as maximum < minimum)
|
||||
* 0: The function completed successfully
|
||||
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
|
||||
*
|
||||
* preferred_min: the special-case minimum value for a specifically-
|
||||
* preferred_min: The special-case minimum value for a specifically-
|
||||
* requested ID, which may be lower than the standard min_id
|
||||
*/
|
||||
static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
|
||||
@ -56,11 +54,11 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
|
||||
/* Check that the ranges make sense */
|
||||
if (*max_id < *min_id) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
|
||||
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
|
||||
log_get_progname(), (unsigned long) *min_id,
|
||||
getdef_ulong ("GID_MIN", 1000UL),
|
||||
(unsigned long) *max_id);
|
||||
_("%s: Invalid configuration: SYS_GID_MIN (%lu), "
|
||||
"GID_MIN (%lu), SYS_GID_MAX (%lu)\n"),
|
||||
log_get_progname(), (unsigned long) *min_id,
|
||||
getdef_ulong ("GID_MIN", 1000UL),
|
||||
(unsigned long) *max_id);
|
||||
return EINVAL;
|
||||
}
|
||||
/*
|
||||
@ -235,11 +233,11 @@ int find_new_gid (bool sys_group,
|
||||
*/
|
||||
|
||||
/* Create an array to hold all of the discovered GIDs */
|
||||
used_gids = calloc_T(gid_max + 1, bool);
|
||||
used_gids = CALLOC (gid_max + 1, bool);
|
||||
if (NULL == used_gids) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to allocate memory: %s\n"),
|
||||
log_get_progname(), strerrno());
|
||||
log_get_progname(), strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -247,7 +245,7 @@ int find_new_gid (bool sys_group,
|
||||
(void) gr_rewind ();
|
||||
highest_found = gid_min;
|
||||
lowest_found = gid_max;
|
||||
while (NULL != (grp = gr_next())) {
|
||||
while ((grp = gr_next ()) != NULL) {
|
||||
/*
|
||||
* Does this entry have a lower GID than the lowest we've found
|
||||
* so far?
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ifdef ENABLE_SUBIDS
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#ifdef ENABLE_SUBIDS
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
@ -18,17 +18,16 @@
|
||||
#include "pwio.h"
|
||||
#include "getdef.h"
|
||||
#include "shadowlog.h"
|
||||
#include "string/strerrno.h"
|
||||
|
||||
/*
|
||||
* get_ranges - Get the minimum and maximum ID ranges for the search
|
||||
*
|
||||
* This function will return the minimum and maximum ranges for IDs
|
||||
*
|
||||
* 0: the function completed successfully
|
||||
* EINVAL: the provided ranges are impossible (such as maximum < minimum)
|
||||
* 0: The function completed successfully
|
||||
* EINVAL: The provided ranges are impossible (such as maximum < minimum)
|
||||
*
|
||||
* preferred_min: the special-case minimum value for a specifically-
|
||||
* preferred_min: The special-case minimum value for a specifically-
|
||||
* requested ID, which may be lower than the standard min_id
|
||||
*/
|
||||
static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
|
||||
@ -55,11 +54,11 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
|
||||
/* Check that the ranges make sense */
|
||||
if (*max_id < *min_id) {
|
||||
(void) fprintf (log_get_logfd(),
|
||||
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
|
||||
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
|
||||
log_get_progname(), (unsigned long) *min_id,
|
||||
getdef_ulong ("UID_MIN", 1000UL),
|
||||
(unsigned long) *max_id);
|
||||
_("%s: Invalid configuration: SYS_UID_MIN (%lu), "
|
||||
"UID_MIN (%lu), SYS_UID_MAX (%lu)\n"),
|
||||
log_get_progname(), (unsigned long) *min_id,
|
||||
getdef_ulong ("UID_MIN", 1000UL),
|
||||
(unsigned long) *max_id);
|
||||
return EINVAL;
|
||||
}
|
||||
/*
|
||||
@ -234,11 +233,11 @@ int find_new_uid(bool sys_user,
|
||||
*/
|
||||
|
||||
/* Create an array to hold all of the discovered UIDs */
|
||||
used_uids = calloc_T(uid_max + 1, bool);
|
||||
used_uids = CALLOC(uid_max + 1, bool);
|
||||
if (NULL == used_uids) {
|
||||
fprintf (log_get_logfd(),
|
||||
_("%s: failed to allocate memory: %s\n"),
|
||||
log_get_progname(), strerrno());
|
||||
log_get_progname(), strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -246,7 +245,7 @@ int find_new_uid(bool sys_user,
|
||||
(void) pw_rewind ();
|
||||
highest_found = uid_min;
|
||||
lowest_found = uid_max;
|
||||
while (NULL != (pwd = pw_next())) {
|
||||
while ((pwd = pw_next ()) != NULL) {
|
||||
/*
|
||||
* Does this entry have a lower UID than the lowest we've found
|
||||
* so far?
|
||||
|
||||
67
lib/fputsx.c
Normal file
67
lib/fputsx.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh
|
||||
* SPDX-FileCopyrightText: 1996 - 1999, Marek Michałkiewicz
|
||||
* SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko
|
||||
* SPDX-FileCopyrightText: 2008 , Nicolas François
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "prototypes.h"
|
||||
#include "string/strcmp/streq.h"
|
||||
|
||||
|
||||
/*@null@*/char *
|
||||
fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f)
|
||||
{
|
||||
char *cp = buf;
|
||||
char *ep;
|
||||
|
||||
while (cnt > 0) {
|
||||
if (fgets (cp, cnt, f) != cp) {
|
||||
if (cp == buf) {
|
||||
return NULL;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ep = strrchr (cp, '\\');
|
||||
if ((NULL != ep) && (*(ep + 1) == '\n')) {
|
||||
cnt -= ep - cp;
|
||||
if (cnt > 0)
|
||||
cp = stpcpy(ep, "");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int fputsx (const char *s, FILE * stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; !streq(s, ""); i++, s++) {
|
||||
if (putc (*s, stream) == EOF) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#if 0 /* The standard getgr*() can't handle that. --marekm */
|
||||
if (i > (BUFSIZ / 2)) {
|
||||
if (putc ('\\', stream) == EOF ||
|
||||
putc ('\n', stream) == EOF)
|
||||
return EOF;
|
||||
|
||||
i = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "fs/mkstemp/fmkomstemp.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_FS_MKSTEMP_FMKOMSTEMP_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "fs/mkstemp/mkomstemp.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_FS_MKSTEMP_MKOMSTEMP_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "fs/readlink/areadlink.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_FS_READLINK_AREADLINK_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
@ -33,7 +33,7 @@ areadlink(const char *link)
|
||||
int len;
|
||||
char *buf;
|
||||
|
||||
buf = malloc_T(size, char);
|
||||
buf = MALLOC(size, char);
|
||||
if (NULL == buf)
|
||||
return NULL;
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include "fs/readlink/readlinknul.h"
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHADOW_INCLUDE_LIB_FS_READLINK_READLINKNUL_H_
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@ -17,8 +17,7 @@
|
||||
#include "sizeof.h"
|
||||
|
||||
|
||||
// readlinknul_a - read link nul-terminate array
|
||||
#define readlinknul_a(link, buf) readlinknul(link, buf, countof(buf))
|
||||
#define READLINKNUL(link, buf) readlinknul(link, buf, countof(buf))
|
||||
|
||||
|
||||
ATTR_STRING(1)
|
||||
@ -26,7 +25,7 @@ inline ssize_t readlinknul(const char *restrict link, char *restrict buf,
|
||||
ssize_t size);
|
||||
|
||||
|
||||
// readlinknul - read link nul-terminate
|
||||
// Similar to readlink(2), but terminate the string.
|
||||
inline ssize_t
|
||||
readlinknul(const char *restrict link, char *restrict buf, ssize_t size)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user