/[adduser]/trunk/adduser
ViewVC logotype

Contents of /trunk/adduser

Parent Directory Parent Directory | Revision Log Revision Log


Revision 561 - (hide annotations) (download)
Wed Apr 26 15:42:33 2006 UTC (7 years, 1 month ago) by zugschlus
File size: 30744 byte(s)
fix parenthesis error
1 rb 80 #!/usr/bin/perl
2 zugschlus 324
3 rb 1 # adduser: a utility to add users to the system
4     # addgroup: a utility to add groups to the system
5 zugschlus 324 my $version = "VERSION";
6 rb 1
7 rb 6 # Copyright (C) 1997, 1998, 1999 Guy Maor <maor@debian.org>
8 rb 1 # Copyright (C) 1995 Ted Hajek <tedhajek@boombox.micro.umn.edu>
9     # Ian A. Murdock <imurdock@gnu.ai.mit.edu>
10 rb 15 # Bugfixes and other improvements Roland Bauerschmidt <rb@debian.org>
11 rb 1 # General scheme of the program adapted by the original debian 'adduser'
12     # program by Ian A. Murdock <imurdock@gnu.ai.mit.edu>.
13     #
14     # This program is free software; you can redistribute it and/or modify
15     # it under the terms of the GNU General Public License as published by
16     # the Free Software Foundation; either version 2 of the License, or
17     # (at your option) any later version.
18     #
19     # This program is distributed in the hope that it will be useful,
20     # but WITHOUT ANY WARRANTY; without even the implied warranty of
21     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22     # GNU General Public License for more details.
23     #
24     # You should have received a copy of the GNU General Public License
25     # along with this program; if not, write to the Free Software
26 rb 10 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 rb 1 #
28     #
29     ####################
30 zugschlus 220 # See the usage subroutine for explanation about how the program can be called
31     ####################
32 rb 1
33 rb 80 use warnings;
34 joerghoh-guest 528 use strict;
35 rb 52 use Debian::AdduserCommon;
36 zugschlus 255 use Getopt::Long;
37 rb 15
38 rb 6 BEGIN {
39     eval 'use Locale::gettext';
40     if ($@) {
41     *gettext = sub { shift };
42     *textdomain = sub { "" };
43     *LC_MESSAGES = sub { 5 };
44     }
45     eval {
46     require POSIX;
47     import POSIX qw(setlocale);
48     };
49     if ($@) {
50 zugschlus 286 *setlocale = sub { return 1 };
51 rb 6 }
52 zugschlus 350 eval {
53     require I18N::Langinfo;
54     import I18N::Langinfo qw(langinfo YESEXPR);
55     };
56     if ($@) {
57     *langinfo = sub { "^[yY]" };
58     *YESEXPR = sub { 1 };
59     }
60 rb 6 }
61    
62     setlocale(LC_MESSAGES, "");
63     textdomain("adduser");
64 zugschlus 350 my $yesexpr = langinfo(YESEXPR());
65 rb 6
66 zugschlus 286 my %config; # configuration hash
67 rb 1
68 zugschlus 330 my @defaults = ("/etc/adduser.conf");
69 zugschlus 286 my $nogroup_id = getgrnam("nogroup") || 65534;
70 rb 1 $0 =~ s+.*/++;
71    
72 joerghoh-guest 528 our $verbose = 1; # should we be verbose?
73     my $allow_badname = 0; # should we allow bad names?
74     my $ask_passwd = 1; # ask for a passwd?
75     my $disabled_login = 0; # leave the new account disabled?
76 rb 1
77 joerghoh-guest 528 our $configfile = undef;
78     our $found_group_opt = undef;
79     our $found_sys_opt = undef;
80     our $ingroup_name = undef;
81     our $new_firstuid = undef;
82     our $new_gecos = undef;
83     our $new_gid = undef;
84     our $new_lastuid = undef;
85     our $new_uid = undef;
86     our $no_create_home = undef;
87     our $special_home = undef;
88     our $special_shell = undef;
89 zugschlus 557 our $add_extra_groups = 0;
90 joerghoh-guest 528
91     # Global variables we need later
92     my $existing_user = undef;
93     my $existing_group = undef;
94     my $new_name = undef;
95     my $make_group_also = 0;
96     my $home_dir = undef;
97     my $undohome = undef;
98     my $undouser = undef;
99     my $undogroup = undef;
100     my $shell = undef;
101     my $first_uid = undef;
102     my $last_uid = undef;
103     my $dir_mode = undef;
104     my $perm = undef;
105    
106 joerghoh-guest 539 our @names;
107 joerghoh-guest 528
108 zugschlus 255 # Parse options, sanity checks
109 zugschlus 559 unless ( GetOptions ("quiet" => sub { $verbose = 0 },
110 zugschlus 255 "force-badname" => \$allow_badname,
111     "help|h" => sub { &usage(); exit 0 },
112     "version" => sub { &version(); exit 0 },
113     "system" => \$found_sys_opt,
114     "group" => \$found_group_opt,
115     "ingroup=s" => \$ingroup_name,
116     "home=s" => \$special_home,
117     "gecos=s" => \$new_gecos,
118     "shell=s" => \$special_shell,
119 zugschlus 337 "disabled-password" => sub { $ask_passwd = 0 },
120 zugschlus 306 "disabled-login" => sub { $disabled_login = 1; $ask_passwd = 0 },
121 zugschlus 255 "uid=i" => \$new_uid,
122     "firstuid=i" => \$new_firstuid,
123     "lastuid=i" => \$new_lastuid,
124     "gid=i" => \$new_gid,
125 zugschlus 330 "conf=s" => \$configfile,
126 zugschlus 255 "no-create-home" => \$no_create_home,
127 zugschlus 557 "add_extra_groups" => \$add_extra_groups,
128 zugschlus 561 "debug" => sub { $verbose = 2 } ) ) {
129 zugschlus 559 &usage;
130     exit 1;
131     }
132 zugschlus 255
133 zugschlus 257 # everyone can issue "--help" and "--version", but only root can go on
134 zugschlus 559 dief (gtx("Only root may add a user or group to the system.\n")) if ($> != 0);
135 zugschlus 255
136 zugschlus 330 if( defined($configfile) ) { @defaults = ($configfile); }
137 zugschlus 255
138 zugschlus 286 # detect the right mode
139     my $action = $0 eq "addgroup" ? "addgroup" : "adduser";
140 zugschlus 255 if (defined($found_sys_opt)) {
141     $action = "addsysuser" if ($action eq "adduser");
142     $action = "addsysgroup" if ($action eq "addgroup");
143     }
144 rb 1
145    
146 zugschlus 255
147 zugschlus 257 ############################
148     # checks related to @names #
149     ############################
150 zugschlus 255
151 zugschlus 257
152 joerghoh-guest 528 while (defined(my $arg = shift(@ARGV))) {
153 joerghoh-guest 549 push (@names, $arg);
154 zugschlus 120 }
155    
156 joerghoh-guest 385 if ( (! defined $names[0]) || length($names[0]) == 0 || @names > 2) {
157 zugschlus 559 dief (gtx("Only one or two names allowed.\n"));
158 zugschlus 350 }
159 zugschlus 257
160 zugschlus 255
161 rb 1 if (@names == 2) { # must be addusertogroup
162 zugschlus 559 dief (gtx("Specify only one name in this mode.\n"))
163 rb 1 if ($action eq "addsysuser" || $found_group_opt);
164     $action = "addusertogroup";
165     $existing_user = shift (@names);
166     $existing_group = shift (@names);
167     }
168     else {
169     $new_name = shift (@names);
170     }
171    
172 zugschlus 257 ###################################
173     # check for consistent parameters #
174     ###################################
175    
176 zugschlus 287 if ($action ne "addgroup" &&
177 zugschlus 293 defined($found_group_opt) +defined($ingroup_name) +defined($new_gid) > 1 ) {
178 zugschlus 559 dief (gtx("The --group, --ingroup, and --gid options are mutually exclusive.\n"));
179 zugschlus 287 }
180 zugschlus 257
181    
182     if ((defined($special_home)) && ($special_home !~ m+^/+ )) {
183 zugschlus 559 dief (gtx("The home dir must be an absolute path.\n"));
184 zugschlus 257 }
185    
186     if (defined($special_home) && $verbose) {
187 zugschlus 559 print gtx("Warning: The home dir you specified already exists.\n")
188 zugschlus 257 if (!defined($no_create_home) && -d $special_home);
189 zugschlus 559 print gtx("Warning: The home dir you specified does not exist.\n")
190 zugschlus 257 if (defined($no_create_home) && ! -d $special_home);
191     }
192    
193    
194 rb 1 if ($found_group_opt) {
195     if ($action eq "addsysuser") {
196     $make_group_also = 1;
197     }
198 rb 82 elsif ($found_sys_opt) {
199     $action = "addsysgroup";
200     }
201 rb 1 else {
202     $action = "addgroup";
203     }
204     }
205    
206    
207 joerghoh-guest 385 $ENV{"VERBOSE"} = $verbose;
208 joerghoh-guest 395 $ENV{"DEBUG"} = $verbose;
209 zugschlus 130
210 joerghoh-guest 385
211 joerghoh-guest 383 # preseed configuration data and then read the config file
212 zugschlus 330 preseed_config(\@defaults,\%config);
213 zugschlus 130
214 zugschlus 286 &checkname($new_name) if defined $new_name;
215     $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler';
216    
217 rb 1 #####
218     # OK, we've processed the arguments. $action equals one of the following,
219     # and the appropriate variables have been set:
220     #
221     # $action = "adduser"
222     # $new_name - the name of the new user.
223     # $ingroup_name | $new_gid - the group to add the user to
224     # $special_home, $new_uid, $new_gecos - optional overrides
225     # $action = "addgroup"
226     # $new_name - the name of the new group
227     # $new_gid - optional override
228 rb 82 # $action = "addsysgroup"
229     # $new_name - the name of the new group
230     # $new_gid - optional override
231 rb 1 # $action = "addsysuser"
232     # $new_name - the name of the new user
233     # $make_group_also | $ingroup_name | $new_gid | 0 - which group
234     # $special_home, $new_uid, $new_gecos - optional overrides
235     # $action = "addusertogroup"
236     # $existing_user - the user to be added
237     # $existing_group - the group to add her to
238     #####
239    
240    
241 rb 82 #################
242     ## addsysgroup ##
243     #################
244     if ($action eq "addsysgroup") {
245 zugschlus 112 # Check if requested group already exists and we can exit safely
246 joerghoh-guest 476 if (existing_group_ok($new_name, $new_gid) == 1) {
247 zugschlus 330 printf (gtx("The group `%s' already exists as a system group. Exiting...\n"), $new_name) if $verbose;
248 zugschlus 112 exit 0;
249     }
250 joerghoh-guest 476 if (existing_group_ok($new_name, $new_gid) == 2) {
251     printf (gtx("The group `%s' already exists, but has a different gid, aborting...\n"), $new_name) if $verbose;
252     exit 1;
253     }
254    
255 zugschlus 330 dief (gtx("The group `%s' already exists and is not a system group.\n"),$new_name)
256 rb 82 if (defined getgrnam($new_name));
257 zugschlus 330 dief (gtx("The GID `%s' is already in use.\n"),$new_gid)
258 rb 82 if (defined($new_gid) && defined(getgrgid($new_gid)));
259     if (!defined($new_gid)) {
260 joerghoh-guest 448 $new_gid = &first_avail_gid($config{"first_system_gid"},
261     $config{"last_system_gid"});
262 rb 82
263     if ($new_gid == -1) {
264 zugschlus 350 print STDERR "$0: ";
265     printf STDERR gtx("No GID is available in the range %d-%d (FIRST_SYS_GID - LAST_SYS_GID).\n"),$config{"first_system_gid"},$config{"last_system_gid"};
266 zugschlus 330 dief (gtx("The group `%s' was not created.\n"),$new_name);
267 rb 82 }
268     }
269    
270 zugschlus 330 printf (gtx("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose;
271 rb 82 &invalidate_nscd("group");
272     &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name);
273     &invalidate_nscd("group");
274 zugschlus 330 print (gtx("Done.\n")) if $verbose;
275 rb 82 exit 0;
276     }
277    
278    
279 rb 1 ##############
280     ## addgroup ##
281     ##############
282     if ($action eq "addgroup") {
283 zugschlus 330 dief (gtx("The group `%s' already exists.\n"),$new_name)
284 rb 13 if (defined getgrnam($new_name));
285 zugschlus 330 dief (gtx("The GID `%s' is already in use.\n"),$new_gid)
286 rb 13 if (defined($new_gid) && defined(getgrgid($new_gid)));
287 rb 1 if (!defined($new_gid)) {
288 joerghoh-guest 448 $new_gid = &first_avail_gid($config{"first_gid"},
289     $config{"last_gid"});
290 rb 82
291 rb 6 if ($new_gid == -1) {
292 zugschlus 350 print STDERR "$0: ";
293     printf STDERR gtx("No GID is available in the range %d-%d (FIRST_GID - LAST_GID).\n"),$config{"first_gid"},$config{"last_gid"};
294 zugschlus 330 dief (gtx("The group `%s' was not created.\n"),$new_name);
295 rb 6 }
296 rb 1 }
297    
298 zugschlus 330 printf (gtx("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose;
299 rb 15 &invalidate_nscd("group");
300 rb 82 &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name);
301 rb 15 &invalidate_nscd("group");
302 zugschlus 330 print (gtx("Done.\n")) if $verbose;
303 rb 1 exit 0;
304     }
305    
306    
307     ####################
308     ## addusertogroup ##
309     ####################
310 zugschlus 256 if ($action eq "addusertogroup") {
311 zugschlus 330 dief (gtx("The user `%s' does not exist.\n"),$existing_user)
312 rb 8 if (!defined getpwnam($existing_user));
313 zugschlus 330 dief (gtx("The group `%s' does not exist.\n"),$existing_group)
314 rb 15 if (!defined getgrnam($existing_group));
315 rb 1 if (&user_is_member($existing_user, $existing_group)) {
316 zugschlus 332 printf gtx("The user `%s' is already a member of `%s'.\n"),
317     $existing_user,$existing_group if $verbose;
318 rb 1 exit 0; # not really an error
319     }
320    
321 zugschlus 330 printf gtx("Adding user `%s' to group `%s'...\n"),$existing_user,$existing_group
322 rb 1 if $verbose;
323 rb 15 &invalidate_nscd();
324 rb 6 # FIXME - the next line has a race condition.
325 rb 15 #&systemcall('usermod', '-G',
326     #join(",", get_users_groups($existing_user), $existing_group),
327     #$existing_user);
328 rb 82 &systemcall('/usr/bin/gpasswd', '-M',
329 rb 15 join(',', get_group_members($existing_group), $existing_user),
330     $existing_group);
331 rb 17 #&systemcall('gpasswd', '-a',$existing_user,$existing_group);
332 rb 15 &invalidate_nscd();
333 zugschlus 330 print (gtx("Done.\n")) if $verbose;
334 rb 1 exit 0;
335     }
336    
337    
338     ################
339     ## addsysuser ##
340     ################
341 zugschlus 256 if ($action eq "addsysuser") {
342 joerghoh-guest 468 if (existing_user_ok($new_name, $new_uid) == 1) {
343 zugschlus 330 printf (gtx("The user `%s' already exists as a system user. Exiting...\n"), $new_name) if $verbose;
344 rb 37 exit 0;
345     }
346 joerghoh-guest 468 if (existing_user_ok($new_name, $new_uid) == 2) {
347     printf (gtx("The user `%s' already exists with a different uid. Aborting\n"), $new_name) if $verbose;
348     exit 1;
349     }
350    
351 zugschlus 508 if (!$ingroup_name && !defined($new_gid) && !$make_group_also) {
352     $new_gid = $nogroup_id;
353     }
354 zugschlus 112 check_user_group(1);
355 rb 1
356     if (!defined($new_uid) && $make_group_also) {
357 joerghoh-guest 448 $new_uid = &first_avail_uid($config{"first_system_uid"},
358     $config{"last_system_uid"});
359 rb 6 if ($new_uid == -1) {
360 zugschlus 350 print STDERR "$0: ";
361     printf STDERR gtx("No UID/GID pair is available in the range %d-%d (FIRST_SYS_UID - LAST_SYS_UID).\n"),$config{"first_system_uid"},$config{"last_system_uid"};
362 zugschlus 330 dief (gtx("The user `%s' was not created.\n"),$new_name);
363 rb 6 }
364 zugschlus 508 $new_gid = &first_avail_gid($config{"first_system_gid"},
365     $config{"last_system_gid"});
366 rb 1 $ingroup_name = $new_name;
367     }
368     elsif (!defined($new_uid) && !$make_group_also) {
369 joerghoh-guest 448 $new_uid = &first_avail_uid($config{"first_system_uid"},
370     $config{"last_system_uid"});
371 rb 6 if ($new_uid == -1) {
372 zugschlus 350 print STDERR "$0: ";
373     printf STDERR gtx("No UID is available in the range %d-%d (FIRST_SYS_UID - LAST_SYS_UID).\n"),$config{"first_system_uid"},$config{"last_system_uid"};
374     dief (gtx("The user `%s' was not created.\n"),$new_name);
375 rb 6 }
376     if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); }
377 rb 1 elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); }
378 joerghoh-guest 549 else { dief (gtx("Internal error")); }
379 rb 1 }
380     else {
381     if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); }
382     elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); }
383     elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; }
384 joerghoh-guest 549 else { dief (gtx("Internal error")); }
385 rb 1 }
386 joerghoh-guest 489 printf (gtx("Adding system user `%s' with uid %s...\n"),$new_name,$new_uid) if $verbose;
387 rb 82
388 rb 15 &invalidate_nscd();
389 zugschlus 112 # if we reach this point, and the group does already exist, we can use it.
390 zugschlus 287 if ($make_group_also && !getgrnam($new_name)) {
391 zugschlus 330 printf (gtx("Adding new group `%s' (%s).\n"),$new_name,$new_gid) if $verbose;
392 rb 1 $undogroup = $new_name;
393 rb 82 &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name);
394 rb 29 &invalidate_nscd("group");
395 rb 1 }
396    
397 zugschlus 330 printf gtx("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name
398 rb 1 if $verbose;
399     $home_dir = $special_home || &homedir($new_name, $ingroup_name);
400 rb 56 $shell = $special_shell || '/bin/false';
401 rb 1 $undouser = $new_name;
402 rb 82 &systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
403 rb 56 $shell, '-u', $new_uid, $new_name);
404 joerghoh-guest 383 print "/usr/bin/chage -M 99999 $new_name\n" if ($verbose > 1);
405 zugschlus 410 # do _not_ use systemcall() here, since systemcall() dies on
406     # non-zero exit code and we need to do special handling here!
407     if (system('/usr/bin/chage', '-M', '99999', $new_name)) {
408 zugschlus 274 if( ($?>>8) ne 15 ) {
409 zugschlus 239 &cleanup("$0: `/usr/bin/chage -M 99999 $new_name' returned error code " . ($?>>8) . ". Aborting.\n")
410 zugschlus 234 if ($?>>8);
411 zugschlus 239 &cleanup("$0: `/usr/bin/chage -M 99999 $new_name' exited from signal " . ($?&255) . ". Aborting.\n");
412 zugschlus 234 } else {
413 zugschlus 330 print (gtx("chage failed with return code 15, shadow not enabled, password aging cannot be set. Continuing.\n"));
414 zugschlus 234 }
415     }
416 rb 15 &invalidate_nscd();
417 rb 1
418 rb 33 if(defined($new_gecos)) {
419 rb 8 &ch_gecos($new_gecos);
420     }
421    
422 zugschlus 293 create_homedir (0);
423 rb 1
424     exit 0;
425     }
426    
427    
428     #############
429     ## adduser ##
430     #############
431 zugschlus 256 if ($action eq "adduser") {
432 rb 1 if (!$ingroup_name && !defined($new_gid)) {
433 zugschlus 256 if ($config{"usergroups"} =~ /yes/i) { $make_group_also = 1; }
434 rb 1 else { $new_gid = $config{"users_gid"}; }
435     }
436 zugschlus 112 check_user_group(0);
437 rb 43 $first_uid = $new_firstuid || $config{"first_uid"};
438     $last_uid = $new_lastuid || $config{"last_uid"};
439 zugschlus 330 printf (gtx("Adding user `%s'...\n"),$new_name) if $verbose;
440 rb 1
441     if (!defined($new_uid) && $make_group_also) {
442 joerghoh-guest 448 $new_uid = &first_avail_uid($first_uid,
443     $last_uid);
444    
445 rb 6 if ($new_uid == -1) {
446 zugschlus 350 print STDERR "$0: ";
447     printf STDERR gtx("No UID/GID pair is available in the range %d-%d (FIRST_UID - LAST_UID).\n"),$first_uid,$last_uid;
448     dief (gtx("The user `%s' was not created.\n"),$new_name);
449 rb 6 }
450 zugschlus 508 $new_gid = &first_avail_gid($config{"first_gid"},
451     $config{"last_gid"});
452 rb 1 $ingroup_name = $new_name;
453     }
454     elsif (!defined($new_uid) && !$make_group_also) {
455 joerghoh-guest 448 $new_uid = &first_avail_uid($first_uid,
456     $last_uid);
457 rb 6 if ($new_uid == -1) {
458 zugschlus 350 print STDERR "$0: ";
459     printf STDERR gtx("No UID is available in the range %d-%d (FIRST_UID - LAST_UID).\n"),$config{"first_uid"},$config{"last_uid"};
460 zugschlus 330 dief (gtx("The user `%s' was not created.\n"),$new_name);
461 rb 6 }
462 rb 1 if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); }
463     elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); }
464 joerghoh-guest 549 else { dief (gtx("Internal error")); }
465 rb 1 }
466     else {
467     if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); }
468     elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); }
469     elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; }
470 joerghoh-guest 549 else { dien (gtx("Internal error")); }
471 rb 1 }
472    
473 rb 15 &invalidate_nscd();
474 rb 1 if ($make_group_also) {
475 zugschlus 330 printf (gtx("Adding new group `%s' (%s).\n"),$new_name,$new_gid) if $verbose;
476 rb 1 $undogroup = $new_name;
477 rb 82 &systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name);
478 rb 15 &invalidate_nscd();
479 rb 1 }
480    
481 zugschlus 330 printf gtx("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name
482 rb 1 if $verbose;
483     $home_dir = $special_home || &homedir($new_name, $ingroup_name);
484 rb 56 $shell = $special_shell || $config{"dshell"};
485 rb 1 $undouser = $new_name;
486 rb 82 &systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s',
487 rb 56 $shell, '-u', $new_uid, $new_name);
488 rb 15 &invalidate_nscd();
489 rb 1
490 zugschlus 293 create_homedir (1); # copy skeleton data
491 rb 1
492 zugschlus 223 # useradd without -p has left the account disabled (password string is '!')
493 rb 1 if ($ask_passwd) {
494 joerghoh-guest 400 for (;;) {
495     &systemcall('/usr/bin/passwd', $new_name);
496     my $ok = $? & 128;
497     if ($ok != 0) {
498     my $noexpr = langinfo(NOEXPR());
499     my $answer;
500     # hm, error, should we break now?
501     print (gtx("Permission denied\n")) if ($ok == 1);
502     print (gtx("invalid combination of options\n")) if ($ok == 2);
503     print (gtx("unexpected failure, nothing done\n")) if ($ok == 3);
504     print (gtx("unexpected failure, passwd file missing\n")) if ($ok == 3);
505     print (gtx("passwd file busy, try again\n")) if ($ok == 4);
506     print (gtx("invalid argument to option\n")) if ($ok == 5);
507    
508     # Translators: [y/N] has to be replaced by values defined in your
509     # locale. You can see by running "locale noexpr" which regular
510     # expression will be checked to find positive answer.
511 joerghoh-guest 445 print (gtx("Try again(Y/n)?"));
512 joerghoh-guest 400 chop ($answer=<STDIN>);
513     last if ($answer =~ m/$noexpr/o);
514     }
515     else {
516     last; ## passwd ok
517     }
518     }
519 rb 56 } else {
520     if(!$disabled_login) {
521 rb 82 &systemcall('/usr/sbin/usermod', '-p', '*', $new_name);
522 rb 56 }
523 rb 1 }
524    
525 rb 33 if (defined($new_gecos)) {
526 rb 8 &ch_gecos($new_gecos);
527 rb 1 }
528     else {
529 zugschlus 348 my $yesexpr = langinfo(YESEXPR());
530 rb 1 for (;;) {
531 rb 82 &systemcall('/usr/bin/chfn', $new_name);
532 zugschlus 348 # Translators: [y/N] has to be replaced by values defined in your
533     # locale. You can see by running "locale yesexpr" which regular
534     # expression will be checked to find positive answer.
535 zugschlus 330 print (gtx("Is the information correct? [y/N] "));
536 joerghoh-guest 528 chop (my $answer=<STDIN>);
537 zugschlus 348 last if ($answer =~ m/$yesexpr/o);
538 rb 1 }
539     }
540    
541 zugschlus 557 if ( ( $add_extra_groups || $config{"add_extra_groups"} ) && defined($config{"extra_groups"}) ) {
542     printf (gtx("Adding new user `%s' to extra groups\n"), $new_name);
543     foreach my $newgrp ( split ' ', $config{"extra_groups"} ) {
544     if (!defined getgrnam($newgrp)) {
545     warnf (gtx("The group `%s' does not exist.\n"),$newgrp);
546     next;
547     }
548     if (&user_is_member($new_name, $newgrp)) {
549     printf gtx("The user `%s' is already a member of `%s'.\n"),
550     $new_name,$newgrp if $verbose;
551     next;
552    
553     }
554    
555     printf gtx("Adding user `%s' to group `%s'...\n"),$new_name,$newgrp
556     if $verbose;
557     &invalidate_nscd();
558     &systemcall('/usr/bin/gpasswd', '-M',
559     join(',', get_group_members($newgrp), $new_name),
560     $newgrp);
561     &invalidate_nscd();
562     }
563     }
564    
565    
566 rb 1 if ($config{"quotauser"}) {
567 zugschlus 330 printf (gtx("Setting quota from `%s'.\n"),$config{quotauser});
568 rb 82 &systemcall('/usr/sbin/edquota', '-p', $config{quotauser}, $new_name);
569 rb 1 }
570    
571     &systemcall('/usr/local/sbin/adduser.local', $new_name, $new_uid,
572     $new_gid, $home_dir) if (-x "/usr/local/sbin/adduser.local");
573    
574     exit 0;
575     }
576    
577 zugschlus 256 #
578     # we never go here
579     #
580 rb 1
581 zugschlus 256
582 rb 1 # calculate home directory
583     sub homedir {
584     my $dir = $config{"dhome"};
585     $dir .= '/' . $_[1] if ($config{"grouphomes"} =~ /yes/i);
586     $dir .= '/' . substr($_[0],0,1) if ($config{"letterhomes"} =~ /yes/i);
587     $dir .= '/' . $_[0];
588 zugschlus 256 return $dir;
589 rb 1 }
590    
591    
592 zugschlus 293 # create_homedir -- create the homedirectory
593     # parameter 1: $copy_skeleton:
594     # if 0 -> don't copy the skeleton data
595     # if 1 -> copy the files in /etc/skel to the newly created home directory
596     sub create_homedir {
597 zugschlus 306 my ($copy_skeleton) = @_;
598 zugschlus 293
599     if ($no_create_home) {
600 zugschlus 351 printf gtx("Not creating home directory `%s'.\n"), $home_dir if $verbose;
601 zugschlus 293 }
602     elsif (-e $home_dir) {
603 zugschlus 330 printf gtx("The home directory `%s' already exists. Not copying from `%s'\n"),
604 zugschlus 293 $home_dir,$config{skel} if $verbose && !$no_create_home;
605     my @homedir_stat = stat($home_dir);
606     my $home_uid = $homedir_stat[4];
607     my $home_gid = $homedir_stat[5];
608     if (($home_uid != $new_uid) || ($home_gid != $new_gid)) {
609 zugschlus 350 warnf gtx("Warning: that home directory does not belong to the user you are currently creating\n");
610 zugschlus 293 }
611     undef @homedir_stat; undef $home_uid; undef $home_gid;
612     }
613     else {
614 zugschlus 330 printf gtx("Creating home directory `%s'.\n"),$home_dir if $verbose;
615 zugschlus 293 $undohome = $home_dir;
616     &mktree($home_dir) || &cleanup("Couldn't create $home_dir: $!.\n");
617     chown($new_uid, $new_gid, $home_dir)
618     || &cleanup("chown $new_uid:$new_gid $home_dir: $!\n");
619     $dir_mode = get_dir_mode($make_group_also);
620     chmod ($dir_mode, $home_dir) ||
621     &cleanup("chmod $dir_mode $home_dir: $!\n");
622    
623     if ($config{"skel"} && $copy_skeleton) {
624 zugschlus 330 printf gtx("Copying files from `%s'\n"),$config{skel} if $verbose;
625 zugschlus 509 open(FIND, "cd $config{skel}; find . -print |")
626 zugschlus 293 || &cleanup("fork for find: $!\n");
627     while (<FIND>) {
628     chop;
629     next if ($_ eq ".");
630 zugschlus 509 next if ($_ =~ qr/$config{skel_ignore_regex}/ );
631 zugschlus 293 &copy_to_dir($config{"skel"}, $_, $home_dir, $new_uid,
632     $new_gid, ($config{"setgid_home"} =~ /yes/i));
633     }
634     }
635     }
636     }
637    
638 joerghoh-guest 383 # create a directory and all parent directories
639     # we don't care about the rights and so on
640 rb 1 sub mktree {
641     my($tree) = @_;
642     my($done, @path);
643     my $default_dir_mode = 0755;
644    
645     $tree =~ s:^/*(.*)/*$:$1:; # chop off leading & trailing slashes
646     @path = split(/\//, $tree);
647    
648     $done = "";
649     while (@path) {
650     $done .= '/' . shift(@path);
651     -d $done || mkdir($done, $default_dir_mode) || return 0;
652     }
653 zugschlus 256 return 1;
654 rb 1 }
655    
656 zugschlus 256 # returns 0 if the the user doesn't exist or
657 joerghoh-guest 476 # returns 1 if the user already exists with the specified uid (or $new_uid wasn't specified)
658     # returns 2 if the user already exists, but $new_uid doesn't matches its uid
659 zugschlus 112 sub existing_user_ok {
660     my($new_name,$new_uid) = @_;
661     my ($dummy1,$dummy2,$uid);
662     if (($dummy1,$dummy2,$uid) = getpwnam($new_name)) {
663     if( defined($new_uid) && $uid == $new_uid ) {
664     return 1;
665     }
666 joerghoh-guest 476 if (! defined($new_uid)) {
667     return 1;
668     }
669 zugschlus 112 if( $uid >= $config{"first_system_uid"} &&
670     $uid <= $config{"last_system_uid" } ) {
671 joerghoh-guest 468 return 2;
672 zugschlus 112 }
673     } else {
674     return 0;
675     }
676     }
677 rb 1
678 zugschlus 256 # returns 0 if the group doesn't exist or
679 joerghoh-guest 476 # returns 1 if the group already exists with the specified gid (or $new_gid wasn't specified)
680     # returns 2 if the group already exists, but $new_gid doesn't match its gid
681 zugschlus 112 sub existing_group_ok {
682     my($new_name,$new_gid) = @_;
683     my ($dummy1,$dummy2,$gid);
684     if (($dummy1,$dummy2,$gid) = getgrnam($new_name)) {
685     if( defined($new_gid) && $gid == $new_gid ) {
686     return 1;
687     }
688 joerghoh-guest 476 if (! defined($new_gid)) {
689     return 1;
690     }
691 zugschlus 112 if( $gid >= $config{"first_system_gid"} &&
692     $gid <= $config{"last_system_gid" } ) {
693 joerghoh-guest 476 return 2;
694 zugschlus 112 }
695     } else {
696     return 0;
697     }
698     }
699    
700     sub check_user_group {
701     my ($system) = @_;
702     if( !$system || !existing_user_ok($new_name, $new_uid) ) {
703     if( defined getpwnam($new_name) ) {
704     if( $system ) {
705 zugschlus 330 dief (gtx("The user `%s' already exists, and is not a system user.\n"),$new_name);
706 zugschlus 112 } else {
707 zugschlus 330 dief (gtx("The user `%s' already exists.\n"),$new_name);
708 zugschlus 112 }
709     }
710 zugschlus 330 dief (gtx("The UID %s is already in use.\n"),$new_uid)
711 zugschlus 112 if (defined($new_uid) && getpwuid($new_uid));
712     }
713 rb 1 if ($make_group_also) {
714 zugschlus 112 if( !$system || !existing_group_ok($new_name, $new_uid) ) {
715 zugschlus 330 dief (gtx("The group `%s' already exists.\n"),$new_name)
716 zugschlus 112 if (defined getgrnam($new_name));
717 zugschlus 330 dief (gtx("The GID %s is already in use.\n"),$new_uid)
718 zugschlus 112 if (defined($new_uid) && defined(getgrgid($new_uid)));
719     }
720 rb 1 }
721     else {
722 zugschlus 330 dief (gtx("The group `%s' does not exist.\n"),$ingroup_name)
723 rb 13 if ($ingroup_name && !defined(getgrnam($ingroup_name)));
724 zugschlus 330 dief (gtx("The GID %s does not exist.\n"),$new_gid)
725 rb 13 if (defined($new_gid) && !defined(getgrgid($new_gid)));
726 rb 1 }
727     }
728    
729    
730     # copy files, directories, symlinks
731     sub copy_to_dir {
732     my($fromdir, $file, $todir, $newu, $newg, $sgiddir) = @_;
733    
734     if (-l "$fromdir/$file") {
735 zugschlus 219 my $target=readlink("$fromdir/$file") or &cleanup("readlink: $!\n");
736 zugschlus 187 my $curgid="$)";
737     my $curuid="$>";
738 zugschlus 219 my $error="";
739 zugschlus 187 $)="$newg";
740     $>="$newu";
741 zugschlus 526 symlink("$target", "$todir/$file") or $error="$!";
742 zugschlus 187 $>="$curuid";
743     $)="$curgid";
744 zugschlus 219 if( "$error" ne "" ) {
745     &cleanup("symlink: $!\n");
746     }
747 rb 6 return;
748 rb 1 }
749     elsif (-f "$fromdir/$file") {
750     open (FILE, "$fromdir/$file") || &cleanup("open $fromdir/$file: $!");
751     open (NEWFILE, ">$todir/$file") || &cleanup("open >$todir/$file: $!");
752    
753     (print NEWFILE <FILE>) || &cleanup("print $todir/$file: $!");
754     close FILE;
755     close(NEWFILE) || &cleanup("close $todir/$file ");
756    
757     }
758     elsif (-d "$fromdir/$file") {
759     mkdir("$todir/$file", 700) || &cleanup("mkdir: $!");
760     }
761     else {
762     &cleanup("Can't deal with $fromdir/$file. "
763     ."Not a dir, file, or symlink.\n");
764     }
765    
766     chown($newu, $newg, "$todir/$file")
767     || &cleanup("chown $newu:$newg $todir/$file: $!\n");
768     $perm = (stat("$fromdir/$file"))[2] & 07777;
769     $perm |= 02000 if (-d "$fromdir/$file" && ($perm & 010) && $sgiddir);
770     chmod($perm, "$todir/$file") || &cleanup("chmod $todir/$file: $!\n");
771     }
772    
773    
774 joerghoh-guest 383 # check if the given name matches some sanity checks
775 rb 1 sub checkname {
776     my ($name) = @_;
777 zugschlus 530 if ($name !~ /^[_.A-Za-z0-9][-_.A-Za-z0-9]*\$?$/) {
778 rb 1 print STDERR
779 zugschlus 559 ("$0: " . gtx("To avoid problems, the username should consist of
780 zugschlus 530 letters, digits, underscores, periods and dashes, and not start with a
781     dash (as defined by IEEE Std 1003.1-2001). For compatibility with Samba
782     machine accounts \$ is also supported at the end of the username\n"));
783     exit 1;
784 rb 1 }
785 zugschlus 202 if ($name !~ qr/$config{"name_regex"}/) {
786     if ($allow_badname) {
787 zugschlus 330 print (gtx("Allowing use of questionable username.\n")) if ($verbose);
788 zugschlus 202 }
789     else {
790     print STDERR
791 zugschlus 559 ("$0: " . gtx("Please enter a username matching the regular expression configured
792 zugschlus 202 via the name_regex configuration variable. Use the `--force-badname'
793 zugschlus 287 option to relax this check or reconfigure name_regex.\n"));
794 zugschlus 202 exit 1;
795     }
796 rb 1 }
797     }
798    
799 joerghoh-guest 448 # return the first available uid in given range
800     # return -1 if no free uid is available
801     sub first_avail_uid {
802     my ($min, $max) = @_;
803     printf (gtx("Selecting uid from range %s to %s.\n"),$min,$max) if ($verbose > 1);
804 rb 1
805 joerghoh-guest 448 my $t = $min;
806     while ($t <= $max) {
807 zugschlus 455 return $t if (!defined(getpwuid($t)));
808 joerghoh-guest 448 $t++;
809 rb 1 }
810 joerghoh-guest 448 return -1; # nothing available
811 rb 1 }
812    
813 joerghoh-guest 448 # return the first available gid in given range
814     # return -1 if no free gid is available
815     sub first_avail_gid {
816     my ($min, $max) = @_;
817     printf (gtx("Selecting gid from range %s to %s.\n"),$min,$max) if ($verbose > 1);
818 rb 1
819 joerghoh-guest 448 my $t = $min;
820     while ($t <= $max) {
821 zugschlus 455 return $t if (!defined(getgrgid($t)));
822 joerghoh-guest 448 $t++;
823     }
824     return -1; # nothing available
825 rb 1 }
826    
827 rb 8 sub ch_gecos {
828     my $gecos = shift;
829     if($gecos =~ /,/)
830     {
831     my($gecos_name,$gecos_room,$gecos_work,$gecos_home,$gecos_other)
832     = split(/,/,$gecos);
833 rb 1
834 rb 82 &systemcall('/usr/bin/chfn', '-f', $gecos_name, '-r', $gecos_room, $new_name);
835     &systemcall('/usr/bin/chfn','-w',$gecos_work,$new_name)
836 rb 8 if(defined($gecos_work));
837 rb 82 &systemcall('/usr/bin/chfn','-h',$gecos_home,$new_name)
838 rb 8 if(defined($gecos_home));
839 rb 82 &systemcall('/usr/bin/chfn','-o',$gecos_other,$new_name)
840 rb 8 if(defined($gecos_other));
841     }
842     else
843     {
844 rb 82 &systemcall('/usr/bin/chfn', '-f', $gecos, $new_name);
845 rb 8 }
846     }
847    
848 rb 1 # user is member of group?
849     sub user_is_member {
850     my($user, $group) = @_;
851     for (split(/ /, (getgrnam($group))[3])) {
852     return 1 if ($user eq $_);
853     }
854 zugschlus 256 return 0;
855 rb 1 }
856    
857    
858     sub cleanup {
859 joerghoh-guest 527 my ($msg) = @_;
860 zugschlus 546 printf (gtx("Stopped: %s\n"),$msg);
861 rb 1 if ($undohome) {
862 zugschlus 330 printf (gtx("Removing directory `%s'\n"),$undohome);
863 joerghoh-guest 383 &systemcall('rm', '-rf', $undohome);
864 rb 1 }
865     if ($undouser) {
866 zugschlus 330 printf (gtx("Removing user `%s'.\n"),$undouser);
867 joerghoh-guest 383 &systemcall('userdel', $undouser);
868 rb 1 }
869     if ($undogroup) {
870 zugschlus 330 printf (gtx("Removing group `%s'.\n"),$undogroup);
871 joerghoh-guest 383 &systemcall('groupdel', $undogroup);
872 rb 1 }
873 rb 15 # do we need to invalidate the nscd cache here, too?
874 rb 1 exit 1;
875     }
876    
877     sub handler {
878     my($sig) = @_;
879     &cleanup("Caught a SIG$sig.\n");
880     }
881    
882    
883     sub version {
884 zugschlus 293 print "$0: add a user or group to the system. Version VERSION
885 rb 6 Copyright (C) 1997, 1998, 1999 Guy Maor <maor\@debian.org>
886 rb 1 Copyright (C) 1995 Ian Murdock <imurdock\@gnu.ai.mit.edu>,
887     Ted Hajek <tedhajek\@boombox.micro.umn.edu>,
888    
889     This program is free software; you can redistribute it and/or modify
890     it under the terms of the GNU General Public License as published by
891     the Free Software Foundation; either version 2 of the License, or (at
892     your option) any later version.
893    
894     This program is distributed in the hope that it will be useful, but
895     WITHOUT ANY WARRANTY; without even the implied warranty of
896     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
897 rb 19 General Public License, /usr/share/common-licenses/GPL, for more details.
898 zugschlus 293 ";
899 rb 1 }
900    
901     sub usage {
902 zugschlus 330 printf gtx(
903 rb 58 "adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID]
904     [--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID]
905     [--disabled-password] [--disabled-login] user
906 rb 4 Add a normal user
907 rb 1
908 rb 58 adduser --system [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID]
909     [--gecos GECOS] [--group | --ingroup GROUP | --gid ID] [--disabled-password]
910     [--disabled-login] user
911 rb 4 Add a system user
912 rb 1
913 rb 4 adduser --group [--gid ID] group
914     addgroup [--gid ID] group
915 rb 86 Add a user group
916    
917     addgroup --system [--gid ID] group
918 rb 4 Add a system group
919 rb 1
920     adduser user group
921 rb 4 Add an existing user to an existing group
922 rb 1
923 rb 4 Other options are [--quiet] [--force-badname] [--help] [--version] [--conf
924     FILE].
925 zugschlus 330 ");
926 rb 1 }
927 rb 6
928 rb 10 sub get_dir_mode
929     {
930     my $setgid = shift;
931 rb 13 # no longer make home directories setgid per default (closes: #64806)
932 zugschlus 256 $setgid = 0 unless $config{"setgid_home"} =~ /yes/i;
933 rb 13
934 rb 10 my $dir_mode = $config{"dir_mode"};
935     if(!defined($dir_mode) || ! ($dir_mode =~ /[0-7]{3}/ ||
936     $dir_mode =~ /[0-7]{4}/))
937     {
938     $dir_mode = $setgid ? 2755 : 0755;
939     }
940     else
941     {
942     $dir_mode = $config{"dir_mode"};
943     if($setgid && (length($dir_mode) == 3 || $dir_mode =~ /^[0-1|4-5][0-7]{3}$/))
944     {
945     $dir_mode += 2000;
946     }
947     }
948     return oct($dir_mode);
949     }
950 rb 6
951     # Local Variables:
952     # mode:cperl
953     # cperl-indent-level:4
954     # End:
955 rb 10
956    

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.5