1#!/usr/bin/perl 2# 3# $OpenBSD: adduser.perl,v 1.15 1999/02/04 19:38:39 provos Exp $ 4# 5# Copyright (c) 1995-1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin. 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29# $From: adduser.perl,v 1.22 1996/12/07 21:25:12 ache Exp $ 30 31################ 32# main 33# 34$test = 0; # test mode, only for development 35$check_only = 0; 36 37&check_root; # you must be root to run this script! 38&variables; # initialize variables 39&config_read(@ARGV); # read variables from config-file 40&parse_arguments(@ARGV); # parse arguments 41 42if (!$check_only && $#batch < 0) { 43 ©right; &hints; 44} 45 46# check 47$changes = 0; 48&variable_check; # check for valid variables 49&passwd_check; # check for valid passwdb 50&shells_read; # read /etc/shells 51&passwd_read; # read /etc/master.passwd 52&group_read; # read /etc/group 53&group_check; # check for incon* 54exit 0 if $check_only; # only check consistence and exit 55 56exit(!&batch(@batch)) if $#batch >= 0; # batch mode 57 58# Interactive: 59# main loop for creating new users 60&new_users; # add new users 61 62#end 63 64 65# Set adduser "default" variables internally before groking config file 66# Adduser.conf supercedes these 67sub variables { 68 $verbose = 1; # verbose = [0-2] 69 $defaultpasswd = "yes"; # use password for new users 70 $dotdir = "/usr/share/skel"; # copy dotfiles from this dir 71 $dotdir_bak = $dotdir; 72 $send_message = "no"; # send message to new user 73 $send_message_bak = '/etc/adduser.message'; 74 $config = "/etc/adduser.conf"; # config file for adduser 75 $config_read = 1; # read config file 76 $logfile = "/var/log/adduser"; # logfile 77 $home = "/home"; # default HOME 78 $etc_shells = "/etc/shells"; 79 $etc_passwd = "/etc/master.passwd"; 80 $group = "/etc/group"; 81 $pwd_mkdb = "pwd_mkdb -p"; # program for building passwd database 82 $encryptionmethod = "blowfish"; 83 84 # List of directories where shells located 85 @path = ('/bin', '/usr/bin', '/usr/local/bin'); 86 # common shells, first element has higher priority 87 @shellpref = ('csh', 'sh', 'bash', 'tcsh', 'ksh'); 88 89 @encryption_methods = ('blowfish', 'md5', 'des', 'old'); 90 91 $defaultshell = 'sh'; # defaultshell if not empty 92 $group_uniq = 'USER'; 93 $defaultgroup = $group_uniq;# login groupname, $group_uniq means username 94 95 $uid_start = 1000; # new users get this uid 96 $uid_end = 2147483648; # max. uid 97 98 # global variables 99 # passwd 100 $username = ''; # $username{username} = uid 101 $uid = ''; # $uid{uid} = username 102 $pwgid = ''; # $pwgid{pwgid} = username; gid from passwd db 103 104 $password = ''; # password for new users 105 106 # group 107 $groupname =''; # $groupname{groupname} = gid 108 $groupmembers = ''; # $groupmembers{gid} = members of group/kommalist 109 $gid = ''; # $gid{gid} = groupname; gid form group db 110 111 # shell 112 $shell = ''; # $shell{`basename sh`} = sh 113 114 # only for me (=Wolfram) 115 if ($test) { 116 $home = "/home/w/tmp/adduser/home"; 117 $etc_shells = "./shells"; 118 $etc_passwd = "./master.passwd"; 119 $group = "./group"; 120 $pwd_mkdb = "pwd_mkdb -p -d ."; 121 $config = "adduser.conf"; 122 $send_message = "./adduser.message"; 123 $logfile = "./log.adduser"; 124 } 125 126 umask 022; # don't give login group write access 127 128 $ENV{'PATH'} = "/sbin:/bin:/usr/sbin:/usr/bin"; 129 @passwd_backup = ''; 130 @group_backup = ''; 131 @message_buffer = ''; 132 @user_variable_list = ''; # user variables in /etc/adduser.conf 133 $do_not_delete = '## DO NOT DELETE THIS LINE!'; 134} 135 136# read shell database, see also: shells(5) 137sub shells_read { 138 local($sh); 139 local($err) = 0; 140 141 print "Reading $etc_shells\n" if $verbose; 142 open(S, $etc_shells) || die "$etc_shells:$!\n"; 143 144 while(<S>) { 145 if (/^\s*\//) { 146 s/^\s*//; s/\s+.*//; # chop 147 $sh = $_; 148 if (-x $sh) { 149 $shell{&basename($sh)} = $sh; 150 } else { 151 warn "Shell: $sh not executable!\n"; 152 $err++; 153 } 154 } 155 } 156 157 push(@list, "/sbin/nologin"); 158 &shell_pref_add("nologin"); 159 $shell{"nologin"} = "/sbin/nologin"; 160 161 return $err; 162} 163 164# add new shells if possible 165sub shells_add { 166 local($sh,$dir,@list); 167 168 return 1 unless $verbose; 169 170 foreach $sh (@shellpref) { 171 # all known shells 172 if (!$shell{$sh}) { 173 # shell $sh is not defined as login shell 174 foreach $dir (@path) { 175 if (-x "$dir/$sh") { 176 # found shell 177 if (&confirm_yn("Found shell: $dir/$sh. Add to $etc_shells?", "yes")) { 178 push(@list, "$dir/$sh"); 179 &shell_pref_add("$sh"); 180 $shell{&basename("$dir/$sh")} = "$dir/$sh"; 181 $changes++; 182 } 183 } 184 } 185 } 186 } 187 &append_file($etc_shells, @list) if $#list >= 0; 188} 189 190# add shell to preference list without duplication 191sub shell_pref_add { 192 local($new_shell) = @_; 193 local($shell); 194 195 foreach $shell (@shellpref) { 196 return if ($shell eq $new_shell); 197 } 198 push(@shellpref, $new_shell); 199} 200 201# choose your favourite shell and return the shell 202sub shell_default { 203 local($e,$i,$new_shell); 204 local($sh); 205 206 $sh = &shell_default_valid($defaultshell); 207 return $sh unless $verbose; 208 209 $new_shell = &confirm_list("Enter your default shell:", 0, 210 $sh, sort(keys %shell)); 211 print "Your default shell is: $new_shell -> $shell{$new_shell}\n"; 212 $changes++ if $new_shell ne $sh; 213 return $new_shell; 214} 215 216sub shell_default_valid { 217 local($sh) = @_; 218 local($s,$e); 219 220 return $sh if $shell{$sh}; 221 222 foreach $e (@shellpref) { 223 $s = $e; 224 last if defined($shell{$s}); 225 } 226 $s = "sh" unless $s; 227 warn "Shell ``$sh'' is undefined, use ``$s''\n"; 228 return $s; 229} 230 231# return default home partition (f.e. "/home") 232# create base directory if nesseccary 233sub home_partition { 234 local($home) = @_; 235 $home = &stripdir($home); 236 local($h) = $home; 237 238 return $h if !$verbose && $h eq &home_partition_valid($h); 239 240 while(1) { 241 $h = &confirm_list("Enter your default HOME partition:", 1, $home, ""); 242 $h = &stripdir($h); 243 last if $h eq &home_partition_valid($h); 244 } 245 246 $changes++ if $h ne $home; 247 return $h; 248} 249 250sub home_partition_valid { 251 local($h) = @_; 252 253 $h = &stripdir($h); 254 # all right (I hope) 255 return $h if $h =~ "^/" && -e $h && -w $h && (-d $h || -l $h); 256 257 # Errors or todo 258 if ($h !~ "^/") { 259 warn "Please use absolute path for home: ``$h''.\a\n"; 260 return 0; 261 } 262 263 if (-e $h) { 264 warn "$h exists, but is not a directory or symlink!\n" 265 unless -d $h || -l $h; 266 warn "$h is not writable!\n" 267 unless -w $h; 268 return 0; 269 } else { 270 # create home partition 271 return $h if &mkdir_home($h); 272 } 273 return 0; 274} 275 276# check for valid passwddb 277sub passwd_check { 278 system("$pwd_mkdb -c $etc_passwd"); 279 die "\nInvalid $etc_passwd - cannot add any users!\n" if $?; 280} 281 282# read /etc/passwd 283sub passwd_read { 284 local($p_username, $pw, $p_uid, $p_gid, $sh, %shlist); 285 286 print "Check $etc_passwd\n" if $verbose; 287 open(P, "$etc_passwd") || die "$passwd: $!\n"; 288 289 while(<P>) { 290 chop; 291 push(@passwd_backup, $_); 292 ($p_username, $pw, $p_uid, $p_gid, $sh) = (split(/:/, $_))[0..3,9]; 293 294 print "$p_username already exists with uid: $username{$p_username}!\n" 295 if $username{$p_username} && $verbose; 296 $username{$p_username} = $p_uid; 297 print "User $p_username: uid $p_uid exists twice: $uid{$p_uid}\n" 298 if $uid{$p_uid} && $verbose && $p_uid; # don't warn for uid 0 299 print "User $p_username: illegal shell: ``$sh''\n" 300 if ($verbose && $sh && 301 !$shell{&basename($sh)} && 302 $p_username !~ /^(news|xten|bin|nobody|uucp)$/ && 303 $sh !~ /\/(pppd|sliplogin)$/); 304 $uid{$p_uid} = $p_username; 305 $pwgid{$p_gid} = $p_username; 306 } 307 close P; 308} 309 310# read /etc/group 311sub group_read { 312 local($g_groupname,$pw,$g_gid, $memb); 313 314 print "Check $group\n" if $verbose; 315 open(G, "$group") || die "$group: $!\n"; 316 while(<G>) { 317 chop; 318 push(@group_backup, $_); 319 ($g_groupname, $pw, $g_gid, $memb) = (split(/:/, $_))[0..3]; 320 321 $groupmembers{$g_gid} = $memb; 322 warn "Groupname exists twice: $g_groupname:$g_gid -> $g_groupname:$groupname{$g_groupname}\n" 323 if $groupname{$g_groupname} && $verbose; 324 $groupname{$g_groupname} = $g_gid; 325 warn "Groupid exists twice: $g_groupname:$g_gid -> $gid{$g_gid}:$g_gid\n" 326 if $gid{$g_gid} && $verbose; 327 $gid{$g_gid} = $g_groupname; 328 } 329 close G; 330} 331 332# check gids /etc/passwd <-> /etc/group 333sub group_check { 334 local($c_gid, $c_username, @list); 335 336 foreach $c_gid (keys %pwgid) { 337 if (!$gid{$c_gid}) { 338 $c_username = $pwgid{$c_gid}; 339 warn "User ``$c_username'' has gid $c_gid but a group with this " . 340 "gid does not exist.\n" if $verbose; 341 } 342 } 343} 344 345# 346# main loop for creating new users 347# 348 349# return username 350sub new_users_name { 351 local($name); 352 353 while(1) { 354 $name = &confirm_list("Enter username", 1, "a-z0-9_", ""); 355 if (length($name) > 8) { 356 warn "Username is longer than 8 chars\a\n"; 357 next; 358 } 359 last if (&new_users_name_valid($name) eq $name); 360 } 361 return $name; 362} 363 364sub new_users_name_valid { 365 local($name) = @_; 366 367 if ($name !~ /^[a-z0-9_][a-z0-9_\-]*$/ || $name eq "a-z0-9_-") { 368 warn "Wrong username. " . 369 "Please use only lowercase characters or digits\a\n"; 370 return 0; 371 } elsif ($username{$name}) { 372 warn "Username ``$name'' already exists!\a\n"; return 0; 373 } 374 return $name; 375} 376 377# return full name 378sub new_users_fullname { 379 local($name) = @_; 380 local($fullname); 381 382 while(1) { 383 $fullname = &confirm_list("Enter full name", 1, "", ""); 384 last if $fullname eq &new_users_fullname_valid($fullname); 385 } 386 $fullname = $name unless $fullname; 387 return $fullname; 388} 389 390sub new_users_fullname_valid { 391 local($fullname) = @_; 392 393 return $fullname if $fullname !~ /:/; 394 395 warn "``:'' is not allowed!\a\n"; 396 return 0; 397} 398 399# return shell (full path) for user 400sub new_users_shell { 401 local($sh); 402 403 $sh = &confirm_list("Enter shell", 0, $defaultshell, keys %shell); 404 return $shell{$sh}; 405} 406 407# return free uid and gid 408sub new_users_id { 409 local($name) = @_; 410 local($u_id, $g_id) = &next_id($name); 411 local($u_id_tmp, $e); 412 413 while(1) { 414 $u_id_tmp = &confirm_list("Uid", 1, $u_id, ""); 415 last if $u_id_tmp =~ /^[0-9]+$/ && $u_id_tmp <= $uid_end && 416 ! $uid{$u_id_tmp}; 417 if ($uid{$u_id_tmp}) { 418 warn "Uid ``$u_id_tmp'' in use!\a\n"; 419 } else { 420 warn "Wrong uid.\a\n"; 421 } 422 } 423 # use calculated uid 424 return ($u_id_tmp, $g_id) if $u_id_tmp eq $u_id; 425 # recalculate gid 426 $uid_start = $u_id_tmp; 427 return &next_id($name); 428} 429 430# add user to group 431sub add_group { 432 local($gid, $name) = @_; 433 434 return 0 if 435 $groupmembers{$gid} =~ /^(.+,)?$name(,.+)?$/; 436 437 $groupmembers_bak{$gid} = $groupmembers{$gid}; 438 $groupmembers{$gid} .= "," if $groupmembers{$gid}; 439 $groupmembers{$gid} .= "$name"; 440 441 local(@l) = split(',', $groupmembers{$gid}); 442 # group(5): A group cannot have more than 200 members. 443 # The maximum line length of /etc/group is 1024 characters. 444 # Longer lines will be skiped. 445 if ($#l >= 200 || 446 length($groupmembers{$gid}) > 1024 - 50) { # 50 is for group name 447 warn "WARNING, maybe group line ``$gid{$gid}'' is to long or to\n" . 448 "much users in group, see group(5)\a\n"; 449 } 450 return $name; 451} 452 453 454# return login group 455sub new_users_grplogin { 456 local($name, $defaultgroup, $new_users_ok) = @_; 457 local($group_login, $group); 458 459 $group = $name; 460 $group = $defaultgroup if $defaultgroup ne $group_uniq; 461 462 if ($new_users_ok) { 463 # clean up backup 464 foreach $e (keys %groupmembers_bak) { delete $groupmembers_bak{$e}; } 465 } else { 466 # restore old groupmembers, user was not accept 467 foreach $e (keys %groupmembers_bak) { 468 $groupmembers{$e} = $groupmembers_bak{$e}; 469 } 470 } 471 472 while(1) { 473 $group_login = &confirm_list("Login group", 1, $group, 474 ($name, $group)); 475 last if $group_login eq $group; 476 last if $group_login eq $name; 477 last if defined $groupname{$group_login}; 478 if ($group_login eq $group_uniq) { 479 $group_login = $name; last; 480 } 481 482 if (defined $gid{$group_login}) { 483 # convert numeric groupname (gid) to groupname 484 $group_login = $gid{$group_login}; 485 last; 486 } 487 warn "Group does not exist!\a\n"; 488 } 489 490 #if (defined($groupname{$group_login})) { 491 # &add_group($groupname{$group_login}, $name); 492 #} 493 494 return ($group_login, $group_uniq) if $group_login eq $name; 495 return ($group_login, $group_login); 496} 497 498# return login group 499sub new_users_grplogin_batch { 500 local($name, $defaultgroup) = @_; 501 local($group_login, $group); 502 503 $group_login = $name; 504 $group_login = $defaultgroup if $defaultgroup ne $group_uniq; 505 506 if (defined $gid{$group_login}) { 507 # convert numeric groupname (gid) to groupname 508 $group_login = $gid{$group_login}; 509 } 510 511 # if (defined($groupname{$group_login})) { 512 # &add_group($groupname{$group_login}, $name); 513 # } 514 515 return $group_login 516 if defined($groupname{$group_login}) || $group_login eq $name; 517 warn "Group ``$group_login'' does not exist\a\n"; 518 return 0; 519} 520 521# return other groups (string) 522sub new_users_groups { 523 local($name, $other_groups) = @_; 524 local($string) = 525 "Login group is ``$group_login''. Invite $name into other groups:"; 526 local($e, $flag); 527 local($new_groups,$groups); 528 529 $other_groups = "no" unless $other_groups; 530 531 while(1) { 532 $groups = &confirm_list($string, 1, $other_groups, 533 ("no", $other_groups, "guest")); 534 # no other groups 535 return "" if $groups eq "no"; 536 537 ($flag, $new_groups) = &new_users_groups_valid($groups); 538 last unless $flag; 539 } 540 $new_groups =~ s/\s*$//; 541 return $new_groups; 542} 543 544sub new_users_groups_valid { 545 local($groups) = @_; 546 local($e, $new_groups); 547 local($flag) = 0; 548 549 foreach $e (split(/[,\s]+/, $groups)) { 550 # convert numbers to groupname 551 if ($e =~ /^[0-9]+$/ && $gid{$e}) { 552 $e = $gid{$e}; 553 } 554 if (defined($groupname{$e})) { 555 if ($e eq $group_login) { 556 # do not add user to a group if this group 557 # is also the login group. 558 } elsif (&add_group($groupname{$e}, $name)) { 559 $new_groups .= "$e "; 560 } else { 561 warn "$name is already member of group ``$e''\n"; 562 } 563 } else { 564 warn "Group ``$e'' does not exist\a\n"; $flag++; 565 } 566 } 567 return ($flag, $new_groups); 568} 569 570# your last change 571sub new_users_ok { 572 573 print <<EOF; 574 575Name: $name 576Password: **** 577Fullname: $fullname 578Uid: $u_id 579Gid: $g_id ($group_login) 580Groups: $group_login $new_groups 581HOME: $home/$name 582Shell: $sh 583EOF 584 585 return &confirm_yn("OK?", "yes"); 586} 587 588# make password database 589sub new_users_pwdmkdb { 590 local($last) = @_; 591 592 system("$pwd_mkdb $etc_passwd"); 593 if ($?) { 594 warn "$last\n"; 595 warn "``$pwd_mkdb'' failed\n"; 596 exit($? >> 8); 597 } 598} 599 600# update group database 601sub new_users_group_update { 602 local($e, @a); 603 604 # Add *new* group 605 if (!defined($groupname{$group_login}) && 606 !defined($gid{$groupname{$group_login}})) { 607 push(@group_backup, "$group_login:*:$g_id:"); 608 $groupname{$group_login} = $g_id; 609 $gid{$g_id} = $group_login; 610 # $groupmembers{$g_id} = $group_login; 611 } 612 613 if ($new_groups || defined($groupname{$group_login}) || 614 defined($gid{$groupname{$group_login}}) && 615 $gid{$groupname{$group_login}} ne "+") { 616 # new user is member of some groups 617 # new login group is already in name space 618 rename($group, "$group.bak"); 619 #warn "$group_login $groupname{$group_login} $groupmembers{$groupname{$group_login}}\n"; 620 foreach $e (sort {$a <=> $b} (keys %gid)) { 621 push(@a, "$gid{$e}:*:$e:$groupmembers{$e}"); 622 } 623 &append_file($group, @a); 624 } else { 625 &append_file($group, "$group_login:*:$g_id:"); 626 } 627 628} 629 630sub new_users_passwd_update { 631 # update passwd/group variables 632 push(@passwd_backup, $new_entry); 633 $username{$name} = $u_id; 634 $uid{$u_id} = $name; 635 $pwgid{$g_id} = $name; 636} 637 638# send message to new user 639sub new_users_sendmessage { 640 return 1 if $send_message eq "no"; 641 642 local($cc) = 643 &confirm_list("Send message to ``$name'' and:", 644 1, "no", ("root", "second_mail_address", 645 "no carbon copy")); 646 local($e); 647 $cc = "" if $cc eq "no"; 648 649 @message_buffer = (); 650 message_read ($send_message); 651 652 foreach $e (@message_buffer) { 653 print eval "\"$e\""; 654 } 655 print "\n"; 656 657 local(@message_buffer_append) = (); 658 if (!&confirm_yn("Add anything to default message", "no")) { 659 print "Use ``.'' or ^D alone on a line to finish your message.\n"; 660 push(@message_buffer_append, "\n"); 661 while($read = <STDIN>) { 662 last if $read eq "\.\n"; 663 push(@message_buffer_append, $read); 664 } 665 } 666 667 &sendmessage("$name $cc", (@message_buffer, @message_buffer_append)) 668 if (&confirm_yn("Send message", "yes")); 669} 670 671sub sendmessage { 672 local($to, @message) = @_; 673 local($e); 674 675 if (!open(M, "| mail -s Welcome $to")) { 676 warn "Cannot send mail to: $to!\n"; 677 return 0; 678 } else { 679 foreach $e (@message) { 680 print M eval "\"$e\""; 681 } 682 close M; 683 } 684} 685 686 687sub new_users_password { 688 689 # empty password 690 return "" if $defaultpasswd ne "yes"; 691 692 local($password); 693 694 while(1) { 695 system("stty -echo"); 696 $password = &confirm_list("Enter password", 1, "", ""); 697 system("stty echo"); 698 print "\n"; 699 if ($password ne "") { 700 system("stty -echo"); 701 $newpass = &confirm_list("Enter password again", 1, "", ""); 702 system("stty echo"); 703 print "\n"; 704 last if $password eq $newpass; 705 print "They didn't match, please try again\n"; 706 } 707 elsif (&confirm_yn("Use an empty password?", "yes")) { 708 last; 709 } 710 } 711 712 return $password; 713} 714 715 716sub new_users { 717 718 print "\n" if $verbose; 719 print "Ok, let's go.\n" . 720 "Don't worry about mistakes. I will give you the chance later to " . 721 "correct any input.\n" if $verbose; 722 723 # name: Username 724 # fullname: Full name 725 # sh: shell 726 # u_id: user id 727 # g_id: group id 728 # group_login: groupname of g_id 729 # new_groups: some other groups 730 local($name, $group_login, $fullname, $sh, $u_id, $g_id, $new_groups); 731 local($groupmembers_bak, $cryptpwd); 732 local($new_users_ok) = 1; 733 734 735 $new_groups = "no"; 736 $new_groups = "no" unless $groupname{$new_groups}; 737 738 while(1) { 739 $name = &new_users_name; 740 $fullname = &new_users_fullname($name); 741 $sh = &new_users_shell; 742 ($u_id, $g_id) = &new_users_id($name); 743 ($group_login, $defaultgroup) = 744 &new_users_grplogin($name, $defaultgroup, $new_users_ok); 745 # do not use uniq username and login group 746 $g_id = $groupname{$group_login} if (defined($groupname{$group_login})); 747 748 $new_groups = &new_users_groups($name, $new_groups); 749 $password = &new_users_password; 750 751 752 if (&new_users_ok) { 753 $new_users_ok = 1; 754 755 $cryptpwd = "*"; # Locked by default 756 $cryptpwd = encrypt($password, &salt) if ($password ne ""); 757 758 # obscure perl bug 759 $new_entry = "$name\:" . "$cryptpwd" . 760 "\:$u_id\:$g_id\::0:0:$fullname:$home/$name:$sh"; 761 &append_file($etc_passwd, "$new_entry"); 762 &new_users_pwdmkdb("$new_entry"); 763 &new_users_group_update; 764 &new_users_passwd_update; print "Added user ``$name''\n"; 765 &adduser_log("$name:*:$u_id:$g_id($group_login):$fullname"); 766 &home_create($name, $group_login); 767 &new_users_sendmessage; 768 } else { 769 $new_users_ok = 0; 770 } 771 if (!&confirm_yn("Add another user?", "yes")) { 772 print "Goodbye!\n" if $verbose; 773 last; 774 } 775 print "\n" if !$verbose; 776 } 777} 778 779sub batch { 780 local($name, $groups, $fullname, $password) = @_; 781 local($sh); 782 783 $defaultshell = &shell_default_valid($defaultshell); 784 return 0 unless $home = &home_partition_valid($home); 785 return 0 if $dotdir ne &dotdir_default_valid($dotdir); 786 $send_message = &message_default; 787 788 return 0 if $name ne &new_users_name_valid($name); 789 $sh = $shell{$defaultshell}; 790 ($u_id, $g_id) = &next_id($name); 791 $group_login = &new_users_grplogin_batch($name, $defaultgroup); 792 return 0 unless $group_login; 793 $g_id = $groupname{$group_login} if (defined($groupname{$group_login})); 794 ($flag, $new_groups) = &new_users_groups_valid($groups); 795 return 0 if $flag; 796 797 $cryptpwd = "*"; # Locked by default 798 if ($password ne "" && $password ne "*") { 799 if($unencrypted) { $cryptpwd = encrypt($password, &salt) } 800 else { $cryptpwd = $password } 801 } 802 # obscure perl bug 803 $new_entry = "$name\:" . "$cryptpwd" . 804 "\:$u_id\:$g_id\::0:0:$fullname:$home/$name:$sh"; 805 &append_file($etc_passwd, "$new_entry"); 806 &new_users_pwdmkdb("$new_entry"); 807 &new_users_group_update; 808 &new_users_passwd_update; print "Added user ``$name''\n"; 809 &sendmessage($name, @message_buffer) if $send_message ne "no"; 810 &adduser_log("$name:*:$u_id:$g_id($group_login):$fullname"); 811 &home_create($name, $group_login); 812} 813 814# ask for password usage 815sub password_default { 816 local($p) = $defaultpasswd; 817 if ($verbose) { 818 $p = &confirm_yn("Prompt for passwords by default", $defaultpasswd); 819 $changes++ unless $p; 820 } 821 return "yes" if (($defaultpasswd eq "yes" && $p) || 822 ($defaultpasswd eq "no" && !$p)); 823 return "no"; # otherwise 824} 825 826# get default encryption method 827sub encryption_default { 828 local($m) = ""; 829 if ($verbose) { 830 while (&encryption_check($m) == 0) { 831 $m = &confirm_list("Default encryption method for passwords", 1, 832 $encryption_methods[0], @encryption_methods); 833 } 834 } 835 return($m); 836} 837 838# Confirm that we have a valid encryption method 839sub encryption_check { 840 local($m) = $_[0]; 841 842 foreach $i (@encryption_methods) { 843 if ($m eq $i) { return 1; } 844 } 845 846 if ($m =~ /^blowfish,(\d+)$/) { return 1; } 847 return 0; 848} 849 850# misc 851sub check_root { 852 die "You are not root!\n" if $< && !$test; 853} 854 855sub usage { 856 warn <<USAGE; 857usage: adduser 858 [-batch username [group[,group]...] [fullname] [password]] 859 [-check_only] 860 [-config_create] 861 [-dotdir dotdir] 862 [-e|-encryption method] 863 [-group login_group] 864 [-h|-help] 865 [-home home] 866 [-message message_file] 867 [-noconfig] 868 [-shell shell] 869 [-s|-silent|-q|-quiet] 870 [-uid_start uid_start] 871 [-uid_end uid_end] 872 [-unencrypted] 873 [-v|-verbose] 874 875home=$home shell=$defaultshell dotdir=$dotdir login_group=$defaultgroup 876message_file=$send_message uid_start=$uid_start uid_end=$uid_end 877USAGE 878 exit 1; 879} 880 881# uniq(1) 882sub uniq { 883 local(@list) = @_; 884 local($e, $last, @array); 885 886 foreach $e (sort @list) { 887 push(@array, $e) unless $e eq $last; 888 $last = $e; 889 } 890 return @array; 891} 892 893# Generate an appropriate argument to encrypt() 894# That may be a DES salt or a blowfish rotation count 895sub salt { 896 local($salt); # initialization 897 if ($encryptionmethod eq "des" || $encryptionmethod eq "old") { 898 local($i, $rand); 899 local(@itoa64) = ( 0 .. 9, a .. z, A .. Z ); # 0 .. 63 900 901 warn "calculate salt\n" if $verbose > 1; 902 903 for ($i = 0; $i < 8; $i++) { 904 srand(time + $rand + $$); 905 $rand = rand(25*29*17 + $rand); 906 $salt .= $itoa64[$rand & $#itoa64]; 907 } 908 } elsif ($encryptionmethod eq "md5") { 909 $salt = ""; 910 } elsif ($encryptionmethod =~ /^blowfish/ ) { 911 ($encryptionmethod, $salt) = split(/\,/, $encryptionmethod); 912 if ($salt eq "") { $salt = 7; } # default rounds inf unspecified 913 } else { 914 warn "$encryptionmethod encryption method invalid\n" if ($verbose > 0); 915 warn "Falling back to blowfish,7...\n" if ($verbose > 0); 916 $encryptionmethod = "blowfish"; 917 $salt = 7; 918 } 919 920 warn "Salt is: $salt\n" if $verbose > 1; 921 922 return $salt; 923} 924 925# Encrypt a password using the selected method 926sub encrypt { 927 local($pass, $salt) = ($_[0], $_[1]); 928 local($args, $crypt); 929 local($goodpass); 930 931 if ($encryptionmethod eq "des" || $encryptionmethod eq "old") { 932 $args = "-s $salt"; 933 } elsif ($encryptionmethod eq "md5") { 934 $args = "-m"; 935 } elsif ($encryptionmethod eq "blowfish") { 936 $args = "-b $salt"; 937 } 938 939 $pass =~ s/(.)/\\$1/g; 940 941 $crypt = `/usr/bin/encrypt $args -- $pass`; 942 chop $crypt; 943 return($crypt); 944} 945 946# print banner 947sub copyright { 948 return; 949} 950 951# hints 952sub hints { 953 if ($verbose) { 954 print "Use option ``-silent'' if you don't want see " . 955 "all warnings & questions.\n\n"; 956 } 957} 958 959# 960sub parse_arguments { 961 local(@argv) = @_; 962 963 while ($_ = $argv[0], /^-/) { 964 shift @argv; 965 last if /^--$/; 966 if (/^--?(v|verbose)$/) { $verbose = 1 } 967 elsif (/^--?(s|silent|q|quiet)$/) { $verbose = 0 } 968 elsif (/^--?(debug)$/) { $verbose = 2 } 969 elsif (/^--?(h|help|\?)$/) { &usage } 970 elsif (/^--?(home)$/) { $home = $argv[0]; shift @argv } 971 elsif (/^--?(shell)$/) { $defaultshell = $argv[0]; shift @argv } 972 elsif (/^--?(dotdir)$/) { $dotdir = $argv[0]; shift @argv } 973 elsif (/^--?(uid_start)$/) { $uid_start = $argv[0]; shift @argv } 974 elsif (/^--?(uid_end)$/) { $uid_end = $argv[0]; shift @argv } 975 elsif (/^--?(group)$/) { $defaultgroup = $argv[0]; shift @argv } 976 elsif (/^--?(check_only)$/) { $check_only = 1 } 977 elsif (/^--?(message)$/) { $send_message = $argv[0]; shift @argv; 978 $sendmessage = 1; } 979 elsif (/^--?(unencrypted)$/) { $unencrypted = 1 } 980 elsif (/^--?(batch)$/) { 981 @batch = splice(@argv, 0, 4); $verbose = 0; 982 die "batch: too few arguments\n" if $#batch < 0; 983 } 984 # see &config_read 985 elsif (/^--?(config_create)$/) { ©right; &hints; &create_conf; exit(0); } 986 elsif (/^--?(noconfig)$/) { $config_read = 0; } 987 elsif (/^--?(e|encryption)$/) { 988 $encryptionmethod = $argv[0]; 989 shift @argv; 990 } 991 else { &usage } 992 } 993 #&usage if $#argv < 0; 994} 995 996sub basename { 997 local($name) = @_; 998 $name =~ s|/+$||; 999 $name =~ s|.*/+||; 1000 return $name; 1001} 1002 1003sub dirname { 1004 local($name) = @_; 1005 $name = &stripdir($name); 1006 $name =~ s|/+[^/]+$||; 1007 $name = "/" unless $name; # dirname of / is / 1008 return $name; 1009} 1010 1011# return 1 if $file is a readable file or link 1012sub filetest { 1013 local($file, $verb) = @_; 1014 1015 if (-e $file) { 1016 if (-f $file || -l $file) { 1017 return 1 if -r _; 1018 warn "$file unreadable\n" if $verbose; 1019 } else { 1020 warn "$file is not a plain file or link\n" if $verbose; 1021 } 1022 } 1023 return 0; 1024} 1025 1026# create or recreate configuration file prompting for values 1027sub create_conf { 1028 $create_conf = 1; 1029 1030 &shells_read; # Pull in /etc/shells info 1031 &shells_add; # maybe add some new shells 1032 $defaultshell = &shell_default; # enter default shell 1033 $home = &home_partition($home); # find HOME partition 1034 $dotdir = &dotdir_default; # check $dotdir 1035 $send_message = &message_default; # send message to new user 1036 $defaultpasswd = &password_default; # maybe use password 1037 $defaultencryption = &encryption_default; # Encryption method 1038 1039 if ($send_message ne 'no') { 1040 &message_create($send_message); 1041 } else { 1042 &message_create($send_message_bak); 1043 } 1044 &config_write(1); 1045} 1046 1047# log for new user in /var/log/adduser 1048sub adduser_log { 1049 local($string) = @_; 1050 local($e); 1051 1052 return 1 if $logfile eq "no"; 1053 1054 local($sec, $min, $hour, $mday, $mon, $year) = localtime; 1055 $mon++; 1056 1057 foreach $e ('sec', 'min', 'hour', 'mday', 'mon', 'year') { 1058 # '7' -> '07' 1059 eval "\$$e = 0 . \$$e" if (eval "\$$e" < 10); 1060 } 1061 1062 &append_file($logfile, "$year/$mon/$mday $hour:$min:$sec $string"); 1063} 1064 1065# create HOME directory, copy dotfiles from $dotdir to $HOME 1066sub home_create { 1067 local($name, $group) = @_; 1068 local($homedir) = "$home/$name"; 1069 1070 if (-e "$homedir") { 1071 warn "HOME Directory ``$homedir'' already exist\a\n"; 1072 return 0; 1073 } 1074 1075 if ($dotdir eq 'no') { 1076 if (!mkdir("$homedir",0755)) { 1077 warn "mkdir $homedir: $!\n"; return 0; 1078 } 1079 system 'chown', "$name:$group", $homedir; 1080 return !$?; 1081 } 1082 1083 # copy files from $dotdir to $homedir 1084 # rename 'dot.foo' files to '.foo' 1085 print "Copy files from $dotdir to $homedir\n" if $verbose; 1086 system("cp -r $dotdir $homedir"); 1087 system("chmod -R u+wrX,go-w $homedir"); 1088 system("chown -R $name:$group $homedir"); 1089 1090 # security 1091 opendir(D, $homedir); 1092 foreach $file (readdir(D)) { 1093 if ($file =~ /^dot\./ && -f "$homedir/$file") { 1094 $file =~ s/^dot\././; 1095 rename("$homedir/dot$file", "$homedir/$file"); 1096 } 1097 chmod(0600, "$homedir/$file") 1098 if ($file =~ /^\.(rhosts|Xauthority|kermrc|netrc)$/); 1099 chmod(0700, "$homedir/$file") 1100 if ($file =~ /^(Mail|prv|\.(iscreen|term))$/); 1101 } 1102 closedir D; 1103 return 1; 1104} 1105 1106# makes a directory hierarchy 1107sub mkdir_home { 1108 local($dir) = @_; 1109 $dir = &stripdir($dir); 1110 local($user_partition) = "/usr"; 1111 local($dirname) = &dirname($dir); 1112 1113 1114 -e $dirname || &mkdirhier($dirname); 1115 1116 if (((stat($dirname))[0]) == ((stat("/"))[0])){ 1117 # home partition is on root partition 1118 # create home partition on $user_partition and make 1119 # a symlink from $dir to $user_partition/`basename $dir` 1120 # For instance: /home -> /usr/home 1121 1122 local($basename) = &basename($dir); 1123 local($d) = "$user_partition/$basename"; 1124 1125 1126 if (-d $d) { 1127 warn "Oops, $d already exist\n" if $verbose; 1128 } else { 1129 print "Create $d\n" if $verbose; 1130 if (!mkdir("$d", 0755)) { 1131 warn "$d: $!\a\n"; return 0; 1132 } 1133 } 1134 1135 unlink($dir); # symlink to nonexist file 1136 print "Create symlink: $dir -> $d\n" if $verbose; 1137 if (!symlink("$d", $dir)) { 1138 warn "Symlink $d: $!\a\n"; return 0; 1139 } 1140 } else { 1141 print "Create $dir\n" if $verbose; 1142 if (!mkdir("$dir", 0755)) { 1143 warn "Directory ``$dir'': $!\a\n"; return 0; 1144 } 1145 } 1146 return 1; 1147} 1148 1149sub mkdirhier { 1150 local($dir) = @_; 1151 local($d,$p); 1152 1153 $dir = &stripdir($dir); 1154 1155 foreach $d (split('/', $dir)) { 1156 $dir = "$p/$d"; 1157 $dir =~ s|^//|/|; 1158 if (! -e "$dir") { 1159 print "Create $dir\n" if $verbose; 1160 if (!mkdir("$dir", 0755)) { 1161 warn "$dir: $!\n"; return 0; 1162 } 1163 } 1164 $p .= "/$d"; 1165 } 1166 return 1; 1167} 1168 1169# stript unused '/' 1170# F.i.: //usr///home// -> /usr/home 1171sub stripdir { 1172 local($dir) = @_; 1173 1174 $dir =~ s|/+|/|g; # delete double '/' 1175 $dir =~ s|/$||; # delete '/' at end 1176 return $dir if $dir ne ""; 1177 return '/'; 1178} 1179 1180# Read one of the elements from @list. $confirm is default. 1181# If !$allow accept only elements from @list. 1182sub confirm_list { 1183 local($message, $allow, $confirm, @list) = @_; 1184 local($read, $c, $print); 1185 1186 $print = "$message" if $message; 1187 $print .= " " unless $message =~ /\n$/ || $#list == 0; 1188 1189 $print .= join($", &uniq(@list)); #" 1190 $print .= " " unless $message =~ /\n$/ && $#list == 0; 1191 print "$print"; 1192 print "\n" if (length($print) + length($confirm)) > 60; 1193 print "[$confirm]: "; 1194 1195 chop($read = <STDIN>); 1196 $read =~ s/^\s*//; 1197 $read =~ s/\s*$//; 1198 return $confirm if $read eq ""; 1199 return "$read" if $allow; 1200 1201 foreach $c (@list) { 1202 return $read if $c eq $read; 1203 } 1204 warn "$read: is not allowed!\a\n"; 1205 return &confirm_list($message, $allow, $confirm, @list); 1206} 1207 1208# YES or NO question 1209# return 1 if &confirm("message", "yes") and answer is yes 1210# or if &confirm("message", "no") an answer is no 1211# otherwise 0 1212sub confirm_yn { 1213 local($message, $confirm) = @_; 1214 local($yes) = '^(yes|YES|y|Y)$'; 1215 local($no) = '^(no|NO|n|N)$'; 1216 local($read, $c); 1217 1218 if ($confirm && ($confirm =~ "$yes" || $confirm == 1)) { 1219 $confirm = "y"; 1220 } else { 1221 $confirm = "n"; 1222 } 1223 print "$message (y/n) [$confirm]: "; 1224 chop($read = <STDIN>); 1225 $read =~ s/^\s*//; 1226 $read =~ s/\s*$//; 1227 return 1 unless $read; 1228 1229 if (($confirm eq "y" && $read =~ "$yes") || 1230 ($confirm eq "n" && $read =~ "$no")) { 1231 return 1; 1232 } 1233 1234 if ($read !~ "$yes" && $read !~ "$no") { 1235 warn "Wrong value. Enter again!\a\n"; 1236 return &confirm_yn($message, $confirm); 1237 } 1238 return 0; 1239} 1240 1241# test if $dotdir exist 1242# return "no" if $dotdir not exist or dotfiles should not copied 1243sub dotdir_default { 1244 local($dir) = $dotdir; 1245 1246 return &dotdir_default_valid($dir) unless $verbose; 1247 while($verbose) { 1248 $dir = &confirm_list("Copy dotfiles from:", 1, 1249 $dir, ("no", $dotdir_bak, $dir)); 1250 last if $dir eq &dotdir_default_valid($dir); 1251 } 1252 warn "Do not copy dotfiles.\n" if $verbose && $dir eq "no"; 1253 1254 $changes++ if $dir ne $dotdir; 1255 return $dir; 1256} 1257 1258sub dotdir_default_valid { 1259 local($dir) = @_; 1260 1261 return $dir if (-e $dir && -r _ && (-d _ || -l $dir) && $dir =~ "^/"); 1262 return $dir if $dir eq "no"; 1263 warn "Dotdir ``$dir'' is not a directory\a\n"; 1264 return "no"; 1265} 1266 1267# ask for messages to new users 1268sub message_default { 1269 local($file) = $send_message; 1270 local(@d) = ($file, $send_message_bak, "no"); 1271 1272 while($verbose) { 1273 $file = &confirm_list("Send message from file:", 1, $file, @d); 1274 last if $file eq "no"; 1275 last if &filetest($file, 1); 1276 1277 # maybe create message file 1278 &message_create($file) if &confirm_yn("Create ``$file''?", "yes"); 1279 last if &filetest($file, 0); 1280 last if !&confirm_yn("File ``$file'' does not exist, try again?", 1281 "yes"); 1282 } 1283 1284 if ($file eq "no" || !&filetest($file, 0)) { 1285 warn "Do not send message\n" if $verbose; 1286 $file = "no"; 1287 } else { 1288 &message_read($file); 1289 } 1290 1291 $changes++ if $file ne $send_message && $verbose; 1292 return $file; 1293} 1294 1295# create message file 1296sub message_create { 1297 local($file) = @_; 1298 1299 rename($file, "$file.bak"); 1300 if (!open(M, "> $file")) { 1301 warn "Messagefile ``$file'': $!\n"; return 0; 1302 } 1303 print M <<EOF; 1304# 1305# Message file for adduser(8) 1306# comment: ``#'' 1307# default variables: \$name, \$fullname, \$password 1308# other variables: see /etc/adduser.conf after 1309# line ``$do_not_delete'' 1310# 1311 1312\$fullname, 1313 1314your account ``\$name'' was created. 1315Have fun! 1316 1317See also chpass(1), finger(1), passwd(1) 1318EOF 1319 close M; 1320 return 1; 1321} 1322 1323# read message file into buffer 1324sub message_read { 1325 local($file) = @_; 1326 @message_buffer = (); 1327 1328 if (!open(R, "$file")) { 1329 warn "File ``$file'':$!\n"; return 0; 1330 } 1331 while(<R>) { 1332 push(@message_buffer, $_) unless /^\s*#/; 1333 } 1334 close R; 1335} 1336 1337# write @list to $file with file-locking 1338sub append_file { 1339 local($file,@list) = @_; 1340 local($e); 1341 local($LOCK_EX) = 2; 1342 local($LOCK_NB) = 4; 1343 local($LOCK_UN) = 8; 1344 1345 open(F, ">> $file") || die "$file: $!\n"; 1346 print "Lock $file.\n" if $verbose > 1; 1347 while(!flock(F, $LOCK_EX | $LOCK_NB)) { 1348 warn "Cannot lock file: $file\a\n"; 1349 die "Sorry, give up\n" 1350 unless &confirm_yn("Try again?", "yes"); 1351 } 1352 print F join("\n", @list) . "\n"; 1353 close F; 1354 print "Unlock $file.\n" if $verbose > 1; 1355 flock(F, $LOCK_UN); 1356} 1357 1358# return free uid+gid 1359# uid == gid if possible 1360sub next_id { 1361 local($group) = @_; 1362 1363 $uid_start = 1000 if ($uid_start <= 0 || $uid_start >= $uid_end); 1364 # looking for next free uid 1365 while($uid{$uid_start}) { 1366 $uid_start++; 1367 $uid_start = 1000 if $uid_start >= $uid_end; 1368 print "$uid_start\n" if $verbose > 1; 1369 } 1370 1371 local($gid_start) = $uid_start; 1372 # group for user (username==groupname) already exist 1373 if ($groupname{$group}) { 1374 $gid_start = $groupname{$group}; 1375 } 1376 # gid is in use, looking for another gid. 1377 # Note: uid an gid are not equal 1378 elsif ($gid{$uid_start}) { 1379 while($gid{$gid_start} || $uid{$gid_start}) { 1380 $gid_start--; 1381 $gid_start = $uid_end if $gid_start < 100; 1382 } 1383 } 1384 return ($uid_start, $gid_start); 1385} 1386 1387# read config file - typically /etc/adduser.conf 1388sub config_read { 1389 local($opt) = @_; 1390 local($user_flag) = 0; 1391 1392 # don't read config file 1393 return 1 if $opt =~ /-(noconfig|config_create)/ || !$config_read; 1394 1395 if (!-f $config) { 1396 warn("Couldn't find $config: creating a new adduser configuration file\n"); 1397 &create_conf; 1398 } 1399 1400 if (!open(C, "$config")) { 1401 warn "$config: $!\n"; return 0; 1402 } 1403 1404 while(<C>) { 1405 # user defined variables 1406 /^$do_not_delete/ && $user_flag++; 1407 # found @array or $variable 1408 if (s/^(\w+\s*=\s*\()/\@$1/ || s/^(\w+\s*=)/\$$1/) { 1409 eval $_; 1410 #warn "$_"; 1411 } 1412 next if /^$/; 1413 # lines with '^##' are not saved 1414 push(@user_variable_list, $_) 1415 if $user_flag && !/^##/ && (s/^[\$\@]// || /^[#\s]/); 1416 } 1417 #warn "X @user_variable_list X\n"; 1418 close C; 1419} 1420 1421 1422# write config file 1423sub config_write { 1424 local($silent) = @_; 1425 1426 # nothing to do 1427 return 1 unless ($changes || ! -e $config || !$config_read || $silent); 1428 1429 if (!$silent) { 1430 if (-e $config) { 1431 return 1 if &confirm_yn("\nWrite your changes to $config?", "no"); 1432 } else { 1433 return 1 unless 1434 &confirm_yn("\nWrite your configuration to $config?", "yes"); 1435 } 1436 } 1437 1438 rename($config, "$config.bak"); 1439 open(C, "> $config") || die "$config: $!\n"; 1440 1441 # prepare some variables 1442 $send_message = "no" unless $send_message; 1443 $defaultpasswd = "no" unless $defaultpasswd; 1444 local($shpref) = "'" . join("', '", @shellpref) . "'"; 1445 local($shpath) = "'" . join("', '", @path) . "'"; 1446 local($user_var) = join('', @user_variable_list); 1447 1448 print C <<EOF; 1449# 1450# $OpenBSD: adduser.perl,v 1.15 1999/02/04 19:38:39 provos Exp $ 1451# $config - automatic generated by adduser(8) 1452# 1453# Note: adduser read *and* write this file. 1454# You may change values, but don't add new things befor the 1455# line ``$do_not_delete'' 1456# 1457 1458# verbose = [0-2] 1459verbose = $verbose 1460 1461# Get new password for new users 1462# defaultpasswd = yes | no 1463defaultpasswd = $defaultpasswd 1464 1465# Default encryption method for user passwords 1466# Methods are all those listed in passwd.conf(5) 1467encryptionmethod = "$defaultencryption" 1468 1469# copy dotfiles from this dir ("/usr/share/skel" or "no") 1470dotdir = "$dotdir" 1471 1472# send this file to new user ("/etc/adduser.message" or "no") 1473send_message = "$send_message" 1474 1475# config file for adduser ("/etc/adduser.conf") 1476config = "$config" 1477 1478# logfile ("/var/log/adduser" or "no") 1479logfile = "$logfile" 1480 1481# default HOME directory ("/home") 1482home = "$home" 1483 1484# List of directories where shells located 1485# path = ('/bin', '/usr/bin', '/usr/local/bin') 1486path = ($shpath) 1487 1488# common shell list, first element has higher priority 1489# shellpref = ('bash', 'tcsh', 'ksh', 'csh', 'sh') 1490shellpref = ($shpref) 1491 1492# defaultshell if not empty ("bash") 1493defaultshell = "$defaultshell" 1494 1495# defaultgroup ('USER' for same as username or any other valid group) 1496defaultgroup = $defaultgroup 1497 1498# new users get this uid 1499uid_start = $uid_start 1500uid_end = $uid_end 1501 1502$do_not_delete 1503## your own variables, see /etc/adduser.message 1504EOF 1505 print C "$user_var\n" if ($user_var ne ''); 1506 print C "\n## end\n"; 1507 close C; 1508} 1509 1510# check for sane variables 1511sub variable_check { 1512 local($abort) = 0; 1513 1514 # Check uid_start & uid_end 1515 warn "WARNING: uid_start < 1000!\n" if($uid_start < 1000); 1516 die "ERROR: uid_start >= uid_end!\n" if($uid_start >= $uid_end); 1517 # unencrypted really only usable in batch mode 1518 warn "WARNING: unencrypted only effective in batch mode\n" 1519 if($#batch < 0 && $unencrypted); 1520} 1521 1522