#!/usr/bin/perl # # adduser VERSION # # adduser: a utility to add users to the system # addgroup: a utility to add groups to the system # Copyright (C) 1997, 1998, 1999 Guy Maor # Copyright (C) 1995 Ted Hajek # Ian A. Murdock # Bugfixes and other improvements Roland Bauerschmidt # General scheme of the program adapted by the original debian 'adduser' # program by Ian A. Murdock . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # #################### # See the usage subroutine for explanation about how the program can be called #################### use warnings; use Debian::AdduserCommon; use Getopt::Long; BEGIN { eval 'use Locale::gettext'; if ($@) { *gettext = sub { shift }; *textdomain = sub { "" }; *LC_MESSAGES = sub { 5 }; } eval { require POSIX; import POSIX qw(setlocale); }; if ($@) { *setlocale = sub { 1 }; } } setlocale(LC_MESSAGES, ""); textdomain("adduser"); $verbose = 1; # should we be verbose? $allow_badname = 0; # should we allow bad names? $ask_passwd = 1; # ask for a passwd? $disabled_login = 0; # leave the new account disabled? $defaults = "/etc/adduser.conf"; $nogroup_id = getgrnam("nogroup") || 65534; $0 =~ s+.*/++; $config{"dshell"} = "/bin/bash"; $config{"first_system_uid"} = 100; $config{"last_system_uid"} = 999; $config{"first_uid"} = 1000; $config{"last_uid"} = 29999; $config{"first_system_gid"} = 100; $config{"last_system_gid"} = 999; $config{"first_gid"} = 1000; $config{"last_gid"} = 29999; $config{"dhome"} = "/home"; $config{"skel"} = "/etc/skel"; $config{"usergroups"} = "yes"; $config{"users_gid"} = "100"; $config{"grouphomes"} = "no"; $config{"letterhomes"} = "no"; $config{"quotauser"} = ""; $config{"dir_mode"} = "0755"; $config{"setgid_home"} = "no"; $config{"name_regex"} = "^[a-z][-a-z0-9]*\$"; $action = $0 eq "addgroup" ? "addgroup" : "adduser"; die "$0: ",_("Only root may add a user or group to the system.\n") if ($> != 0); # Parse options, sanity checks GetOptions ("quiet" => sub { $verbose = 0 }, "force-badname" => \$allow_badname, "help|h" => sub { &usage(); exit 0 }, "version" => sub { &version(); exit 0 }, "system" => \$found_sys_opt, "group" => \$found_group_opt, "ingroup=s" => \$ingroup_name, "home=s" => \$special_home, "gecos=s" => \$new_gecos, "shell=s" => \$special_shell, "disabled_password" => sub { $ask_passwd = 0 }, "disabled_login" => sub { $disabled_login = 1; $ask_passwd = 0 }, "uid=i" => \$new_uid, "firstuid=i" => \$new_firstuid, "lastuid=i" => \$new_lastuid, "gid=i" => \$new_gid, "conf=s" => \$defaults, "no-create-home" => \$no_create_home, "debug" => \$debugging ); # check for unknown parameters # all other parameters are names while (defined($arg = shift(@ARGV))) { if (defined($names[0]) && $arg =~ /^--/) { die "$0: ",_("No options allowed after names.\n") } else { # it's a username push (@names, $arg); } } if ((defined($special_home)) && ($special_home !~ m+^/+ )) { die "$0: ",_("The home dir must be an absolute path.\n") } if (defined($found_sys_opt)) { $action = "addsysuser" if ($action eq "adduser"); $action = "addsysgroup" if ($action eq "addgroup"); } if (defined($defaults)) { die (_("`%s' does not exist.\n",$defaults)) if (! -f $defaults); } if (defined($special_home) && $verbose) { print "$0: ",_("Warning: The home dir you specified already exists.\n") if (!defined($no_create_home) && -d $special_home); print "$0: ",_("Warning: The home dir you specified does not exist.\n") if (defined($no_create_home) && ! -d $special_home); } if (@names == 0) { if($found_group_opt || $action eq "addgroup" || $action eq "addsysgroup") { print _("Enter a groupname to add: "); } else { print _("Enter a username to add: "); } chomp($answer=); push(@names, $answer); } die "$0: ",_("I need a name to add.\n") if (length($names[0]) == 0); die "$0: ",_("No more than two names.\n") if (@names > 2); if (@names == 2) { # must be addusertogroup die "$0: ",_("Specify only one name in this mode.\n") if ($action eq "addsysuser" || $found_group_opt); $action = "addusertogroup"; $existing_user = shift (@names); $existing_group = shift (@names); } else { $new_name = shift (@names); } if ($found_group_opt) { if ($action eq "addsysuser") { $make_group_also = 1; } elsif ($found_sys_opt) { $action = "addsysgroup"; } else { $action = "addgroup"; } } die "$0: ",_("The --group, --ingroup, and --gid options are mutually exclusive.\n") if ($action ne "addgroup" && defined($found_group_opt) +defined($ingroup_name) +defined($new_gid) > 1); if( $verbose ) { $ENV{"VERBOSE"}="1" } if( $debugging ) { $ENV{"DEBUG"}="1" } ##### # OK, we've processed the arguments. $action equals one of the following, # and the appropriate variables have been set: # # $action = "adduser" # $new_name - the name of the new user. # $ingroup_name | $new_gid - the group to add the user to # $special_home, $new_uid, $new_gecos - optional overrides # $action = "addgroup" # $new_name - the name of the new group # $new_gid - optional override # $action = "addsysgroup" # $new_name - the name of the new group # $new_gid - optional override # $action = "addsysuser" # $new_name - the name of the new user # $make_group_also | $ingroup_name | $new_gid | 0 - which group # $special_home, $new_uid, $new_gecos - optional overrides # $action = "addusertogroup" # $existing_user - the user to be added # $existing_group - the group to add her to ##### &read_config($defaults); &checkname($new_name) if defined $new_name; $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler'; ################# ## addsysgroup ## ################# if ($action eq "addsysgroup") { # Check if requested group already exists and we can exit safely if (existing_group_ok($new_name, $new_gid)) { printf (_("The group `%s' already exists as a system group. Exiting...\n"), $new_name) if $verbose; exit 0; } dief (_("The group `%s' already exists.\n"),$new_name) if (defined getgrnam($new_name)); dief (_("The GID %s is already in use.\n"),$new_gid) if (defined($new_gid) && defined(getgrgid($new_gid))); if (!defined($new_gid)) { $new_gid = &first_avail_id($config{"first_system_gid"}, $config{"last_system_gid"}, &get_current_gids); if ($new_gid == -1) { print STDERR "$0: ",_("No GID is available in the range "), "$config{\"first_system_gid\"} - $config{\"last_system_gid\"}\n", "(FIRST_SYS_GID - LAST_SYS_GID). "; dief (_("The group `%s' was not created.\n"),$new_name); } } printf (_("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose; &invalidate_nscd("group"); &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); &invalidate_nscd("group"); print _("Done.\n") if $verbose; exit 0; } ############## ## addgroup ## ############## if ($action eq "addgroup") { dief (_("The group `%s' already exists.\n"),$new_name) if (defined getgrnam($new_name)); dief (_("The GID %s is already in use.\n"),$new_gid) if (defined($new_gid) && defined(getgrgid($new_gid))); if (!defined($new_gid)) { $new_gid = &first_avail_id($config{"first_gid"}, $config{"last_gid"}, &get_current_gids); if ($new_gid == -1) { print STDERR "$0: ",_("No GID is available in the range "), "$config{\"first_gid\"} - $config{\"last_gid\"}\n", "(FIRST_GID - LAST_GID). "; dief (_("The group `%s' was not created.\n"),$new_name); } } printf (_("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose; &invalidate_nscd("group"); &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); &invalidate_nscd("group"); print _("Done.\n") if $verbose; exit 0; } #################### ## addusertogroup ## #################### if ($action eq "addusertogroup") { dief (_("The user `%s' does not exist.\n"),$existing_user) if (!defined getpwnam($existing_user)); dief (_("The group `%s' does not exist.\n"),$existing_group) if (!defined getgrnam($existing_group)); if (&user_is_member($existing_user, $existing_group)) { printf _("The user `%s' is already a member of `%s'.\n"), $existing_user,$existing_group if $verbose; exit 0; # not really an error } printf _("Adding user `%s' to group `%s'...\n"),$existing_user,$existing_group if $verbose; &invalidate_nscd(); # FIXME - the next line has a race condition. #&systemcall('usermod', '-G', #join(",", get_users_groups($existing_user), $existing_group), #$existing_user); # FIXME - if the group contains a non-existing user, gpasswd will fail &systemcall('/usr/bin/gpasswd', '-M', join(',', get_group_members($existing_group), $existing_user), $existing_group); #&systemcall('gpasswd', '-a',$existing_user,$existing_group); &invalidate_nscd(); print _("Done.\n") if $verbose; exit 0; } ################ ## addsysuser ## ################ if ($action eq "addsysuser") { if (existing_user_ok($new_name, $new_uid)) { printf (_("The user `%s' already exists as a system user. Exiting...\n"), $new_name) if $verbose; exit 0; } $new_gid = $nogroup_id if (!$ingroup_name && !defined($new_gid) && !$make_group_also); check_user_group(1); printf (_("Adding system user `%s'...\n"),$new_name) if $verbose; if (!defined($new_uid) && $make_group_also) { $new_uid = &first_avail_id($config{"first_system_uid"}, $config{"last_system_uid"}, &get_current_uids, &get_current_gids); if ($new_uid == -1) { print STDERR "$0: ",_("No UID/GID pair is available in the range "), "$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n", "(FIRST_SYS_UID - LAST_SYS_UID). "; dief (_("The user `%s' was not created.\n"),$new_name); } $new_gid = $new_uid; $ingroup_name = $new_name; } elsif (!defined($new_uid) && !$make_group_also) { $new_uid = &first_avail_id($config{"first_system_uid"}, $config{"last_system_uid"}, &get_current_uids); if ($new_uid == -1) { print STDERR "$0: ",_("No UID is available in the range "), "$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n", "(FIRST_SYS_UID - LAST_SYS_UID). "; &dief (_("The user `%s' was not created.\n"),$new_name); } if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } else { die _("Internal error"); } } else { if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; } else { die _("Internal error"); } } &invalidate_nscd(); # if we reach this point, and the group does already exist, we can use it. if ($make_group_also && !getgrnam($new_name)) {printf _("Adding new group `%s' (%s).\n"),$new_name,$new_gid if $verbose; $undogroup = $new_name; &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); &invalidate_nscd("group"); } printf _("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name if $verbose; $home_dir = $special_home || &homedir($new_name, $ingroup_name); $shell = $special_shell || '/bin/false'; $undouser = $new_name; &systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s', $shell, '-u', $new_uid, $new_name); print "/usr/bin/chage -M 99999 $new_name\n" if $debugging; if (system('/usr/bin/chage', '-M', '99999', $new_name)) { if( ($?>>8) ne 3 ) { &cleanup("$0: `/usr/bin/chage -M 99999 $new_name' returned error code " . ($?>>8) . ". Aborting.\n") if ($?>>8); &cleanup("$0: `/usr/bin/chage -M 99999 $new_name' exited from signal " . ($?&255) . ". Aborting.\n"); } else { print _("chage failed with return code 3, shadow not enabled, password aging cannot be set. Continuing.\n"); } } &invalidate_nscd(); if(defined($new_gecos)) { &ch_gecos($new_gecos); } if ($no_create_home) { print _("Not creating home directory.\n") if $verbose; } elsif (-e $home_dir) { printf _("Home directory `%s' already exists.\n"),$home_dir if $verbose; } else { printf _("Creating home directory `%s'.\n"),$home_dir if $verbose; $undohome = $home_dir; &mktree($home_dir) || &cleanup("Couldn't create $home_dir: $!.\n"); chown($new_uid, $new_gid, $home_dir) || &cleanup("chown $new_uid:$new_gid $home_dir: $!\n"); $dir_mode = get_dir_mode($make_group_also); chmod ($dir_mode, $home_dir) || &cleanup("chmod $dir_mode $home_dir: $!\n"); } exit 0; } ############# ## adduser ## ############# if ($action eq "adduser") { if (!$ingroup_name && !defined($new_gid)) { if ($config{"usergroups"} =~ /yes/i) { $make_group_also = 1; } else { $new_gid = $config{"users_gid"}; } } check_user_group(0); $first_uid = $new_firstuid || $config{"first_uid"}; $last_uid = $new_lastuid || $config{"last_uid"}; printf _("Adding user `%s'...\n"),$new_name if $verbose; if (!defined($new_uid) && $make_group_also) { $new_uid = &first_avail_id($first_uid, $last_uid, &get_current_uids, &get_current_gids); if ($new_uid == -1) { print STDERR "$0: ",_("No UID/GID pair is available in the range "), "$first_uid - $last_uid\n", "(FIRST_UID - LAST_UID). "; dief(_("The user `%s' was not created.\n"),$new_name); } $new_gid = $new_uid; $ingroup_name = $new_name; } elsif (!defined($new_uid) && !$make_group_also) { $new_uid = &first_avail_id($first_uid, $last_uid, &get_current_uids); if ($new_uid == -1) { print STDERR "$0: ",_("No UID is available in the range "), "$config{\"first_uid\"} - $config{\"last_uid\"}\n", "(FIRST_UID - LAST_UID). "; dief(_("The user `%s' was not created.\n"),$new_name); } if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } else { die _("Internal error"); } } else { if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; } else { die _("Internal error"); } } &invalidate_nscd(); if ($make_group_also) { printf _("Adding new group `%s' (%s).\n"),$new_name,$new_gid if $verbose; $undogroup = $new_name; &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); &invalidate_nscd(); } printf _("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name if $verbose; $home_dir = $special_home || &homedir($new_name, $ingroup_name); $shell = $special_shell || $config{"dshell"}; $undouser = $new_name; &systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s', $shell, '-u', $new_uid, $new_name); &invalidate_nscd(); if (-e $home_dir) { printf _("The home directory `%s' already exists. Not copying from `%s'\n"), $home_dir,$config{skel} if $verbose && !$no_create_home; } elsif ($no_create_home) { print "Not creating $home_dir.\n" if $verbose; } else { printf _("Creating home directory `%s'.\n"),$home_dir if $verbose; $undohome = $home_dir; &mktree($home_dir) || &cleanup("Couldn't create $home_dir: $!.\n"); chown($new_uid, $new_gid, $home_dir) || &cleanup("chown $new_uid:$new_gid $home_dir: $!\n"); $dir_mode = get_dir_mode($make_group_also); chmod ($dir_mode, $home_dir) || &cleanup("chmod $dir_mode $home_dir: $!\n"); if ($config{"skel"}) { printf _("Copying files from `%s'\n"),$config{skel} if $verbose; open(FIND, "cd $config{skel}; find . ! -name '*.dpkg-*' -print |") || &cleanup("fork for find: $!\n"); while () { chop; next if ($_ eq "."); ©_to_dir($config{"skel"}, $_, $home_dir, $new_uid, $new_gid, ($config{"setgid_home"} =~ /yes/i)); } } } # useradd without -p has left the account disabled (password string is '!') if ($ask_passwd) { &systemcall('/usr/bin/passwd', $new_name); } else { if(!$disabled_login) { &systemcall('/usr/sbin/usermod', '-p', '*', $new_name); } } if (defined($new_gecos)) { &ch_gecos($new_gecos); } else { for (;;) { &systemcall('/usr/bin/chfn', $new_name); print _("Is the information correct? [y/N] "); chop ($answer=); last if ($answer eq _("y")); } } if ($config{"quotauser"}) { printf _("Setting quota from `%s'.\n"),$config{quotauser}; &systemcall('/usr/sbin/edquota', '-p', $config{quotauser}, $new_name); } &systemcall('/usr/local/sbin/adduser.local', $new_name, $new_uid, $new_gid, $home_dir) if (-x "/usr/local/sbin/adduser.local"); exit 0; } # # we never go here # # calculate home directory sub homedir { my $dir = $config{"dhome"}; $dir .= '/' . $_[1] if ($config{"grouphomes"} =~ /yes/i); $dir .= '/' . substr($_[0],0,1) if ($config{"letterhomes"} =~ /yes/i); $dir .= '/' . $_[0]; return $dir; } # create a directory and all leading directories sub mktree { my($tree) = @_; my($done, @path); my $default_dir_mode = 0755; $tree =~ s:^/*(.*)/*$:$1:; # chop off leading & trailing slashes @path = split(/\//, $tree); $done = ""; while (@path) { $done .= '/' . shift(@path); -d $done || mkdir($done, $default_dir_mode) || return 0; } return 1; } # returns 0 if the the user doesn't exist or # returns 1 if # - the account already exists as a system user or # - if an explicit UID is given, that UID matches the existing user. sub existing_user_ok { my($new_name,$new_uid) = @_; my ($dummy1,$dummy2,$uid); if (($dummy1,$dummy2,$uid) = getpwnam($new_name)) { if( defined($new_uid) && $uid == $new_uid ) { ##+#print "uid"; return 1; } if( $uid >= $config{"first_system_uid"} && $uid <= $config{"last_system_uid" } ) { ##+#print "range"; return 1; } } else { return 0; } } # returns 0 if the group doesn't exist or # returns 1 if # - the group already exists as a system group or # - if an explicit GID is given, that GID matches the existing group. sub existing_group_ok { my($new_name,$new_gid) = @_; my ($dummy1,$dummy2,$gid); if (($dummy1,$dummy2,$gid) = getgrnam($new_name)) { if( defined($new_gid) && $gid == $new_gid ) { return 1; } if( $gid >= $config{"first_system_gid"} && $gid <= $config{"last_system_gid" } ) { return 1; } } else { return 0; } } sub check_user_group { my ($system) = @_; if( !$system || !existing_user_ok($new_name, $new_uid) ) { if( defined getpwnam($new_name) ) { if( $system ) { dief(_("The user `%s' already exists, and is not a system user.\n"),$new_name); } else { dief(_("The user `%s' already exists.\n"),$new_name); } } dief(_("The UID %s is already in use.\n"),$new_uid) if (defined($new_uid) && getpwuid($new_uid)); } if ($make_group_also) { if( !$system || !existing_group_ok($new_name, $new_uid) ) { dief(_("The group `%s' already exists.\n"),$new_name) if (defined getgrnam($new_name)); dief(_("The GID %s is already in use.\n"),$new_uid) if (defined($new_uid) && defined(getgrgid($new_uid))); } } else { dief(_("The group `%s' does not exist.\n"),$ingroup_name) if ($ingroup_name && !defined(getgrnam($ingroup_name))); dief(_("The GID %s does not exist.\n"),$new_gid) if (defined($new_gid) && !defined(getgrgid($new_gid))); } } # copy files, directories, symlinks sub copy_to_dir { my($fromdir, $file, $todir, $newu, $newg, $sgiddir) = @_; if (-l "$fromdir/$file") { my $target=readlink("$fromdir/$file") or &cleanup("readlink: $!\n"); my $curgid="$)"; my $curuid="$>"; my $error=""; $)="$newg"; $>="$newu"; symlink("$target", "$todir/$file"); $error="$!"; $>="$curuid"; $)="$curgid"; if( "$error" ne "" ) { &cleanup("symlink: $!\n"); } return; } elsif (-f "$fromdir/$file") { open (FILE, "$fromdir/$file") || &cleanup("open $fromdir/$file: $!"); open (NEWFILE, ">$todir/$file") || &cleanup("open >$todir/$file: $!"); (print NEWFILE ) || &cleanup("print $todir/$file: $!"); close FILE; close(NEWFILE) || &cleanup("close $todir/$file "); } elsif (-d "$fromdir/$file") { mkdir("$todir/$file", 700) || &cleanup("mkdir: $!"); } else { &cleanup("Can't deal with $fromdir/$file. " ."Not a dir, file, or symlink.\n"); } chown($newu, $newg, "$todir/$file") || &cleanup("chown $newu:$newg $todir/$file: $!\n"); $perm = (stat("$fromdir/$file"))[2] & 07777; $perm |= 02000 if (-d "$fromdir/$file" && ($perm & 010) && $sgiddir); chmod($perm, "$todir/$file") || &cleanup("chmod $todir/$file: $!\n"); } # is name ok? sub checkname { my ($name) = @_; if ($name !~ /^[-_\.A-Za-z0-9]*\$?$/) { print STDERR "$0: ",_("To avoid problems, the username should consist of letters, digits, underscores, periods and dashes. For compatibility with Samba machine accounts \$ is also supported at the end of the username\n"); exit 1; } if ($name !~ qr/$config{"name_regex"}/) { if ($allow_badname) { print _("Allowing use of questionable username.\n") if ($verbose); } else { print STDERR "$0: ",_("Please enter a username matching the regular expression configured via the name_regex configuration variable. Use the `--force-badname' option to relax this check or reconfigure name_regex.\n"); exit 1; } } } # return the smallest X such that # $min <= X <= $max, and X is not an element of @ids # or -1 if no such X sub first_avail_id { my ($min, $max, @ids) = @_; @ids = sort {$a <=> $b} @ids; printf _("Selecting from %s %s (%s).\n"),$min,$max,join(",",@ids) if $debugging; while ($min <= $max) { return $min if ($min < $ids[0] || @ids==0); shift @ids if ($min > $ids[0]); $min++ if ($min == $ids[0]); } return -1; # nothing available } # return an array containing all the GIDs sub get_current_gids { my(@gids, $gid); setgrent; push @gids, $gid while defined($gid = (getgrent)[2]); endgrent; return @gids; } # return an array containing all the UIDs sub get_current_uids { my(@uids, $uid); setpwent; push @uids, $uid while defined($uid = (getpwent)[2]); endpwent; return @uids; } sub ch_gecos { my $gecos = shift; if($gecos =~ /,/) { my($gecos_name,$gecos_room,$gecos_work,$gecos_home,$gecos_other) = split(/,/,$gecos); &systemcall('/usr/bin/chfn', '-f', $gecos_name, '-r', $gecos_room, $new_name); &systemcall('/usr/bin/chfn','-w',$gecos_work,$new_name) if(defined($gecos_work)); &systemcall('/usr/bin/chfn','-h',$gecos_home,$new_name) if(defined($gecos_home)); &systemcall('/usr/bin/chfn','-o',$gecos_other,$new_name) if(defined($gecos_other)); } else { &systemcall('/usr/bin/chfn', '-f', $gecos, $new_name); } } # user is member of group? sub user_is_member { my($user, $group) = @_; for (split(/ /, (getgrnam($group))[3])) { return 1 if ($user eq $_); } return 0; } sub cleanup { print "@{_}Cleaning up.\n"; if ($undohome) { printf _("Removing directory `%s'\n"),$undohome; system('rm', '-rf', $undohome); } if ($undouser) { printf _("Removing user `%s'.\n"),$undouser; system('userdel', $undouser); } if ($undogroup) { printf _("Removing group `%s'.\n"),$undogroup; system('groupdel', $undogroup); } # do we need to invalidate the nscd cache here, too? exit 1; } sub handler { my($sig) = @_; &cleanup("Caught a SIG$sig.\n"); } sub version { print "$0: add a user or group to the system. Version VERSION Copyright (C) 1997, 1998, 1999 Guy Maor Copyright (C) 1995 Ian Murdock , Ted Hajek , This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, /usr/share/common-licenses/GPL, for more details. "; } sub usage { printf _( "adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] user Add a normal user adduser --system [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--gecos GECOS] [--group | --ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] user Add a system user adduser --group [--gid ID] group addgroup [--gid ID] group Add a user group addgroup --system [--gid ID] group Add a system group adduser user group Add an existing user to an existing group Global configuration is in the file %s. Other options are [--quiet] [--force-badname] [--help] [--version] [--conf FILE]. "),$defaults; } sub systemcall { my $c = join(' ', @_); print "$c\n" if $debugging; if (system(@_)) { &cleanup("$0: `$c' returned error code " . ($?>>8) . ". Aborting.\n") if ($?>>8); &cleanup("$0: `$c' exited from signal " . ($?&255) . ". Aborting.\n"); } } sub get_dir_mode { my $setgid = shift; # no longer make home directories setgid per default (closes: #64806) $setgid = 0 unless $config{"setgid_home"} =~ /yes/i; my $dir_mode = $config{"dir_mode"}; if(!defined($dir_mode) || ! ($dir_mode =~ /[0-7]{3}/ || $dir_mode =~ /[0-7]{4}/)) { $dir_mode = $setgid ? 2755 : 0755; } else { $dir_mode = $config{"dir_mode"}; if($setgid && (length($dir_mode) == 3 || $dir_mode =~ /^[0-1|4-5][0-7]{3}$/)) { $dir_mode += 2000; } } return oct($dir_mode); } # Local Variables: # mode:cperl # cperl-indent-level:4 # End: