home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / system-tools-backends-2.0 / scripts / Users / Users.pm < prev   
Encoding:
Perl POD Document  |  2006-08-14  |  18.0 KB  |  707 lines

  1. #-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. # Users account manager. Designed to be architecture and distribution independent.
  3. #
  4. # Copyright (C) 2000-2001 Ximian, Inc.
  5. #
  6. # Authors: Hans Petter Jansson <hpj@ximian.com>,
  7. #          Arturo Espinosa <arturo@ximian.com>,
  8. #          Tambet Ingo <tambet@ximian.com>.
  9. #          Grzegorz Golawski <grzegol@pld-linux.org> (PLD Support)
  10. #
  11. # This program is free software; you can redistribute it and/or modify
  12. # it under the terms of the GNU Library General Public License as published
  13. # by the Free Software Foundation; either version 2 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. # GNU Library General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU Library General Public License
  22. # along with this program; if not, write to the Free Software
  23. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  24.  
  25. # Best viewed with 100 columns of width.
  26.  
  27. # Configuration files affected:
  28. #
  29. # /etc/passwd
  30. # /etc/group
  31. # /etc/shadow
  32. # /etc/login.defs
  33. # /etc/shells
  34. # /etc/skel/
  35.  
  36. # NIS support will come later.
  37.  
  38. # Running programs affected/used:
  39. #
  40. # adduser: creating users.
  41. # usermod: modifying user data.
  42. # passwd: assigning or changing passwords. (Un)locking users.
  43. # chfn: modifying finger information - Name, Office, Office phone, Home phone.
  44. # pw: modifying users/groups and user/group data on FreeBSD.
  45.  
  46. package Users::Users;
  47.  
  48. use Utils::Util;
  49. use Utils::Report;
  50. use Utils::File;
  51. use Utils::Backend;
  52. use Utils::Replace;
  53.  
  54. # --- System config file locations --- #
  55.  
  56. # We list each config file type with as many alternate locations as possible.
  57. # They are tried in array order. First found = used.
  58. @passwd_names =     ( "/etc/passwd" );
  59. @shadow_names =     ( "/etc/shadow", "/etc/master.passwd" );
  60. @login_defs_names = ( "/etc/login.defs", "/etc/adduser.conf" );
  61. @shell_names =      ( "/etc/shells" );
  62. @skel_dir =         ( "/usr/share/skel", "/etc/skel" );
  63.  
  64. # Where are the tools?
  65. $cmd_usermod  = &Utils::File::locate_tool ("usermod");
  66. $cmd_userdel  = &Utils::File::locate_tool ("userdel");
  67. $cmd_useradd  = &Utils::File::locate_tool ("useradd");
  68.  
  69. $cmd_adduser  = &Utils::File::locate_tool ("adduser");
  70. $cmd_deluser  = &Utils::File::locate_tool ("deluser");
  71.  
  72. $cmd_chfn     = &Utils::File::locate_tool ("chfn");
  73. $cmd_pw       = &Utils::File::locate_tool ("pw");
  74.  
  75. # enum like for verbose group array positions
  76. my $LOGIN   = 0;
  77. my $PASSWD  = 1;
  78. my $UID     = 2;
  79. my $GID     = 3;
  80. my $COMMENT = 4;
  81. my $HOME    = 5;
  82. my $SHELL   = 6;
  83.  
  84. %login_defs_prop_map = ();
  85. %profiles_prop_map = ();
  86.  
  87. sub get_login_defs_prop_array
  88. {
  89.   my @prop_array;
  90.   my @login_defs_prop_array_default =
  91.     (
  92.      "QMAIL_DIR",      "qmail_dir",
  93.      "MAIL_DIR",       "mailbox_dir",
  94.      "MAIL_FILE",      "mailbox_file",
  95.      "PASS_MAX_DAYS",  "pwd_maxdays",
  96.      "PASS_MIN_DAYS",  "pwd_mindays",
  97.      "PASS_MIN_LEN",   "pwd_min_length",
  98.      "PASS_WARN_AGE",  "pwd_warndays",
  99.      "UID_MIN",        "umin",
  100.      "UID_MAX",        "umax",
  101.      "GID_MIN",        "gmin",
  102.      "GID_MAX",        "gmax",
  103.      "USERDEL_CMD",    "del_user_additional_command",
  104.      "CREATE_HOME",    "create_home",
  105.      "", "");
  106.  
  107.   my @login_defs_prop_array_suse =
  108.     (
  109.      "QMAIL_DIR",      "qmail_dir",
  110.      "MAIL_DIR",       "mailbox_dir",
  111.      "MAIL_FILE",      "mailbox_file",
  112.      "PASS_MAX_DAYS",  "pwd_maxdays",
  113.      "PASS_MIN_DAYS",  "pwd_mindays",
  114.      "PASS_MIN_LEN",   "pwd_min_length",
  115.      "PASS_WARN_AGE",  "pwd_warndays",
  116.      "UID_MIN",        "umin",
  117.      "UID_MAX",        "umax",
  118.      "SYSTEM_GID_MIN", "gmin",
  119.      "GID_MAX",        "gmax",
  120.      "USERDEL_CMD",    "del_user_additional_command",
  121.      "CREATE_HOME",    "create_home",
  122.      "", "");
  123.  
  124.   if ($Utils::Backend::tool{"platform"} =~ /^suse/)
  125.   {
  126.     @prop_array = @login_defs_prop_array_suse;
  127.   }
  128.   else
  129.   {
  130.     @prop_array = @login_defs_prop_array_default;
  131.   }
  132.  
  133.   for ($i = 0; $prop_array [$i] ne ""; $i += 2)
  134.   {
  135.     $login_defs_prop_map {$prop_array [$i]}     = $prop_array [$i + 1];
  136.     $login_defs_prop_map {$prop_array [$i + 1]} = $prop_array [$i];
  137.   }
  138. }
  139.  
  140. sub get_profiles_prop_array
  141. {
  142.   my @prop_array;
  143.   my @profiles_prop_array_default =
  144.     (
  145.      "NAME" ,          "name",
  146.      "COMMENT",        "comment",
  147.      "LOGINDEFS",      "login_defs",
  148.      "HOME_PREFFIX",   "home_prefix",
  149.      "SHELL",          "shell",
  150.      "GROUP",          "group",
  151.      "SKEL_DIR",       "skel_dir",
  152.      "QMAIL_DIR" ,     "qmail_dir",
  153.      "MAIL_DIR" ,      "mailbox_dir",
  154.      "MAIL_FILE" ,     "mailbox_file",
  155.      "PASS_RANDOM",    "pwd_random",
  156.      "PASS_MAX_DAYS" , "pwd_maxdays",
  157.      "PASS_MIN_DAYS" , "pwd_mindays",
  158.      "PASS_MIN_LEN" ,  "pwd_min_length",
  159.      "PASS_WARN_AGE" , "pwd_warndays",
  160.      "UID_MIN" ,       "umin",
  161.      "UID_MAX" ,       "umax",
  162.      "GID_MIN" ,       "gmin",
  163.      "GID_MAX" ,       "gmax",
  164.      "USERDEL_CMD" ,   "del_user_additional_command",
  165.      "CREATE_HOME" ,   "create_home",
  166.      "", "");
  167.  
  168.   my @profiles_prop_array_suse =
  169.     (
  170.      "NAME" ,          "name",
  171.      "COMMENT",        "comment",
  172.      "LOGINDEFS",      "login_defs",
  173.      "HOME_PREFFIX",   "home_prefix",
  174.      "SHELL",          "shell",
  175.      "GROUP",          "group",
  176.      "SKEL_DIR",       "skel_dir",
  177.      "QMAIL_DIR" ,     "qmail_dir",
  178.      "MAIL_DIR" ,      "mailbox_dir",
  179.      "MAIL_FILE" ,     "mailbox_file",
  180.      "PASS_RANDOM",    "pwd_random",
  181.      "PASS_MAX_DAYS" , "pwd_maxdays",
  182.      "PASS_MIN_DAYS" , "pwd_mindays",
  183.      "PASS_MIN_LEN" ,  "pwd_min_length",
  184.      "PASS_WARN_AGE" , "pwd_warndays",
  185.      "UID_MIN" ,       "umin",
  186.      "UID_MAX" ,       "umax",
  187.      "GID_MIN" ,       "gmin",
  188.      "GID_MAX" ,       "gmax",
  189.      "USERDEL_CMD" ,   "del_user_additional_command",
  190.      "CREATE_HOME" ,   "create_home",
  191.      "", "");
  192.  
  193.   if ($Utils::Backend::tool{"platform"} =~ /suse/)
  194.   {
  195.     @prop_array = @profiles_prop_array_suse;
  196.   }
  197.   else
  198.   {
  199.     @prop_array = @profiles_prop_array_default;
  200.   }
  201.  
  202.   for ($i = 0; $prop_array[$i] ne ""; $i += 2)
  203.   {
  204.     $profiles_prop_map {$prop_array [$i]}     = $prop_array [$i + 1];
  205.     $profiles_prop_map {$prop_array [$i + 1]} = $prop_array [$i];
  206.   }
  207. }
  208.  
  209. my $rh_logindefs_defaults = {
  210.   'shell'    => '/bin/bash',
  211.   'group'    => -1,
  212.   'skel_dir' => '/etc/skel/',
  213. };
  214.  
  215. my $gentoo_logindefs_defaults = {
  216.   'shell'    => '/bin/bash',
  217.   'group'    => 100,
  218.   'skel_dir' => '/etc/skel/',
  219. };
  220.  
  221. my $freebsd_logindefs_defaults = {
  222.   'shell'    => '/bin/sh',
  223.   'group'    => -1,
  224.   'skel_dir' => '/etc/skel/',
  225. };
  226.  
  227. my $logindefs_dist_map = {
  228.   'redhat-6.2'      => $rh_logindefs_defaults,
  229.   'redhat-7.0'      => $rh_logindefs_defaults,
  230.   'redhat-7.1'      => $rh_logindefs_defaults,
  231.   'redhat-7.2'      => $rh_logindefs_defaults,
  232.   'redhat-7.3'      => $rh_logindefs_defaults,
  233.   'redhat-8.0'      => $rh_logindefs_defaults,
  234.   'mandrake-9.0'    => $rh_logindefs_defaults,
  235.   'pld-1.0'         => $rh_logindefs_defaults,
  236.   'fedora-1'        => $rh_logindefs_defaults,
  237.   'debian-3.0'      => $rh_logindefs_defaults,
  238.   'vine-3.0'        => $rh_logindefs_defaults,
  239.   'gentoo'            => $gentoo_logindefs_defaults,
  240.   'archlinux'       => $gentoo_logindefs_defaults,
  241.   'slackware-9.1.0' => $gentoo_logindefs_defaults,
  242.   'freebsd-5'       => $freebsd_logindefs_defaults,
  243.   'suse-9.0'        => $gentoo_logindefs_defaults,
  244. };
  245.  
  246.  
  247. # Add reporting table.
  248.  
  249. &Utils::Report::add ({
  250.   'users_read_profiledb_success' => ['info', 'Profiles read successfully.'],
  251.   'users_read_profiledb_fail'    => ['warn', 'Profiles read failed.'],
  252.   'users_read_users_success'     => ['info', 'Users read successfully.'],
  253.   'users_read_users_fail'        => ['warn', 'Users read failed.'],
  254.   'users_read_groups_success'    => ['info', 'Groups read successfully.'],
  255.   'users_read_groups_fail'       => ['warn', 'Groups read failed.'],
  256.   'users_read_shells_success'    => ['info', 'Shells read successfully.'],
  257.   'users_read_shells_fail'       => ['warn', 'Reading shells failed.'],
  258.  
  259.   'users_write_profiledb_success' => ['info', 'Profiles written successfully.'],
  260.   'users_write_profiledb_fail'    => ['warn', 'Writing profiles failed.'],
  261.   'users_write_users_success'     => ['info', 'Users written successfully.'],
  262.   'users_write_users_fail'        => ['warn', 'Writing users failed.'],
  263.   'users_write_groups_success'    => ['info', 'Groups written successfully.'],
  264.   'users_write_groups_fail'       => ['warn', 'Writing groups failed.'],
  265. });
  266.  
  267.  
  268. sub do_get_use_md5
  269. {
  270.   my ($file) = @_;
  271.   my ($fh, @line, $i, $use_md5);
  272.  
  273.   my $fh = &Utils::File::open_read_from_names ("/etc/pam.d/$file");
  274.   return 0 if (!$fh);
  275.  
  276.   $use_md5 = 0;
  277.  
  278.   while (<$fh>)
  279.   {
  280.     next if &Utils::Util::ignore_line ($_);
  281.     chomp;
  282.     @line = split /[ \t]+/;
  283.  
  284.     if ($line[0] eq "\@include")
  285.     {
  286.       $use_md5 = &do_get_use_md5 ($line[1]);
  287.     }
  288.     elsif ($line[0] eq "password")
  289.     {
  290.       foreach $i (@line)
  291.       {
  292.         $use_md5 = 1 if ($i eq "md5");
  293.       }
  294.     }
  295.   }
  296.  
  297.   close $fh;
  298.   return $use_md5;
  299. }
  300.  
  301. sub get_use_md5
  302. {
  303.   return &do_get_use_md5 ("passwd");
  304. }
  305.  
  306. sub logindefs_add_defaults
  307. {
  308.   # Common for all distros
  309.   my $logindefs = {
  310.     'home_prefix' => '/home/',
  311.   };
  312.  
  313.   &get_profiles_prop_array ();
  314.  
  315.   # Distro specific
  316.   my $dist_specific = $logindefs_dist_map->{$Utils::Backend::tool{"platform"}};
  317.  
  318.   # Just to be 100% sure SOMETHING gets filled:
  319.   unless ($dist_specific)
  320.   {
  321.     $dist_specific = $rh_logindefs_defaults;
  322.   }
  323.  
  324.   foreach my $key (keys %$dist_specific)
  325.   {
  326.     # Make sure there's no crappy entries
  327.     if (exists ($profiles_prop_map{$key}) || $key eq "groups")
  328.     {
  329.       $logindefs->{$key} = $dist_specific->{$key};
  330.     }
  331.   }
  332.   return $logindefs;
  333. }
  334.  
  335. sub get_logindefs
  336. {
  337.   my $logindefs;
  338.  
  339.   &get_login_defs_prop_array ();
  340.   $logindefs = &logindefs_add_defaults ();
  341.  
  342.   # Get new data in case someone has changed login_defs manually.
  343.   my $fh = &Utils::File::open_read_from_names (@login_defs_names);
  344.  
  345.   if ($fh)
  346.   {
  347.     while (<$fh>)
  348.     {
  349.       next if &Utils::Util::ignore_line ($_);
  350.       chomp;
  351.       my @line = split /[ \t]+/;
  352.  
  353.       if (exists $login_defs_prop_map{$line[0]})
  354.       {
  355.         $logindefs->{$login_defs_prop_map{$line[0]}} = $line[1];
  356.       }
  357.     }
  358.  
  359.     close $fh;
  360.   }
  361.   else
  362.   {
  363.     # Put safe defaults for distros/OS that don't have any defaults file
  364.     $logindefs->{"umin"} = '1000';
  365.     $logindefs->{"umax"} = '60000';
  366.     $logindefs->{"gmin"} = '1000';
  367.     $logindefs->{"gmax"} = '60000';
  368.   }
  369.  
  370.   return $logindefs;
  371. }
  372.  
  373. sub get
  374. {
  375.   my ($ifh, @users, %users_hash);
  376.   my (@line, @users);
  377.  
  378.   # Find the passwd file.
  379.   $ifh = &Utils::File::open_read_from_names(@passwd_names);
  380.   return unless ($ifh);
  381.  
  382.   while (<$ifh>)
  383.   {
  384.     chomp;
  385.     # FreeBSD allows comments in the passwd file.
  386.     next if &Utils::Util::ignore_line ($_);
  387.  
  388.     @line  = split ':', $_, -1;
  389.  
  390.     $login = $line[$LOGIN];
  391.     @comment = split ',', $line[$COMMENT], 5;
  392.  
  393.     # we need to make sure that there are 5 elements
  394.     push @comment, "" while (scalar (@comment) < 5);
  395.     $line[$COMMENT] = [@comment];
  396.     
  397.     $users_hash{$login} = [@line];
  398.   }
  399.  
  400.   &Utils::File::close_file ($ifh);
  401.   $ifh = &Utils::File::open_read_from_names(@shadow_names);
  402.  
  403.   if ($ifh)
  404.   {
  405.     while (<$ifh>)
  406.     {
  407.       chomp;
  408.  
  409.       # FreeBSD allows comments in the shadow passwd file.
  410.       next if &Utils::Util::ignore_line ($_);
  411.  
  412.       @line = split ':', $_, -1;
  413.       $login = shift @line;
  414.       $passwd = shift @line;
  415.  
  416.       $users_hash{$login}[$PASSWD] = $passwd;
  417.  
  418.       # FIXME: add the rest of the fields?
  419.       #push @{$$users_hash{$login}}, @line;
  420.     }
  421.  
  422.     &Utils::File::close_file ($ifh);
  423.   }
  424.  
  425.   # transform the hash into an array
  426.   foreach $login (keys %users_hash)
  427.   {
  428.     push @users, $users_hash{$login};
  429.   }
  430.  
  431.   return \@users;
  432. }
  433.  
  434. sub get_files
  435. {
  436.   my @arr;
  437.  
  438.   push @arr, @passwd_names;
  439.   push @arr, @shadow_names;
  440.  
  441.   return \@arr;
  442. }
  443.  
  444.  
  445. sub del_user
  446. {
  447.     my ($user) = @_;
  448.   my ($command);
  449.     
  450.   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
  451.   {
  452.     $command = "$cmd_pw userdel -n \'" . $$user[$LOGIN] . "\' ";
  453.   }
  454.   else
  455.   {
  456.     if ($cmd_deluser)
  457.     {
  458.       $command = "$cmd_deluser '". $$user[$LOGIN] . "'";
  459.     }
  460.     else
  461.     {
  462.       $command = "$cmd_userdel \'" . $$user[$LOGIN] . "\'";
  463.     }
  464.   }
  465.  
  466.   &Utils::File::run ($command);
  467. }
  468.  
  469. sub change_user_chfn
  470. {
  471.   my ($login, $old_comment, $comment) = @_;
  472.   my ($fname, $office, $office_phone, $home_phone);
  473.   my ($command);
  474.  
  475.   return if !$login;
  476.  
  477.   # Compare old and new data
  478.   return if (Utils::Util::struct_eq ($old_comment, $comment));
  479.  
  480.   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
  481.   {
  482.     my ($str);
  483.  
  484.     $str = join (",", @$comment);
  485.     $command = "$cmd_pw usermod -n " . $login . " -c \'" . $str . "\'";
  486.   }
  487.   else
  488.   {
  489.     ($fname, $office, $office_phone, $home_phone) = @$comment;
  490.  
  491.     $command = "$cmd_chfn" .
  492.         " -f \'" . $fname . "\'" .
  493.         " -h \'" . $home_phone . "\'";
  494.  
  495.     if ($Utils::Backend::tool{"platform"} =~ /^debian/ ||
  496.         $Utils::Backend::tool{"platform"} =~ /^archlinux/)
  497.     {
  498.       $command .= " -r \'" . $office . "\'" .
  499.           " -w \'" . $office_phone . "\'";
  500.     }
  501.     else
  502.     {
  503.       $command .= " -o \'" . $office . "\'" .
  504.           " -p \'" . $office_phone . "\'";
  505.     }
  506.  
  507.     $command .= " $login";
  508.   }
  509.  
  510.   &Utils::File::run ($command);
  511. }
  512.  
  513. sub add_user
  514. {
  515.     my ($user) = @_;
  516.     my ($home_parents, $tool_mkdir);
  517.   
  518.   $tool_mkdir = &Utils::File::locate_tool ("mkdir");
  519.  
  520.   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
  521.   {
  522.     my $pwdpipe;
  523.     my $home;
  524.  
  525.     # FreeBSD doesn't create the home directory
  526.     $home = $$user[$HOME];
  527.     &Utils::File::run ("$tool_mkdir -p $home");
  528.  
  529.     $command = "$cmd_pw useradd " .
  530.         " -n \'" . $$user[$LOGIN] . "\'" .
  531.         " -u \'" . $$user[$UID]   . "\'" .
  532.         " -d \'" . $$user[$HOME]  . "\'" .
  533.         " -g \'" . $$user[$GID]   . "\'" .
  534.         " -s \'" . $$user[$SHELL] . "\'" .
  535.         " -H 0"; # pw(8) reads password from STDIN
  536.  
  537.     $pwdpipe = &Utils::File::run_pipe_write ($command);
  538.     print $pwdpipe $$user[$PASSWD];
  539.     &Utils::File::close_file ($pwdpipe);
  540.   }
  541.   else
  542.   {
  543.     $home_parents = $$user[$HOME];
  544.     $home_parents =~ s/\/+[^\/]+\/*$//;
  545.     &Utils::File::run ("$tool_mkdir -p $home_parents");
  546.  
  547.     if ($cmd_adduser)
  548.     {
  549.       # use adduser if available, set empty gecos fields
  550.       # and password, they will be filled out later
  551.       $command = "$cmd_adduser --gecos '' --disabled-password" .
  552.           " --home \'"  . $$user[$HOME]   . "\'" .
  553.           " --gid \'"   . $$user[$GID]    . "\'" .
  554.           " --shell \'" . $$user[$SHELL]  . "\'" .
  555.           " --uid \'"   . $$user[$UID]    . "\'" .
  556.           " \'"         . $$user[$LOGIN]  . "\'";
  557.  
  558.       &Utils::File::run ($command);
  559.  
  560.       # password can't be set in non-interactive
  561.       # mode with adduser, call usermod instead
  562.       $command = "$cmd_usermod " .
  563.           " -p '" . $$user[$PASSWD] . "' " . $$user[$LOGIN];
  564.  
  565.       &Utils::File::run ($command);
  566.     }
  567.     else
  568.     {
  569.       # fallback to useradd
  570.       $command = "$cmd_useradd -m" .
  571.           " --home \'"     . $$user[$HOME]   . "\'" .
  572.           " --gid \'"      . $$user[$GID]    . "\'" .
  573.           " --password \'" . $$user[$PASSWD] . "\'" .
  574.           " --shell \'"    . $$user[$SHELL]  . "\'" .
  575.           " --uid \'"      . $$user[$UID]    . "\'" .
  576.           " \'"            . $$user[$LOGIN]  . "\'";
  577.  
  578.       &Utils::File::run ($command);
  579.     }
  580.   }
  581.  
  582.   &change_user_chfn ($$user[$LOGIN], undef, $$user[$COMMENT]);
  583. }
  584.  
  585. sub change_user
  586. {
  587.   my ($old_user, $new_user) = @_;
  588.     
  589.   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
  590.   {
  591.     my $pwdpipe;
  592.  
  593.     $command = "$cmd_pw usermod \'" . $$old_user[$LOGIN] . "\'" .
  594.         " -l \'" . $$new_user[$LOGIN] . "\'" .
  595.         " -u \'" . $$new_user[$UID]   . "\'" .
  596.         " -d \'" . $$new_user[$HOME]  . "\'" .
  597.         " -g \'" . $$new_user[$GID]   . "\'" .
  598.         " -s \'" . $$new_user[$SHELL] . "\'" .
  599.         " -H 0"; # pw(8) reads password from STDIN
  600.  
  601.     $pwdpipe = &Utils::File::run_pipe_write ($command);
  602.     print $pwdpipe $$new_user[$PASSWD];
  603.     &Utils::File::close_file ($pwdpipe);
  604.   }
  605.   else
  606.   {
  607.     $command = "$cmd_usermod" .
  608.         " -d \'" . $$new_user[$HOME]   . "\'" .
  609.         " -g \'" . $$new_user[$GID]    . "\'" .
  610.         " -l \'" . $$new_user[$LOGIN]  . "\'" .
  611.         " -p \'" . $$new_user[$PASSWD] . "\'" .
  612.         " -s \'" . $$new_user[$SHELL]  . "\'" .
  613.         " -u \'" . $$new_user[$UID]    . "\'" .
  614.         " \'" . $$old_user[$LOGIN] . "\'";
  615.  
  616.     &Utils::File::run ($command);
  617.   }
  618.  
  619.   &change_user_chfn ($$new_user[$LOGIN], $$old_user[$COMMENT], $$new_user[$COMMENT]);
  620. }
  621.  
  622. sub set_logindefs
  623. {
  624.   my ($config) = @_;
  625.   my ($logindefs, $key, $file);
  626.  
  627.   return unless $config;
  628.  
  629.   &get_login_defs_prop_array ();
  630.  
  631.   foreach $key (@login_defs_names)
  632.   {
  633.     if (-f $key)
  634.     {
  635.       $file = $key;
  636.       last;
  637.     }
  638.   }
  639.  
  640.   unless ($file) 
  641.   {
  642.     &Utils::Report::do_report ("file_open_read_failed", join (", ", @login_defs_names));
  643.     return;
  644.   }
  645.  
  646.   foreach $key (keys (%$config))
  647.   {
  648.     # Write ONLY login.defs values.
  649.     if (exists ($login_defs_prop_map{$key}))
  650.     {
  651.       &Utils::Replace::split ($file, $login_defs_prop_map{$key}, "[ \t]+", $$config{$key});
  652.     }
  653.   }
  654. }
  655.  
  656. sub set
  657. {
  658.   my ($config) = @_;
  659.   my ($old_config, %users);
  660.   my (%config_hash, %old_config_hash);
  661.  
  662.   if ($config)
  663.   {
  664.     # Make backups manually, otherwise they don't get backed up.
  665.     &Utils::File::do_backup ($_) foreach (@passwd_names);
  666.     &Utils::File::do_backup ($_) foreach (@shadow_names);
  667.  
  668.     $old_config = &get ();
  669.  
  670.     foreach $i (@$config) 
  671.     {
  672.       $users{$$i[0]} |= 1;
  673.       $config_hash{$$i[0]} = $i;
  674.       }    
  675.     
  676.     foreach $i (@$old_config)
  677.     {
  678.       $users{$$i[0]} |= 2;
  679.       $old_config_hash{$$i[0]} = $i;
  680.     }
  681.  
  682.     # Delete all groups that only appeared in the old configuration
  683.     foreach $i (sort (keys (%users)))
  684.     {
  685.       $state = $users{$i};
  686.  
  687.       if ($state == 1)
  688.       {
  689.         # Groups with state 1 have been added to the config
  690.         &add_user ($config_hash{$i});
  691.       }
  692.       elsif ($state == 2)
  693.       {
  694.         # Groups with state 2 have been deleted from the config
  695.         &del_user ($old_config_hash{$i});
  696.       }
  697.       elsif (($state == 3) &&
  698.              (!Utils::Util::struct_eq ($config_hash{$i}, $old_config_hash{$i})))
  699.       {
  700.         &change_user ($old_config_hash{$i}, $config_hash{$i});
  701.       }
  702.       }
  703.   }
  704. }
  705.  
  706. 1;
  707.