Report forwarded to debian-bugs-dist@lists.debian.org, Guy Maor <maor@debian.org>:
Bug#43527; Package adduser.
debian-bugs-dist@lists.debian.orgGuy Maor
Subject: Bug#43527: "adduser" does not check for qmail "~alias/.qmail-newuser" alias
Reply-To: "I. Forbes" , 43527@bugs.debian.org
Resent-From: "I. Forbes"
Resent-To: debian-bugs-dist@lists.debian.org
Resent-CC: Guy Maor
Resent-Date: Thu, 26 Aug 1999 09:03:07 GMT
Resent-Message-ID:
Resent-Sender: iwj@debian.org
X-Debian-PR-Message: report 43527
X-Debian-PR-Package: adduser
X-Debian-PR-Keywords:
X-Loop: owner@bugs.debian.org
Received: via spool by bugs@bugs.debian.org id=B.93565792522877
(code B ref -1); Thu, 26 Aug 1999 09:03:07 GMT
From: "I. Forbes"
To: submit@bugs.debian.org
Date: Thu, 26 Aug 1999 10:54:16 +0200
MIME-Version: 1.0
Content-type: text/plain; charset=US-ASCII
Content-transfer-encoding: 7BIT
Priority: normal
X-mailer: Pegasus Mail for Win32 (v3.01d)
Package: adduser
Version: 3.8
The "qmail" MTA (see www.qmail.org) is now available on debian via the package "qmail-src".
This MTA does a few unconventional things, one of them is an alternate method of handling e-
mail "alias" names. (Latest versions also honour the accepted /etc/aliases file).
There is a user "alias" defined on the system. If a file named:
~alias/.qmail-newuser
is present, the contents of that file are treated as a ".qmail" file, (which is a variation of
sendmail's .forward file). Mail addressed to "newuser" will then be delivered according to the
instructions contained in that file.
This is well and good for qmail - it is all a bit different but it works very well.
The trouble is that if the file
~alias/.qmail-newuser
exists, it is not a good idea to go and create a new user called "newuser" as unpredictable
things will happen to his mail.
My "adduser" script has been patched to complain if you try and do this. I have attached it for
your information and possible inclusion in future released of adduser. Search for "qmail" for a
quick look at what has changed.
The qmail mechanism is complex. It can react to
~alias/.qmail-newuser-default
or
~alias/.qmail-new-user
My patches were put together by a student who helped me (Craig Bates craig@zsd.co.za), I am
not sure they will work for all of these possibilities.
Thanks
Ian Forbes
#!/usr/bin/perl -w
#
# adduser 3.8
#
# adduser: a utility to add users to the system
# addgroup: a utility to add groups to the system
# Copyright (C) 1997 Guy Maor
# Copyright (C) 1995 Ted Hajek
# Ian A. Murdock
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
####################
# the program can be called as:
#
# adduser [--home DIR] [--uid ID] [--ingroup GROUP | --gid ID]
# [--disabled-password] [--gecos GECOS] user
# add a normal user to the system
# example: adduser fred
# $action = "adduser"
#
# adduser --group [--gid ID] group
# addgroup [--gid ID] group
# add a system group
# example: addgroup --quiet www-data
# $action = "addgroup"
#
# adduser --system [--home DIR] [--uid ID] [--group | --ingroup GROUP
# | --gid ID] [--disabled-password] [--gecos GECOS] user
# add a system user. Create a like-named, like-id'd group with
# --group, add to an existing group with --ingroup or --gid. Add
# to "nogroup" with neither.
# example: adduser --system --home /home/gopher-data --group gopher
# $action = "addsysuser"
#
# adduser user group
# add the existing user to an existing group.
# $action = "addusertogroup"
#
# all commands take the following options:
# --quiet don't give progress information on STDOUT
# --force-badname disable checking of names for funny characters
# --help usage message
# --version version number and copyright
# --conf FILE use FILE instead of /etc/adduser.conf
############
# Modified by Craig Bates - 29-01-99 to check qmail aliases.
$verbose = 1; # should we be verbose?
$allow_badname = 0; # should we allow bad names?
$ask_passwd = 1; # ask for a passwd?
$defaults = "/etc/adduser.conf";
$nogroup_id = getgrnam("nogroup") || 65534;
$0 =~ s+.*/++;
$config{"qmail_alias_dir"} = "/var/qmail/alias/";
$config{"dshell"} = "/bin/bash";
$config{"first_system_uid"} = 100;
$config{"last_system_uid"} = 999;
$config{"first_uid"} = 1000;
$config{"last_uid"} = 29999;
$config{"dhome"} = "/home";
$config{"skel"} = "/etc/skel";
$config{"usergroups"} = "yes";
$config{"users_gid"} = "100";
$config{"grouphomes"} = "no";
$config{"letterhomes"} = "no";
$config{"quotauser"} = "";
$action = $0 eq "addgroup" ? "addgroup" : "adduser";
while ($arg = shift(@ARGV)) {
die "$0: No options allowed after names.\n"
if ($names[0] && $arg =~ /^--/);
if ($arg eq "--quiet") {
$verbose = 0;
} elsif ($arg eq "--force-badname") {
$allow_badname = 1;
} elsif ($arg eq "--help") {
&usage();
exit 0;
} elsif ($arg eq "--version") {
&version();
exit 0;
} elsif ($arg eq "--system") {
$action = "addsysuser";
} elsif ($arg eq "--group") {
$found_group_opt = 1;
} elsif ($arg eq "--ingroup") {
die "$0: --ingroup requires an argument.\n"
if (!($ingroup_name = shift(@ARGV)));
} elsif ($arg eq "--home") {
die "$0: --home requires an argument.\n"
if (!($special_home = shift(@ARGV)));
print "$0: Warning: The home dir you specified already exists.\n"
if (-d $special_home && $verbose);
die "$0: The home dir must be an absolute path.\n"
if ($special_home !~ m+^/+ );
} elsif ($arg eq "--gecos") {
$new_gecos = shift(@ARGV);
} elsif ($arg eq "--disabled-password") {
$ask_passwd = 0;
} elsif ($arg eq "--uid") {
die "$0: --uid requires a numeric argument.\n"
if (!($new_uid = shift(@ARGV)) || $new_uid !~ /^\d+$/);
} elsif ($arg eq "--gid") {
die "$0: --gid requires a numeric argument.\n"
if (!($new_gid = shift(@ARGV)) || $new_gid !~ /^\d+$/);
} elsif ($arg eq "--conf") {
die "$0: --conf requires an argument.\n"
if (!($defaults = shift(@ARGV)));
die "$0: `$defaults' doesn't exist.\n"
if (! -f $defaults);
} elsif ($arg eq "--debug") {
$debugging = 1;
} elsif ($arg =~ /^--/) { # bad argument!
die "$0: Unknown argument `$arg'.\n";
} else { # it's a username
push (@names, $arg);
}
}
die "$0: Only root may add a user or group to the system.\n" if ($> != 0);
die "$0: I need a name to add.\n" if (@names == 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;
}
else {
$action = "addgroup";
}
}
die "$0: --group, --ingroup, and --gid options are mutually exclusive.\n" if
($action ne "addgroup" &&
defined($found_group_opt) +defined($ingroup_name) +defined($new_gid) > 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 = "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 $new_name;
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler';
##############
## addgroup ##
##############
if ($action eq "addgroup") {
die "$0: The group `$new_name' already exists.\n"
if (getgrnam($new_name));
die "$0: The GID `$new_gid' is already in use.\n"
if (defined($new_gid) && getgrgid($new_gid));
if (!defined($new_gid)) {
$new_gid = &first_avail_id($config{"first_system_uid"},
$config{"last_system_uid"},
&get_current_gids);
die "$0: No GID is available in the range ",
"$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n",
"(FIRST_SYS_UID - LAST_SYS_UID). ",
"Group `$new_name' not created.\n" if ($new_gid == -1);
}
print "Adding group $new_name ($new_gid)...\n" if $verbose;
&systemcall('groupadd', '-g', $new_gid, $new_name);
print "Done.\n" if $verbose;
exit 0;
}
####################
## addusertogroup ##
####################
elsif ($action eq "addusertogroup") {
die "$0: The user `$existing_user' doesn't exist.\n"
if (!getpwnam($existing_user));
die "$0: The group `$existing_group' doesn't exist.\n"
if (!getgrnam($existing_group));
if (&user_is_member($existing_user, $existing_group)) {
print "The user `$existing_user' is already a member of ",
"`$existing_group'.\n" if $verbose;
exit 0; # not really an error
}
print "Adding user $existing_user to group $existing_group...\n"
if $verbose;
&systemcall('usermod', '-G',
join(",", get_users_groups($existing_user), $existing_group),
$existing_user);
print "Done.\n" if $verbose;
exit 0;
}
################
## addsysuser ##
################
elsif ($action eq "addsysuser") {
$new_gid = $nogroup_id
if (!$ingroup_name && !defined($new_gid) && !$make_group_also);
&check_user_group();
print "Adding system user $new_name...\n" 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);
die "$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). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
$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);
die "$0: No UID is available in the range ",
"$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n",
"(FIRST_SYS_UID - LAST_SYS_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
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"; }
}
if ($make_group_also) {
print "Adding new group $new_name ($new_gid).\n" if $verbose;
$undogroup = $new_name;
&systemcall('groupadd', '-g', $new_gid, $new_name);
}
print "Adding new user $new_name ($new_uid) with group $ingroup_name.\n"
if $verbose;
$home_dir = $special_home || &homedir($new_name, $ingroup_name);
$undouser = $new_name;
&systemcall('useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
'/bin/false', '-u', $new_uid, $new_name);
&systemcall('chfn', '-f', $new_gecos, $new_name) if ($new_gecos);
if (-d $home_dir) {
print "Home directory $home_dir already exists.\n" if $verbose;
} else {
print "Creating home directory $home_dir.\n" 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 = $make_group_also ? 02755 : 0755;
chmod ($dir_mode, $home_dir) ||
&cleanup("chmod $dir_mode $home_dir: $!\n");
}
exit 0;
}
#############
## adduser ##
#############
elsif ($action eq "adduser") {
if (!$ingroup_name && !defined($new_gid)) {
if ($config{"usergroups"} eq "yes") { $make_group_also = 1; }
else { $new_gid = $config{"users_gid"}; }
}
&check_user_group();
print "Adding user $new_name...\n" if $verbose;
if (!defined($new_uid) && $make_group_also) {
$new_uid = &first_avail_id($config{"first_uid"},
$config{"last_uid"},
&get_current_uids, &get_current_gids);
die "$0: No UID/GID pair is available in the range ",
"$config{\"first_uid\"} - $config{\"last_uid\"}\n",
"(FIRST_UID - LAST_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
$new_gid = $new_uid;
$ingroup_name = $new_name;
}
elsif (!defined($new_uid) && !$make_group_also) {
$new_uid = &first_avail_id($config{"first_uid"},
$config{"last_uid"},
&get_current_uids);
die "$0: No UID is available in the range ",
"$config{\"first_uid\"} - $config{\"last_uid\"}\n",
"(FIRST_UID - LAST_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
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"; }
}
if ($make_group_also) {
print "Adding new group $new_name ($new_gid).\n" if $verbose;
$undogroup = $new_name;
&systemcall('groupadd', '-g', $new_gid, $new_name);
}
print "Adding new user $new_name ($new_uid) with group $ingroup_name.\n"
if $verbose;
$home_dir = $special_home || &homedir($new_name, $ingroup_name);
$undouser = $new_name;
&systemcall('useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
$config{dshell}, '-u', $new_uid, $new_name);
if (-d $home_dir) {
print "Home directory $home_dir already exists. Not copying from",
" $config{skel}\n" if $verbose;
}
else {
print "Creating home directory $home_dir.\n" 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 = $make_group_also ? 02755 : 0755;
chmod ($dir_mode, $home_dir) ||
&cleanup("chmod $dir_mode $home_dir: $!\n");
if ($config{"skel"}) {
print "Copying files from $config{skel}\n" if $verbose;
open(FIND, "cd $config{skel}; find . -print |")
|| &cleanup("fork for find: $!\n");
while () {
chop;
next if ($_ eq ".");
©_to_dir($config{"skel"}, $_, $home_dir, $new_uid,
$new_gid, $make_group_also);
}
}
}
if ($ask_passwd) {
&systemcall('passwd', $new_name);
}
if ($new_gecos) {
&systemcall('chfn', '-f', $new_gecos, $new_name);
}
else {
for (;;) {
&systemcall('chfn', $new_name);
print "Is the information correct? [y/n] ";
chop ($answer=);
last if ($answer =~ /^y/i);
}
}
if ($config{"quotauser"}) {
print "Setting quota from $config{quotauser}.\n";
&systemcall('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;
}
# 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];
}
# 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;
}
1;
}
sub check_user_group() {
die "$0: The user `$new_name' already exists.\n" if (getpwnam($new_name));
# qmail alias check added by CVB
opendir(DIR, $config{"qmail_alias_dir"});
@file = readdir(DIR);
closedir(DIR);
foreach (@file) {
if ($_ eq ".qmail-$new_name") {
die "$new_name is a qmail alias\n";
}
}
#########
die "$0: The UID `$new_uid' already exists.\n"
if (defined($new_uid) && getpwuid($new_uid));
if ($make_group_also) {
die "$0: The group `$new_name' already exists.\n"
if (getgrnam($new_name));
die "$0: The GID `$new_uid' already exists.\n"
if (defined($new_uid) && getgrgid($new_uid));
}
else {
die "$0: The group `$ingroup_name' doesn't exist.\n"
if ($ingroup_name && !getgrnam($ingroup_name));
die "$0: The GID `$new_gid' doesn't exist.\n"
if (defined($new_gid) && !getgrgid($new_gid));
}
}
# copy files, directories, symlinks
sub copy_to_dir {
my($fromdir, $file, $todir, $newu, $newg, $sgiddir) = @_;
if (-l "$fromdir/$file") {
symlink(readlink("$fromdir/$file"), "$todir/$file")
|| &cleanup("symlink: $!\n");
}
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 ($allow_badname && $name !~ /^[A-Za-z_][-_A-Za-z0-9]*$/) {
print STDERR
"$0: To avoid problems, the username should consist of a letter or
underscore followed by letters, digits, underscores, and dashes.\n";
exit 1;
}
elsif ($name !~ /^[a-z][a-z0-9]*$/) {
if (!$allow_badname) {
print STDERR
"$0: Please enter a username consisting of a lower case letter
followed by lower case letters and numbers. Use the `--force-badname'
option to allow underscores, dashes, and uppercase.\n";
exit 1;
}
print "Allowing use of questionable username.\n" if ($verbose);
}
}
# 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;
print "Selecting from $min $max (" . join(",",@ids) . ").\n" if $debugging;
while ($min <= $max) {
return $min if ($min < $ids[0] || @ids==0);
shift @ids if ($min > $ids[0]);
$min++ if ($min == $ids[0]);
}
-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;
@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;
@uids;
}
# return a user's groups
sub get_users_groups {
my($user) = @_;
my($name,$members,@groups);
setgrent;
while (($name,$members) = (getgrent)[0,3]) {
for (split(/ /, $members)) {
if ($user eq $_) {
push @groups, $name;
last;
}
}
}
endgrent;
@groups;
}
# user is member of group?
sub user_is_member {
my($user, $group) = @_;
for (split(/ /, (getgrnam($group))[3])) {
return 1 if ($user eq $_);
}
0;
}
# parse the configuration file
sub read_config {
my ($conf_file) = @_;
my ($var, $lcvar, $val);
if (! -f $conf_file) {
print "$0: $conf_file doesn't exist. Using defaults.\n" if $verbose;
return;
}
open (CONF, $conf_file) || die "$0: $conf_file: $!\n";
while () {
chomp;
next if /^#/ || /^\s*$/;
if ((($var, $val) = /^\s*(\S+)\s*=\s*(.*)/) != 2) {
warn "$0: Couldn't parse $conf_file:$..\n";
next;
}
$lcvar = lc $var;
if (!defined($config{$lcvar})) {
warn "$0: Unknown variable `$var' at $conf_file:$..\n";
next;
}
$val =~ s/^"(.*)"$/$1/;
$val =~ s/^'(.*)'$/$1/;
$config{$lcvar} = $val;
}
close CONF || die "$!";
}
sub systemcall {
my $c = join(' ', @_);
print "$c\n" if $debugging;
system(@_) && &cleanup("$0: `$c' returned error code $?. Aborting.\n");
}
sub cleanup {
print "@{_}Cleaning up.\n";
if ($undohome) {
print "Removing directory `$undohome'\n";
system('rm', '-rf', $undohome);
}
if ($undouser) {
print "Removing user `$undouser'.\n";
system('userdel', $undouser);
}
if ($undogroup) {
print "Removing group `$undogroup'.\n";
system('groupdel', $undogroup);
}
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 3.8
Copyright (C) 1997 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/doc/copyright/GPL, for more details.
";
}
sub usage {
print "adduser [--home DIR] [--uid ID] [--ingroup GROUP | --gid ID]
[--disabled-password] [--gecos GECOS] user
Add a normal user
adduser --system [--home DIR] [--uid ID] [--group | --ingroup GROUP |
--gid ID] [--disabled-password] [--gecos GECOS] user
Add a system user
adduser --group [--gid ID] group
addgroup [--gid ID] group
Add a system group
adduser user group
Add an existing user to an existing group
Global configuration is in the file $defaults.
Other options are [--quiet] [--force-badname] [--help] [--version] [--conf
FILE].
";
}
---------------------------------------------------------------------
Ian Forbes ZSD
http://www.zsd.co.za
Office: +27 +21 683-1388 Fax: +27 +21 64-1106
Snail Mail: P.O. Box 46827, Glosderry, 7702, South Africa
---------------------------------------------------------------------
Acknowledgement sent to "I. Forbes" <iforbes@zsd.co.za>:
New bug report received and forwarded. Copy sent to Guy Maor <maor@debian.org>.
-t
From: owner@bugs.debian.org (Debian Bug Tracking System)
To: "I. Forbes"
Subject: Bug#43527: Acknowledgement ("adduser" does not check for qmail "~alias/.qmail-newuser" alias )
Message-ID:
In-Reply-To:
References:
X-Debian-PR-Message: ack 43527
Thank you for the problem report you have sent regarding Debian.
This is an automatically generated reply, to let you know your message has
been received. It is being forwarded to the developers' mailing list for
their attention; they will reply in due course.
Your message has been sent to the package maintainer(s):
Guy Maor
If you wish to submit further information on your problem, please send
it to 43527@bugs.debian.org (and *not* to
bugs@bugs.debian.org).
Please do not reply to the address at the top of this message,
unless you wish to report a problem with the bug-tracking system.
Ian Jackson
(administrator, Debian bugs database)
Received: (at submit) by bugs.debian.org; 26 Aug 1999 08:58:45 +0000
Received: (qmail 22872 invoked from network); 26 Aug 1999 08:58:15 -0000
Received: from nimbus.zsd.co.za (qmailr@196.25.198.2)
by master.debian.org with SMTP; 26 Aug 1999 08:58:15 -0000
Received: (qmail 16970 invoked from network); 26 Aug 1999 08:57:12 -0000
Received: from unknown (HELO discus) (192.168.1.7)
by nimbus.zsd.co.za with SMTP; 26 Aug 1999 08:57:12 -0000
From: "I. Forbes"
To: submit@bugs.debian.org
Date: Thu, 26 Aug 1999 10:54:16 +0200
MIME-Version: 1.0
Content-type: text/plain; charset=US-ASCII
Content-transfer-encoding: 7BIT
Subject: "adduser" does not check for qmail "~alias/.qmail-newuser" alias
Priority: normal
X-mailer: Pegasus Mail for Win32 (v3.01d)
Package: adduser
Version: 3.8
The "qmail" MTA (see www.qmail.org) is now available on debian via the package "qmail-src".
This MTA does a few unconventional things, one of them is an alternate method of handling e-
mail "alias" names. (Latest versions also honour the accepted /etc/aliases file).
There is a user "alias" defined on the system. If a file named:
~alias/.qmail-newuser
is present, the contents of that file are treated as a ".qmail" file, (which is a variation of
sendmail's .forward file). Mail addressed to "newuser" will then be delivered according to the
instructions contained in that file.
This is well and good for qmail - it is all a bit different but it works very well.
The trouble is that if the file
~alias/.qmail-newuser
exists, it is not a good idea to go and create a new user called "newuser" as unpredictable
things will happen to his mail.
My "adduser" script has been patched to complain if you try and do this. I have attached it for
your information and possible inclusion in future released of adduser. Search for "qmail" for a
quick look at what has changed.
The qmail mechanism is complex. It can react to
~alias/.qmail-newuser-default
or
~alias/.qmail-new-user
My patches were put together by a student who helped me (Craig Bates craig@zsd.co.za), I am
not sure they will work for all of these possibilities.
Thanks
Ian Forbes
#!/usr/bin/perl -w
#
# adduser 3.8
#
# adduser: a utility to add users to the system
# addgroup: a utility to add groups to the system
# Copyright (C) 1997 Guy Maor
# Copyright (C) 1995 Ted Hajek
# Ian A. Murdock
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
####################
# the program can be called as:
#
# adduser [--home DIR] [--uid ID] [--ingroup GROUP | --gid ID]
# [--disabled-password] [--gecos GECOS] user
# add a normal user to the system
# example: adduser fred
# $action = "adduser"
#
# adduser --group [--gid ID] group
# addgroup [--gid ID] group
# add a system group
# example: addgroup --quiet www-data
# $action = "addgroup"
#
# adduser --system [--home DIR] [--uid ID] [--group | --ingroup GROUP
# | --gid ID] [--disabled-password] [--gecos GECOS] user
# add a system user. Create a like-named, like-id'd group with
# --group, add to an existing group with --ingroup or --gid. Add
# to "nogroup" with neither.
# example: adduser --system --home /home/gopher-data --group gopher
# $action = "addsysuser"
#
# adduser user group
# add the existing user to an existing group.
# $action = "addusertogroup"
#
# all commands take the following options:
# --quiet don't give progress information on STDOUT
# --force-badname disable checking of names for funny characters
# --help usage message
# --version version number and copyright
# --conf FILE use FILE instead of /etc/adduser.conf
############
# Modified by Craig Bates - 29-01-99 to check qmail aliases.
$verbose = 1; # should we be verbose?
$allow_badname = 0; # should we allow bad names?
$ask_passwd = 1; # ask for a passwd?
$defaults = "/etc/adduser.conf";
$nogroup_id = getgrnam("nogroup") || 65534;
$0 =~ s+.*/++;
$config{"qmail_alias_dir"} = "/var/qmail/alias/";
$config{"dshell"} = "/bin/bash";
$config{"first_system_uid"} = 100;
$config{"last_system_uid"} = 999;
$config{"first_uid"} = 1000;
$config{"last_uid"} = 29999;
$config{"dhome"} = "/home";
$config{"skel"} = "/etc/skel";
$config{"usergroups"} = "yes";
$config{"users_gid"} = "100";
$config{"grouphomes"} = "no";
$config{"letterhomes"} = "no";
$config{"quotauser"} = "";
$action = $0 eq "addgroup" ? "addgroup" : "adduser";
while ($arg = shift(@ARGV)) {
die "$0: No options allowed after names.\n"
if ($names[0] && $arg =~ /^--/);
if ($arg eq "--quiet") {
$verbose = 0;
} elsif ($arg eq "--force-badname") {
$allow_badname = 1;
} elsif ($arg eq "--help") {
&usage();
exit 0;
} elsif ($arg eq "--version") {
&version();
exit 0;
} elsif ($arg eq "--system") {
$action = "addsysuser";
} elsif ($arg eq "--group") {
$found_group_opt = 1;
} elsif ($arg eq "--ingroup") {
die "$0: --ingroup requires an argument.\n"
if (!($ingroup_name = shift(@ARGV)));
} elsif ($arg eq "--home") {
die "$0: --home requires an argument.\n"
if (!($special_home = shift(@ARGV)));
print "$0: Warning: The home dir you specified already exists.\n"
if (-d $special_home && $verbose);
die "$0: The home dir must be an absolute path.\n"
if ($special_home !~ m+^/+ );
} elsif ($arg eq "--gecos") {
$new_gecos = shift(@ARGV);
} elsif ($arg eq "--disabled-password") {
$ask_passwd = 0;
} elsif ($arg eq "--uid") {
die "$0: --uid requires a numeric argument.\n"
if (!($new_uid = shift(@ARGV)) || $new_uid !~ /^\d+$/);
} elsif ($arg eq "--gid") {
die "$0: --gid requires a numeric argument.\n"
if (!($new_gid = shift(@ARGV)) || $new_gid !~ /^\d+$/);
} elsif ($arg eq "--conf") {
die "$0: --conf requires an argument.\n"
if (!($defaults = shift(@ARGV)));
die "$0: `$defaults' doesn't exist.\n"
if (! -f $defaults);
} elsif ($arg eq "--debug") {
$debugging = 1;
} elsif ($arg =~ /^--/) { # bad argument!
die "$0: Unknown argument `$arg'.\n";
} else { # it's a username
push (@names, $arg);
}
}
die "$0: Only root may add a user or group to the system.\n" if ($> != 0);
die "$0: I need a name to add.\n" if (@names == 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;
}
else {
$action = "addgroup";
}
}
die "$0: --group, --ingroup, and --gid options are mutually exclusive.\n" if
($action ne "addgroup" &&
defined($found_group_opt) +defined($ingroup_name) +defined($new_gid) > 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 = "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 $new_name;
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler';
##############
## addgroup ##
##############
if ($action eq "addgroup") {
die "$0: The group `$new_name' already exists.\n"
if (getgrnam($new_name));
die "$0: The GID `$new_gid' is already in use.\n"
if (defined($new_gid) && getgrgid($new_gid));
if (!defined($new_gid)) {
$new_gid = &first_avail_id($config{"first_system_uid"},
$config{"last_system_uid"},
&get_current_gids);
die "$0: No GID is available in the range ",
"$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n",
"(FIRST_SYS_UID - LAST_SYS_UID). ",
"Group `$new_name' not created.\n" if ($new_gid == -1);
}
print "Adding group $new_name ($new_gid)...\n" if $verbose;
&systemcall('groupadd', '-g', $new_gid, $new_name);
print "Done.\n" if $verbose;
exit 0;
}
####################
## addusertogroup ##
####################
elsif ($action eq "addusertogroup") {
die "$0: The user `$existing_user' doesn't exist.\n"
if (!getpwnam($existing_user));
die "$0: The group `$existing_group' doesn't exist.\n"
if (!getgrnam($existing_group));
if (&user_is_member($existing_user, $existing_group)) {
print "The user `$existing_user' is already a member of ",
"`$existing_group'.\n" if $verbose;
exit 0; # not really an error
}
print "Adding user $existing_user to group $existing_group...\n"
if $verbose;
&systemcall('usermod', '-G',
join(",", get_users_groups($existing_user), $existing_group),
$existing_user);
print "Done.\n" if $verbose;
exit 0;
}
################
## addsysuser ##
################
elsif ($action eq "addsysuser") {
$new_gid = $nogroup_id
if (!$ingroup_name && !defined($new_gid) && !$make_group_also);
&check_user_group();
print "Adding system user $new_name...\n" 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);
die "$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). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
$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);
die "$0: No UID is available in the range ",
"$config{\"first_system_uid\"} - $config{\"last_system_uid\"}\n",
"(FIRST_SYS_UID - LAST_SYS_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
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"; }
}
if ($make_group_also) {
print "Adding new group $new_name ($new_gid).\n" if $verbose;
$undogroup = $new_name;
&systemcall('groupadd', '-g', $new_gid, $new_name);
}
print "Adding new user $new_name ($new_uid) with group $ingroup_name.\n"
if $verbose;
$home_dir = $special_home || &homedir($new_name, $ingroup_name);
$undouser = $new_name;
&systemcall('useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
'/bin/false', '-u', $new_uid, $new_name);
&systemcall('chfn', '-f', $new_gecos, $new_name) if ($new_gecos);
if (-d $home_dir) {
print "Home directory $home_dir already exists.\n" if $verbose;
} else {
print "Creating home directory $home_dir.\n" 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 = $make_group_also ? 02755 : 0755;
chmod ($dir_mode, $home_dir) ||
&cleanup("chmod $dir_mode $home_dir: $!\n");
}
exit 0;
}
#############
## adduser ##
#############
elsif ($action eq "adduser") {
if (!$ingroup_name && !defined($new_gid)) {
if ($config{"usergroups"} eq "yes") { $make_group_also = 1; }
else { $new_gid = $config{"users_gid"}; }
}
&check_user_group();
print "Adding user $new_name...\n" if $verbose;
if (!defined($new_uid) && $make_group_also) {
$new_uid = &first_avail_id($config{"first_uid"},
$config{"last_uid"},
&get_current_uids, &get_current_gids);
die "$0: No UID/GID pair is available in the range ",
"$config{\"first_uid\"} - $config{\"last_uid\"}\n",
"(FIRST_UID - LAST_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
$new_gid = $new_uid;
$ingroup_name = $new_name;
}
elsif (!defined($new_uid) && !$make_group_also) {
$new_uid = &first_avail_id($config{"first_uid"},
$config{"last_uid"},
&get_current_uids);
die "$0: No UID is available in the range ",
"$config{\"first_uid\"} - $config{\"last_uid\"}\n",
"(FIRST_UID - LAST_UID). ",
"User `$new_name' not created.\n" if ($new_uid == -1);
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"; }
}
if ($make_group_also) {
print "Adding new group $new_name ($new_gid).\n" if $verbose;
$undogroup = $new_name;
&systemcall('groupadd', '-g', $new_gid, $new_name);
}
print "Adding new user $new_name ($new_uid) with group $ingroup_name.\n"
if $verbose;
$home_dir = $special_home || &homedir($new_name, $ingroup_name);
$undouser = $new_name;
&systemcall('useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
$config{dshell}, '-u', $new_uid, $new_name);
if (-d $home_dir) {
print "Home directory $home_dir already exists. Not copying from",
" $config{skel}\n" if $verbose;
}
else {
print "Creating home directory $home_dir.\n" 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 = $make_group_also ? 02755 : 0755;
chmod ($dir_mode, $home_dir) ||
&cleanup("chmod $dir_mode $home_dir: $!\n");
if ($config{"skel"}) {
print "Copying files from $config{skel}\n" if $verbose;
open(FIND, "cd $config{skel}; find . -print |")
|| &cleanup("fork for find: $!\n");
while () {
chop;
next if ($_ eq ".");
©_to_dir($config{"skel"}, $_, $home_dir, $new_uid,
$new_gid, $make_group_also);
}
}
}
if ($ask_passwd) {
&systemcall('passwd', $new_name);
}
if ($new_gecos) {
&systemcall('chfn', '-f', $new_gecos, $new_name);
}
else {
for (;;) {
&systemcall('chfn', $new_name);
print "Is the information correct? [y/n] ";
chop ($answer=);
last if ($answer =~ /^y/i);
}
}
if ($config{"quotauser"}) {
print "Setting quota from $config{quotauser}.\n";
&systemcall('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;
}
# 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];
}
# 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;
}
1;
}
sub check_user_group() {
die "$0: The user `$new_name' already exists.\n" if (getpwnam($new_name));
# qmail alias check added by CVB
opendir(DIR, $config{"qmail_alias_dir"});
@file = readdir(DIR);
closedir(DIR);
foreach (@file) {
if ($_ eq ".qmail-$new_name") {
die "$new_name is a qmail alias\n";
}
}
#########
die "$0: The UID `$new_uid' already exists.\n"
if (defined($new_uid) && getpwuid($new_uid));
if ($make_group_also) {
die "$0: The group `$new_name' already exists.\n"
if (getgrnam($new_name));
die "$0: The GID `$new_uid' already exists.\n"
if (defined($new_uid) && getgrgid($new_uid));
}
else {
die "$0: The group `$ingroup_name' doesn't exist.\n"
if ($ingroup_name && !getgrnam($ingroup_name));
die "$0: The GID `$new_gid' doesn't exist.\n"
if (defined($new_gid) && !getgrgid($new_gid));
}
}
# copy files, directories, symlinks
sub copy_to_dir {
my($fromdir, $file, $todir, $newu, $newg, $sgiddir) = @_;
if (-l "$fromdir/$file") {
symlink(readlink("$fromdir/$file"), "$todir/$file")
|| &cleanup("symlink: $!\n");
}
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 ($allow_badname && $name !~ /^[A-Za-z_][-_A-Za-z0-9]*$/) {
print STDERR
"$0: To avoid problems, the username should consist of a letter or
underscore followed by letters, digits, underscores, and dashes.\n";
exit 1;
}
elsif ($name !~ /^[a-z][a-z0-9]*$/) {
if (!$allow_badname) {
print STDERR
"$0: Please enter a username consisting of a lower case letter
followed by lower case letters and numbers. Use the `--force-badname'
option to allow underscores, dashes, and uppercase.\n";
exit 1;
}
print "Allowing use of questionable username.\n" if ($verbose);
}
}
# 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;
print "Selecting from $min $max (" . join(",",@ids) . ").\n" if $debugging;
while ($min <= $max) {
return $min if ($min < $ids[0] || @ids==0);
shift @ids if ($min > $ids[0]);
$min++ if ($min == $ids[0]);
}
-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;
@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;
@uids;
}
# return a user's groups
sub get_users_groups {
my($user) = @_;
my($name,$members,@groups);
setgrent;
while (($name,$members) = (getgrent)[0,3]) {
for (split(/ /, $members)) {
if ($user eq $_) {
push @groups, $name;
last;
}
}
}
endgrent;
@groups;
}
# user is member of group?
sub user_is_member {
my($user, $group) = @_;
for (split(/ /, (getgrnam($group))[3])) {
return 1 if ($user eq $_);
}
0;
}
# parse the configuration file
sub read_config {
my ($conf_file) = @_;
my ($var, $lcvar, $val);
if (! -f $conf_file) {
print "$0: $conf_file doesn't exist. Using defaults.\n" if $verbose;
return;
}
open (CONF, $conf_file) || die "$0: $conf_file: $!\n";
while () {
chomp;
next if /^#/ || /^\s*$/;
if ((($var, $val) = /^\s*(\S+)\s*=\s*(.*)/) != 2) {
warn "$0: Couldn't parse $conf_file:$..\n";
next;
}
$lcvar = lc $var;
if (!defined($config{$lcvar})) {
warn "$0: Unknown variable `$var' at $conf_file:$..\n";
next;
}
$val =~ s/^"(.*)"$/$1/;
$val =~ s/^'(.*)'$/$1/;
$config{$lcvar} = $val;
}
close CONF || die "$!";
}
sub systemcall {
my $c = join(' ', @_);
print "$c\n" if $debugging;
system(@_) && &cleanup("$0: `$c' returned error code $?. Aborting.\n");
}
sub cleanup {
print "@{_}Cleaning up.\n";
if ($undohome) {
print "Removing directory `$undohome'\n";
system('rm', '-rf', $undohome);
}
if ($undouser) {
print "Removing user `$undouser'.\n";
system('userdel', $undouser);
}
if ($undogroup) {
print "Removing group `$undogroup'.\n";
system('groupdel', $undogroup);
}
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 3.8
Copyright (C) 1997 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/doc/copyright/GPL, for more details.
";
}
sub usage {
print "adduser [--home DIR] [--uid ID] [--ingroup GROUP | --gid ID]
[--disabled-password] [--gecos GECOS] user
Add a normal user
adduser --system [--home DIR] [--uid ID] [--group | --ingroup GROUP |
--gid ID] [--disabled-password] [--gecos GECOS] user
Add a system user
adduser --group [--gid ID] group
addgroup [--gid ID] group
Add a system group
adduser user group
Add an existing user to an existing group
Global configuration is in the file $defaults.
Other options are [--quiet] [--force-badname] [--help] [--version] [--conf
FILE].
";
}
---------------------------------------------------------------------
Ian Forbes ZSD
http://www.zsd.co.za
Office: +27 +21 683-1388 Fax: +27 +21 64-1106
Snail Mail: P.O. Box 46827, Glosderry, 7702, South Africa
---------------------------------------------------------------------
Severity set to `wishlist'.
Request was from Roland Bauerschmidt <rb@debian.org>
to control@bugs.debian.org.
Received: (at control) by bugs.debian.org; 1 Jul 2000 21:31:11 +0000
From roland@hbg.schule.bremen.de Sat Jul 01 16:31:11 2000
Return-path:
Received: from (www.hbg.schule.bremen.de) [195.37.106.41]
by master.debian.org with esmtp (Exim 3.12 2 (Debian))
id 138Ur1-00052L-00; Sat, 01 Jul 2000 16:31:11 -0500
Received: by www.hbg.schule.bremen.de (Postfix, from userid 1000)
id 79B382F61D; Sat, 1 Jul 2000 23:31:08 +0200 (CEST)
Date: Sat, 1 Jul 2000 23:31:08 +0200
From: Roland Bauerschmidt
To: control@bugs.debian.org
Message-ID: <20000701233108.A7920@hbg.schule.bremen.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
Sender: roland@hbg.schule.bremen.de
Delivered-To: control@bugs.debian.org
severity 43527 wishlist
thanks
as qmail is even not in the distribution I consider this as a
wishlist bug.
Roland
--
* Roland Bauerschmidt * http://www.copyleft.de/~roland/ *
* Debian GNU / Linux -- the choice of a gnu generation *
Severity set to `wishlist'.
Request was from Roland Bauerschmidt <rb@debian.org>
to control@bugs.debian.org.
Received: (at control) by bugs.debian.org; 1 Jul 2000 21:31:11 +0000
From roland@hbg.schule.bremen.de Sat Jul 01 16:31:11 2000
Return-path:
Received: from (www.hbg.schule.bremen.de) [195.37.106.41]
by master.debian.org with esmtp (Exim 3.12 2 (Debian))
id 138Ur1-00052L-00; Sat, 01 Jul 2000 16:31:11 -0500
Received: by www.hbg.schule.bremen.de (Postfix, from userid 1000)
id 79B382F61D; Sat, 1 Jul 2000 23:31:08 +0200 (CEST)
Date: Sat, 1 Jul 2000 23:31:08 +0200
From: Roland Bauerschmidt
To: control@bugs.debian.org
Message-ID: <20000701233108.A7920@hbg.schule.bremen.de>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
Sender: roland@hbg.schule.bremen.de
Delivered-To: control@bugs.debian.org
severity 43527 wishlist
thanks
as qmail is even not in the distribution I consider this as a
wishlist bug.
Roland
--
* Roland Bauerschmidt * http://www.copyleft.de/~roland/ *
* Debian GNU / Linux -- the choice of a gnu generation *
Tags added: wontfix
Request was from Roland Bauerschmidt <roland@bauerschmidt.eu.org>
to control@bugs.debian.org.
Received: (at control) by bugs.debian.org; 26 Feb 2001 01:42:27 +0000
From roland@minnesota.bauerschmidt.eu.org Sun Feb 25 19:42:27 2001
Return-path:
Received: from ultra.hbci.com [::ffff:206.230.105.5]
by master.debian.org with esmtp (Exim 3.12 1 (Debian))
id 14XCgF-0006iQ-00; Sun, 25 Feb 2001 19:42:27 -0600
Received: from localhost (postfix@[64.211.114.35])
by ultra.hbci.com (Pro-8.9.3/8.9.3) with ESMTP id TAA02827
for ; Sun, 25 Feb 2001 19:39:18 -0600 (CST)
Received: by localhost (Postfix, from userid 1000)
id E842A46824; Sun, 25 Feb 2001 19:40:35 -0600 (CST)
Date: Sun, 25 Feb 2001 19:40:35 -0600
From: Roland Bauerschmidt
To: control@bugs.debian.org
Subject: adduser
Message-ID: <20010225194035.A2200@minnesota.bauerschmidt.eu.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.3.15i
Delivered-To: control@bugs.debian.org
tag 43527 wontfix
--
Roland Bauerschmidt