[Pkg-shadow-devel] [Git][debian/adduser][wip/feature-system-locks] 11 commits: add some basic tests

Marc Haber (@zugschlus) gitlab at salsa.debian.org
Sun Jan 4 17:17:24 GMT 2026



Marc Haber pushed to branch wip/feature-system-locks at Debian / adduser


Commits:
c9a84b64 by Matt Barry at 2026-01-04T18:10:25+01:00
add some basic tests

- - - - -
124ab1ea by Marc Haber at 2026-01-04T18:10:25+01:00
improve log level handling

Thanks: Matt Barry
Git-Dch: ignore

- - - - -
9941e3e3 by Marc Haber at 2026-01-04T18:10:25+01:00
add new constants for password handling

Git-Dch: ignore
Thanks: Matt Barry

- - - - -
60adaf5e by Marc Haber at 2026-01-04T18:10:25+01:00
introduce password handling logic

Git-Dch: ignore
Thanks: Matt Barry

- - - - -
ac024314 by Marc Haber at 2026-01-04T18:10:25+01:00
introduce new function existing_value_desc

Git-Dch: ignore
Thanks: Matt Barry

- - - - -
a8cfffb1 by Marc Haber at 2026-01-04T18:10:25+01:00
use existing_value_desc

Thanks: Matt Barry
Git-Dch: ignore

- - - - -
b58cf801 by Matt Barry at 2026-01-04T18:10:25+01:00
locked.account.tests

- - - - -
81f6390d by Marc Haber at 2026-01-04T18:10:25+01:00
prepare AdduserTestsCommon for the new tests

Git-Dch: ignore

- - - - -
e8454ada by Matt Barry at 2026-01-04T18:10:25+01:00
user locked account tests

Git-Dch: ignore

- - - - -
adf54cae by Marc Haber at 2026-01-04T18:10:25+01:00
fix testsuite warning in test08.pl

Git-Dch: ignore

- - - - -
64b8e779 by Marc Haber at 2026-01-04T18:10:25+01:00
run upstream testsuite with redirected stdin

otherwise tests might hang invisibly when the software
goes interactive

Git-Dch: ignore

- - - - -


7 changed files:

- AdduserCommon.pm
- adduser
- + debian/tests/f/account_locks.t
- debian/tests/lib/AdduserTestsCommon.pm
- testsuite/runsuite.sh
- testsuite/test08.pl
- + testsuite/test10.pl


Changes:

=====================================
AdduserCommon.pm
=====================================
@@ -102,6 +102,17 @@ use constant {
     EXISTING_ID_MISMATCH => 4,
     EXISTING_LOCKED => 8,
     EXISTING_HAS_PASSWORD => 16,
+    EXISTING_DISABLED_PASS => 40,        # 32 | EXISTING_LOCKED
+    EXISTING_INVALID_PASS => 72,    # 64 | EXISTING_LOCKED
+    EXISTING_EXPIRED => 136,         # 128 | EXISTING_LOCKED
+    EXISTING_NOLOGIN => 264,        # 256 | EXISTING_LOCKED
+    EXISTING_PASSWORDLESS => 512,
+};
+
+use constant {
+    STDOUTDEFLEVEL => "warn",
+    STDERRDEFLEVEL => "warn",
+    LOGMSGDEFLEVEL => "info",
 };
 
 @EXPORT = (
@@ -138,6 +149,14 @@ use constant {
     'EXISTING_ID_MISMATCH',
     'EXISTING_LOCKED',
     'EXISTING_HAS_PASSWORD',
+    'EXISTING_DISABLED_PASS',
+    'EXISTING_INVALID_PASS',
+    'EXISTING_EXPIRED',
+    'EXISTING_NOLOGIN',
+    'EXISTING_PASSWORDLESS',
+    'STDOUTDEFLEVEL',
+    'STDERRDEFLEVEL',
+    'LOGMSGDEFLEVEL',
     'existing_user_status',
     'existing_group_status',
 );
@@ -598,16 +617,18 @@ END {
 #       EXISTING_ID_MISMATCH => 4
 #       EXISTING_LOCKED => 8
 #       EXISTING_HAS_PASSWORD => 16
-#   e.g. if the requested account name exists as a locked system user,
-#   return 8|2|1 == 11
+#       EXISTING_DISABLED_PASS => 32
+#       EXISTING_INVALID_PASS => 64
+#       EXISTING_NOLOGIN => 128
+#       EXISTING_EXPIRED => 256
+#       EXISTING_PASSWORDLESS => 512
 sub existing_user_status {
     my ($config, $new_name,$new_uid) = @_;
-    my ($dummy1,$pw,$uid);
     my $ret = EXISTING_NOT_FOUND;
     log_trace( "existing_user_status called with new_name %s, new_uid %s, first_system_uid %s, last_system_uid %s", $new_name, $new_uid, $config->{"first_system_uid"}, $config->{"last_system_uid"} );
-    if (($dummy1,$pw,$uid) = egetpwnam($new_name)) {
+    if (my (undef,$pw,$uid,undef,undef,$home,$shell) = egetpwnam($new_name)) {
         # user with the name exists
-        log_trace( "egetpwnam(%s) returns %s, %s, %s", $new_name, $dummy1, $pw, $uid );
+        log_trace( "egetpwnam(%s) returns %s, %s, %s, %s", $new_name, $pw, $uid, $home, $shell );
         $ret |= EXISTING_FOUND;
         $ret |= EXISTING_ID_MISMATCH if (defined($new_uid) && $uid != $new_uid);
         $ret |= EXISTING_SYSTEM if
@@ -615,11 +636,22 @@ sub existing_user_status {
         $ret |= EXISTING_HAS_PASSWORD if
             (defined $pw && $pw ne '' && $pw ne '!' && $pw !~ /^\*/);
         $ret |= EXISTING_LOCKED if (substr($pw,0,1) eq "!");  # TODO: also check expiry?
+
+        # Note: the following conditions will also be true against EXISTING_LOCKED
+        # iow, if $x & EXISTING_INVALID_PASS, then $x & EXISTING_LOCKED
+        $ret |= EXISTING_DISABLED_PASS if (substr($pw,0,1) eq "!");
+        $ret |= EXISTING_INVALID_PASS if (substr($pw,0,1) eq "*");
+        $ret |= EXISTING_PASSWORDLESS if ($pw eq '!');
+        $ret |= EXISTING_NOLOGIN if ($shell =~ /bin\/nologin/);
+
+        my $age = `chage -l $new_name`;
+        $ret |= EXISTING_EXPIRED if ($age =~ /password must be changed/);
+
     } elsif (defined($new_uid) && getpwuid($new_uid)) {
         # user with the uid exists
         $ret |= EXISTING_ID_MISMATCH;
     }
-    log_trace( "existing_user_status( %s, %s ) returns %s", $new_name, $new_uid, $ret );
+    log_trace( "existing_user_status( %s, %s ) returns %s (%s)", $new_name, $new_uid, $ret, existing_value_desc($ret) );
     return $ret;
 }
 
@@ -635,10 +667,10 @@ sub existing_user_status {
 #       EXISTING_ID_MISMATCH => 4
 sub existing_group_status {
     my ($config, $new_name,$new_gid) = @_;
-    my ($dummy1,$dummy2,$gid);
+    my ($gid);
     my $ret = EXISTING_NOT_FOUND;
     log_trace( "existing_group_status called with new_name %s, new_gid %s", $new_name, $new_gid );
-    if (($dummy1,$dummy2,$gid) = egetgrnam($new_name)) {
+    if ((undef,undef,$gid) = egetgrnam($new_name)) {
         # group with the name exists
         log_trace("egetgrnam %s returned successfully, gid = %s", $new_name, $gid);
         $ret |= EXISTING_FOUND;
@@ -648,10 +680,26 @@ sub existing_group_status {
     } elsif (defined($new_gid) && getgrgid($new_gid)) {
         $ret |= EXISTING_ID_MISMATCH;
     }
-    log_trace( "existing_group_status( %s, %s ) returns %s", $new_name, $new_gid, $ret );
+    log_trace( "existing_group_status( %s, %s ) returns %s (%s)", $new_name, $new_gid, $ret, existing_value_desc($ret) );
     return $ret;
 }
 
+sub existing_value_desc {
+    my ($val) = @_;
+    my @flags = ();
+    push @flags, "found" if ($val & EXISTING_FOUND);
+    push @flags, "wrongid" if $val & EXISTING_ID_MISMATCH;
+    push @flags, "system" if ($val & EXISTING_SYSTEM);
+    push @flags, "locked" if $val & EXISTING_LOCKED;
+    push @flags, "haspass" if $val & EXISTING_HAS_PASSWORD;
+    push @flags, "badpass" if $val & EXISTING_INVALID_PASS;
+    push @flags, "disabled" if $val & EXISTING_DISABLED_PASS;
+    push @flags, "nologin" if $val & EXISTING_NOLOGIN;
+    push @flags, "expired" if $val & EXISTING_EXPIRED;
+    push @flags, "notfound" unless $#flags > 0;
+    return join '|', at flags
+}
+
 1;
 
 # Local Variables:


=====================================
adduser
=====================================
@@ -103,9 +103,9 @@ $0 =~ s+.*/++;
 our $action;
 our $verbose;		# should we be verbose?
 my $name_check_level = 0;		# should we allow bad names?
-our $stdoutmsglevel = "warn";
-our $stderrmsglevel = "warn";
-our $logmsglevel = "info";
+our $stdoutmsglevel = undef;
+our $stderrmsglevel = undef;
+our $logmsglevel = undef;
 my $allow_badname = 0;		# should we allow bad names?
 my $ask_passwd = 1;		# ask for a passwd?
 my $disabled_login = 0;		# leave the new account disabled?
@@ -201,10 +201,11 @@ if (!@configfiles) {
 
 # make sure that message levels apply for reading configuration
 # this will be overridden again after reading configuration
-$stdoutmsglevel = sanitize_string($stdoutmsglevel);
-$stderrmsglevel = sanitize_string($stderrmsglevel);
-$logmsglevel = sanitize_string($logmsglevel);
-set_msglevel( $stderrmsglevel, $stdoutmsglevel, $logmsglevel );
+set_msglevel( 
+    sanitize_string($stderrmsglevel or STDERRDEFLEVEL),
+    sanitize_string($stdoutmsglevel or STDOUTDEFLEVEL),
+    sanitize_string($logmsglevel or LOGMSGDEFLEVEL),
+);
 log_trace("ARGV %s", join(@ARGV,"-"));
 log_trace("special_home %s", $special_home);
 log_trace("special_home %s", encode($charset, $special_home));
@@ -225,8 +226,13 @@ if( $> != 0) {
     log_fatal( mtx("Only root may add a user or group to the system.") );
     exit( RET_ROOT_NEEDED );
 }
-
-# TODO: Handle configuration file input, allow bare input there.
+# ARGV > adduser.conf > (default)
+$stdoutmsglevel //= $config{'stdoutmsglevel'};
+$stdoutmsglevel //= STDOUTDEFLEVEL;
+$stderrmsglevel //= $config{'stderrmsglevel'}; 
+$stderrmsglevel //= STDERRDEFLEVEL;
+$logmsglevel    //= $config{'logmsglevel'};
+$logmsglevel    //= LOGMSGDEFLEVEL;
 $stdoutmsglevel = sanitize_string($stdoutmsglevel);
 $stderrmsglevel = sanitize_string($stderrmsglevel);
 $logmsglevel = sanitize_string($logmsglevel);
@@ -237,6 +243,7 @@ if( defined $verbose ) {
     } elsif( $verbose == 1 ) {
         set_msglevel( $stderrmsglevel, "info", $logmsglevel );
     } elsif( $verbose == 2 ) {
+        set_msglevel( $stdoutmsglevel, "debug", $logmsglevel );
         set_msglevel( $stderrmsglevel, "debug", $logmsglevel );
     }
 }


=====================================
debian/tests/f/account_locks.t
=====================================
@@ -0,0 +1,109 @@
+#! /usr/bin/perl -Idebian/tests/lib
+
+# Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=701110
+
+
+use diagnostics;
+use strict;
+use warnings;
+
+use AdduserTestsCommon;
+
+my $prefix = "lockedtest";
+my $un;
+
+END {
+	remove_tree("/home/$prefix-user");
+	remove_tree("/var/mail/$prefix-user");
+}
+
+## system user
+
+$un = "${prefix}-sys";
+
+assert_user_does_not_exist($un);
+assert_command_success('/usr/sbin/adduser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+	'--disabled-password',
+    '--system',
+	$un);
+assert_user_exists($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    '--system', "--lock",
+	$un);
+assert_user_exists($un);
+assert_user_is_locked($un);
+assert_user_is_disabled($un);
+assert_user_is_invalid($un);
+assert_user_is_expired($un);
+assert_user_is_nologin($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    '--system', "--lock",
+	$un);
+assert_user_exists($un);
+assert_command_success('/usr/sbin/adduser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    '--system',
+	$un);
+assert_user_exists($un);
+assert_user_is_not_locked($un);
+assert_user_is_not_disabled($un);
+assert_user_is_not_invalid($un);
+assert_user_is_not_expired($un);
+assert_user_is_not_nologin($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    '--system', '--force-delete',
+	$un);
+assert_user_does_not_exist($un);
+
+## normal user
+
+$un = "${prefix}-user";
+
+assert_user_does_not_exist($un);
+assert_command_success('/usr/sbin/adduser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+	'--disabled-password',
+	$un);
+assert_user_exists($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    "--lock",
+	$un);
+assert_user_exists($un);
+assert_user_is_locked($un);
+assert_user_is_disabled($un);
+assert_user_is_invalid($un);
+assert_user_is_expired($un);
+assert_user_is_nologin($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    "--lock",
+	$un);
+assert_user_exists($un);
+assert_command_failure('/usr/sbin/adduser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+	$un);
+assert_user_exists($un);
+assert_user_is_locked($un);
+assert_command_success('/usr/sbin/adduser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+	'--unlock',
+	$un);
+assert_user_exists($un);
+assert_user_is_not_locked($un);
+assert_user_is_not_disabled($un);
+assert_user_is_not_invalid($un);
+assert_user_is_not_expired($un);
+assert_user_is_not_nologin($un);
+assert_command_success('/usr/sbin/deluser',
+	'--stdoutmsglevel=error', '--stderrmsglevel=error',
+    '--system', '--force-delete', '--remove-home',
+	$un);
+assert_user_does_not_exist($un);
+
+
+# vim: tabstop=4 shiftwidth=4 expandtab


=====================================
debian/tests/lib/AdduserTestsCommon.pm
=====================================
@@ -30,6 +30,22 @@ END {
     if (-f '/var/cache/adduser/tests/state.tar');
 }
 
+use constant {
+    EXISTING_NOT_FOUND => 0,
+    EXISTING_FOUND => 1,
+    EXISTING_SYSTEM => 2,
+    EXISTING_ID_MISMATCH => 4,
+    EXISTING_LOCKED => 8,
+    EXISTING_DISABLED_PASS => 24,        # 16 | EXISTING_LOCKED
+    EXISTING_INVALID_PASS => 40,    # 32 | EXISTING_LOCKED
+    EXISTING_EXPIRED => 72,         # 64 | EXISTING_LOCKED
+    EXISTING_NOLOGIN => 136,        # 128 | EXISTING_LOCKED
+    SYS_MIN => 100,
+    SYS_MAX => 999,
+    USER_MIN => 1000,
+    USER_MAX => 9999,
+};
+
 my $charset = langinfo(CODESET);
 binmode(STDOUT, ":encoding($charset)");
 binmode(STDERR, ":encoding($charset)");
@@ -291,11 +307,6 @@ sub assert_path_has_ownership {
     is(sprintf('%s:%s', $user, $group), $ownership, $name);
 }
 
-sub assert_path_is_a_file {
-    my $path = shift;
-    ok(-f $path, "path is a file $path");
-}
-
 sub assert_path_is_a_directory {
     my $path = shift;
     ok(-d $path, "path is a directory: $path");
@@ -387,6 +398,7 @@ sub assert_user_has_home_directory {
 
 sub assert_user_has_comment {
     my ($user, $comment) = @_;
+    $comment .= ',,,';
     is((egetpwnam($user))[6], $comment, "user has comment: ~$user is $comment");
 }
 
@@ -459,6 +471,65 @@ sub apply_config_hash {
     close(CONF);
 }
 
+sub assert_user_is_locked { 
+    return existing_user_status($1) & EXISTING_LOCKED; 
+}
+sub assert_user_is_disabled { 
+    return (existing_user_status($1) & EXISTING_DISABLED_PASS)==EXISTING_DISABLED_PASS;
+}
+sub assert_user_is_invalid {
+    return (existing_user_status($1) & EXISTING_INVALID_PASS)==EXISTING_INVALID_PASS;
+}
+sub assert_user_is_nologin {
+    return (existing_user_status($1) & EXISTING_NOLOGIN)==EXISTING_NOLOGIN;
+}
+sub assert_user_is_expired {
+    return (existing_user_status($1) & EXISTING_EXPIRED)==EXISTING_EXPIRED;
+}
+sub assert_user_is_not_locked { return !assert_user_is_locked($1) }
+sub assert_user_is_not_disabled { return !assert_user_is_disabled($1) }
+sub assert_user_is_not_invalid { return !assert_user_is_invalid($1) }
+sub assert_user_is_not_nologin { return !assert_user_is_nologin($1) }
+sub assert_user_is_not_expired { return !assert_user_is_expired($1) }
+
+sub existing_user_status {
+    my ($new_name,$new_uid) = @_;
+    my $ret = EXISTING_NOT_FOUND;
+    if (my (undef,$pw,$uid,undef,undef,$home,$shell) = egetpwnam($new_name)) {
+        $ret |= EXISTING_FOUND;
+        $ret |= EXISTING_ID_MISMATCH if (defined($new_uid) && $uid != $new_uid);
+        $ret |= EXISTING_SYSTEM if \
+            ($uid >= SYS_MIN && $uid <= SYS_MAX);
+        
+	# Note: the following conditions will also be true against EXISTING_LOCKED
+        # iow, if $x & EXISTING_INVALID_PASS, then $x & EXISTING_LOCKED
+        $ret |= EXISTING_DISABLED_PASS if (substr($pw,0,1) eq "!");
+        $ret |= EXISTING_INVALID_PASS if (substr($pw,0,1) eq "*");
+        $ret |= EXISTING_NOLOGIN if ($shell =~ /bin\/nologin/);
+
+        my $age = `chage -l $new_name`;
+        $ret |= EXISTING_EXPIRED if ($age =~ /password must be changed/);
+    } elsif ($new_uid && getpwuid($new_uid)) {
+        $ret |= EXISTING_ID_MISMATCH;
+    }
+    return $ret;
+}
+
+sub existing_group_status {
+    my ($new_name,$new_gid) = @_;
+    my $gid;
+    my $ret = EXISTING_NOT_FOUND;
+    if ((undef,undef,$gid) = egetgrnam($new_name)) {
+        $ret |= EXISTING_FOUND;
+        $ret |= EXISTING_ID_MISMATCH if (defined($new_gid) && $gid != $new_gid);
+        $ret |= EXISTING_SYSTEM if \
+            ($gid >= SYS_MIN && $gid <= SYS_MAX);
+    } elsif ($new_gid && getgrgid($new_gid)) {
+        $ret |= EXISTING_ID_MISMATCH;
+    }
+    return $ret;
+}
+
 1;
 
 # vim: tabstop=4 shiftwidth=4 expandtab


=====================================
testsuite/runsuite.sh
=====================================
@@ -20,7 +20,7 @@ for a in on; do
     fi
     echo
     echo "Starting $i (shadow $a)"
-    /usr/bin/perl -I. $i
+    < /dev/null /usr/bin/perl -I. $i
     if [ "$?" != "0" ]; then
       FAILED="$FAILED $i($a)"
     fi


=====================================
testsuite/test08.pl
=====================================
@@ -91,7 +91,7 @@ unless (!defined getgrnam($newgroup)) {
         print "ok\n";
 }
 
-my $newgroup = find_unused_name();
+$newgroup = find_unused_name();
 
 $cmd = "adduser --group $newgroup";
 unless (defined getgrnam($newgroup)) {


=====================================
testsuite/test10.pl
=====================================
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+
+# expect:
+#  - a new non-system group $groupname
+#  - reading the group fails
+#  - reading the group as a system group fails
+#  - a new system group $groupname
+#  - reading the group succeeds
+#  - reading the group as a non-system group fails
+
+use strict;
+
+use lib_test;
+
+my $error;
+my $output;
+
+my $cmd;
+my $username;
+my $num;
+
+$username = find_unused_name();
+$num = 0;
+
+# unlock a non-existing account
+$cmd = "adduser --unlock $username";
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if (!$error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# add the account
+$cmd = "adduser --no-create-home --comment '' --disabled-password $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# lock the account
+$cmd = "deluser --lock $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# add the account (should fail)
+$cmd = "adduser --no-create-home --comment '' --disabled-password $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if (!$error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# unlock the account
+$cmd = "adduser --unlock $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# system
+$username = find_unused_name();
+
+# add system account
+$cmd = "adduser --system $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+print "Testing (10.1) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# lock the account
+$cmd = "deluser --system --lock $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# re-enable via add
+$cmd = "adduser --system $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if ($error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";
+
+# unlock already-unlocked
+$cmd = "adduser --unlock $username";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+$num ++ && print "Testing (10.$num) $cmd... ";
+$output=`$cmd 2>&1`;
+$error = ($?>>8);
+if (!$error) {
+    print "failed\n  $cmd returned errorcode ($error)\n  $output\n";
+    exit 1;
+}
+print "ok\n";



View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/6b5fe312198cab513a7197d6dd518c675a3832a0...64b8e77924dce922bbad50b06a37ed22a16a1094

-- 
View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/6b5fe312198cab513a7197d6dd518c675a3832a0...64b8e77924dce922bbad50b06a37ed22a16a1094
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-shadow-devel/attachments/20260104/30bd3f15/attachment-0001.htm>


More information about the Pkg-shadow-devel mailing list