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 / Init / Services.pm next >
Encoding:
Perl POD Document  |  2006-08-14  |  24.9 KB  |  1,092 lines

  1. #-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  
  3. # Functions for manipulating system services, like daemons and network.
  4. #
  5. # Copyright (C) 2002 Ximian, Inc.
  6. #
  7. # Authors: Carlos Garnacho Parro <garparr@teleline.es>,
  8. #          Hans Petter Jansson <hpj@ximian.com>,
  9. #          Arturo Espinosa <arturo@ximian.com>
  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. package Init::Services;
  26.  
  27. use Init::ServicesList;
  28.  
  29. sub get_runlevel_roles
  30. {
  31.   my (%dist_map, %runlevels);
  32.   my ($desc, $distro);
  33.  
  34.   %dist_map =
  35.     (
  36.      "redhat-6.2"       => "redhat-6.2",
  37.      "redhat-7.0"       => "redhat-6.2",
  38.      "redhat-7.1"       => "redhat-6.2",
  39.      "redhat-7.2"       => "redhat-6.2",
  40.      "redhat-7.3"       => "redhat-6.2",
  41.      "redhat-8.0"       => "redhat-6.2",
  42.      "mandrake-9.0"     => "redhat-6.2",
  43.      "conectiva-9"      => "redhat-6.2",
  44.      "debian-3.0"       => "debian-3.0",
  45.      "suse-9.0"         => "redhat-6.2",
  46.      "pld-1.0"          => "redhat-6.2",
  47.      "vine-3.0"         => "redhat-6.2",
  48.      "slackware-9.1.0"  => "slackware-9.1.0",
  49.      "gentoo"           => "gentoo",
  50.      "freebsd-5"        => "freebsd-5",
  51.     );
  52.  
  53.   %runlevels=
  54.     (
  55.      "redhat-6.2"      => [["0",         "HALT"      ],
  56.                            ["1",         "RECOVER"   ],
  57.                            ["2",         "NONE"      ],
  58.                            ["3",         "TEXT"      ],
  59.                            ["4",         "NONE"      ],
  60.                            ["5",         "GRAPHICAL" ],
  61.                            ["6",         "REBOOT"    ]],
  62.  
  63.      "debian-3.0"      => [["0",         "HALT"      ],
  64.                            ["1",         "RECOVER"   ],
  65.                            ["2",         "NONE"      ],
  66.                            ["3",         "NONE"      ],
  67.                            ["4",         "NONE"      ],
  68.                            ["5",         "NONE"      ],
  69.                            ["6",         "REBOOT"    ]],
  70.  
  71.      "gentoo"          => [["boot",      "BOOT"      ],
  72.                            ["default",   "GRAPHICAL" ],
  73.                            ["nonetwork", "RECOVER"   ]],
  74.  
  75.      "freebsd-5"       => [["default",   "GRAPHICAL" ]],
  76.  
  77.      "slackware-9.1.0" => [["default",   "GRAPHICAL" ]]
  78.     );
  79.  
  80.   $distro = $dist_map{$Utils::Backend::tool{"platform"}};
  81.   $desc = $runlevels{$distro};
  82.  
  83.   return $desc;
  84. }
  85.  
  86. # This function gets the runlevel that is in use
  87. sub get_sysv_default_runlevel
  88. {
  89.     my (@arr);
  90.     @arr = split / /, `/sbin/runlevel` ;
  91.   chomp $arr[1];
  92.  
  93.     return $arr[1];
  94. }
  95.  
  96. sub get_default_runlevel
  97. {
  98.   my $type = &get_init_type ();
  99.  
  100.   return "default" if ($type eq "gentoo" || $type eq "rcng" || $type eq "bsd");
  101.   return &get_sysv_default_runlevel ();
  102. }
  103.  
  104. sub get_sysv_paths
  105. {
  106.   my %dist_map =
  107.     (
  108.      # gst_dist => [rc.X dirs location, init.d scripts location, relative path location]
  109.      "redhat-6.2"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  110.      "redhat-7.0"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  111.      "redhat-7.1"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  112.      "redhat-7.2"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  113.      "redhat-7.3"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  114.      "redhat-8.0"     => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  115.      "mandrake-9.0"   => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  116.      "yoper-2.2"      => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  117.      "conectiva-9"    => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  118.      "debian-3.0"     => ["$gst_prefix/etc",      "$gst_prefix/etc/init.d",      "../init.d"],
  119.      "suse-9.0"       => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d",    "../"],
  120.      "pld-1.0"        => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  121.      "vine-3.0"       => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  122.      "ark"            => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"],
  123.      );
  124.   my $res;
  125.  
  126.   $res = $dist_map{$Utils::Backend::tool{"platform"}};
  127.   &Utils::Report::do_report ("service_sysv_unsupported", $Utils::Backend::tool{"platform"}) if ($res eq undef);
  128.   return @$res;
  129. }
  130.  
  131. # we are going to extract the name of the script
  132. sub get_sysv_service_name
  133. {
  134.     my ($service) = @_;
  135.     
  136.     $service =~ s/$initd_path\///;
  137.   
  138.     return $service;
  139. }
  140.  
  141. # This function gets the state of the service along the runlevels,
  142. # it also returns the average priority
  143. sub get_sysv_runlevels_status
  144. {
  145.     my ($service) = @_;
  146.     my ($link);
  147.     my ($runlevel, $action, $priority);
  148.     my (@arr, @ret);
  149.     
  150.     foreach $link (<$rcd_path/rc[0-6].d/[SK][0-9][0-9]$service>)
  151.     {
  152.         $link =~ s/$rcd_path\///;
  153.         $link =~ /rc([0-6])\.d\/([SK])([0-9][0-9]).*/;
  154.         ($runlevel,$action,$priority)=($1,$2,$3);
  155.  
  156.     if ($action eq "S")
  157.         {
  158.       push @arr, [ $runlevel, "start", $priority ];
  159.     }
  160.         elsif ($action eq "K")
  161.         {
  162.       push @arr, [ $runlevel, "stop", $priority ];
  163.         }
  164.     }
  165.     
  166.     return \@arr;
  167. }
  168.  
  169. # We are going to extract the information of the service
  170. sub get_sysv_service_info
  171. {
  172.     my ($service) = @_;
  173.     my ($script, @actions, @runlevels, $role);
  174.  
  175.     # Return if it's a directory
  176.     return if (-d $service);
  177.     
  178.     # We have to check if the service is executable    
  179.     return unless (-x $service);
  180.  
  181.     $script = &get_sysv_service_name ($service);
  182.         
  183.     # We have to check out if the service is in the "forbidden" list
  184.     return if (&Init::ServicesList::is_forbidden ($script));
  185.  
  186.     $runlevels = &get_sysv_runlevels_status($script);
  187.   $role = &Init::ServicesList::get_role ($script);
  188.  
  189.   return ($script, $role, $runlevels);
  190. }
  191.  
  192. # This function gets an ordered array of the available services from a SysV system
  193. sub get_sysv_services
  194. {
  195.     my ($service);
  196.     my (@arr);
  197.  
  198.     ($rcd_path, $initd_path) = &get_sysv_paths ();
  199.  
  200.   return undef unless ($rcd_path && $initd_path);
  201.  
  202.     foreach $service (<$initd_path/*>)
  203.     {
  204.         my (@info);
  205.  
  206.         @info = &get_sysv_service_info ($service);
  207.     push @arr, \@info  if (scalar (@info));
  208.     }
  209.  
  210.     return \@arr;
  211. }
  212.  
  213. # These are the functions for storing the service settings in SysV
  214. sub remove_sysv_link
  215. {
  216.   my ($rcd_path, $runlevel, $script) = @_;
  217.     
  218.   foreach $link (<$rcd_path/rc$runlevel.d/[SK][0-9][0-9]$script>)
  219.   {
  220.     &Utils::Report::enter ();
  221.     &Utils::Report::do_report ("service_sysv_remove_link", "$link");
  222.     unlink ($link);
  223.     &Utils::Report::leave ();
  224.   }
  225. }
  226.  
  227. sub add_sysv_link
  228. {
  229.   my ($rcd_path, $relative_path, $runlevel, $action, $priority, $service) = @_;
  230.   my ($prio) = sprintf ("%0.2d",$priority);
  231.  
  232.   symlink ("$relative_path/$service", "$rcd_path/rc$runlevel.d/$action$prio$service");
  233.  
  234.   &Utils::Report::enter ();
  235.   &Utils::Report::do_report ("service_sysv_add_link", "$rcd_path/rc$runlevel.d/$action$prio$service");
  236.   &Utils::Report::leave ();
  237. }
  238.  
  239. sub set_sysv_service
  240. {
  241.   my ($service) = @_;
  242.   my ($script, $priority, $runlevels);
  243.   my ($runlevel, $action, %configured_runlevels);
  244.  
  245.   ($rcd_path, $initd_path, $relative_path) = &get_sysv_paths ();
  246.  
  247.   $script = $$service[0];
  248.   $runlevels = $$service[2];
  249.  
  250.   foreach $r (@$runlevels)
  251.   {
  252.     $runlevel = $$r[0];
  253.     $action   = ($$r[1] eq "start") ? "S" : "K";
  254.     $priority = sprintf ("%0.2d", $$r[2]);
  255.  
  256.     $configured_runlevels{$runlevel} = 1;
  257.  
  258.     if (!-f "$rcd_path/rc$runlevel.d/$action$priority$script")
  259.     {
  260.       &remove_sysv_link ($rcd_path, $runlevel, $script);
  261.       &add_sysv_link ($rcd_path, $relative_path, $runlevel, $action, $priority, $script);
  262.     }
  263.   }
  264.  
  265.   # remove unneeded links
  266.   foreach $link (<$rcd_path/rc[0-6].d/[SK][0-9][0-9]$script>)
  267.     {
  268.     $link =~ /rc([0-6])\.d/;
  269.     $runlevel = $1;
  270.  
  271.     if (!exists $configured_runlevels{$runlevel})
  272.     {
  273.       &remove_sysv_link ($rcd_path, $runlevel, $script);
  274.     }
  275.   }
  276. }
  277.  
  278. sub set_sysv_services
  279. {
  280.     my ($services) = @_;
  281.  
  282.     foreach $i (@$services)
  283.     {
  284.         &set_sysv_service($i);
  285.     }
  286. }
  287.  
  288. # This functions get an ordered array of the available services from a file-rc system
  289. sub get_filerc_runlevels_status
  290. {
  291.   my ($start_service, $stop_service, $priority) = @_;
  292.   my (@arr);
  293.  
  294.   # we start with the runlevels in which the service starts
  295.   if ($start_service !~ /-/) {
  296.     my (@runlevels);
  297.  
  298.     @runlevels = split /,/, $start_service;
  299.  
  300.     foreach $runlevel (@runlevels)
  301.     {
  302.       push @arr, [ $runlevel, "start", $priority ];
  303.     }
  304.   }
  305.  
  306.   # now let's go with the runlevels in which the service stops
  307.   if ($stop_service !~ /-/) {
  308.     my (@runlevels);
  309.  
  310.     @runlevels = split /,/, $stop_service;
  311.  
  312.     foreach $runlevel (@runlevels)
  313.     {
  314.       push @arr, [ $runlevel, "stop", $priority ];
  315.     }
  316.   }
  317.  
  318.   return \@arr;
  319. }
  320.  
  321. sub get_filerc_service_info
  322. {
  323.   my ($line, %ret) = @_;
  324.   my (@runlevels, $role);
  325.  
  326.   if ($line =~ /^([0-9][0-9])[\t ]+([0-9\-S,]+)[\t ]+([0-9\-S,]+)[\t ]+\/etc\/init\.d\/(.*)/)
  327.   {
  328.     $priority = $1;
  329.     $stop_service = $2;
  330.     $start_service = $3;
  331.     $script = $4;
  332.  
  333.     return if (&Init::ServicesList::is_forbidden ($script));
  334.  
  335.     $runlevels = &get_filerc_runlevels_status ($start_service, $stop_service, $priority);
  336.     $role = &Init::ServicesList::get_role ($script);
  337.  
  338.     return ($script, $role, $runlevels);
  339.   }
  340.  
  341.   return;
  342. }
  343.  
  344. sub get_filerc_services
  345. {
  346.     my ($script);
  347.   my ($script, @arr, %hash);
  348.  
  349.   open FILE, "$gst_prefix/etc/runlevel.conf" or return undef;
  350.   while ($line = <FILE>)
  351.   {
  352.     next if ($line =~ /^\#.*/);
  353.  
  354.     my (@info);
  355.     my ($start_service, $stop_service);
  356.  
  357.     @info = &get_filerc_service_info ($line);
  358.     next if (!scalar (@info));
  359.  
  360.     $script = $info[0];
  361.  
  362.     if (!$hash{$script})
  363.     {
  364.       $hash{$script} = \@info;
  365.     }
  366.     else
  367.     {
  368.       # We need to mix the runlevels
  369.       foreach $runlevel (@{$info[2]})
  370.       {
  371.         push @{$hash{$script}[2]}, $runlevel;
  372.       }
  373.     }
  374.   }
  375.  
  376.   foreach $key (keys %hash)
  377.   {
  378.     push @arr, $hash{$key};
  379.   }
  380.  
  381.   return \@arr;
  382. }
  383.  
  384. # These are the functions for storing the service settings in file-rc
  385. sub concat_filerc_runlevels
  386. {
  387.   my (@runlevels) = @_;
  388.  
  389.   $str = join (",", sort (@runlevels));
  390.   return ($str) ? $str : "-";
  391. }
  392.  
  393. sub set_filerc_service
  394. {
  395.   my ($buff, $initd_path, $service) = @_;
  396.   my (%hash, $priority, $line, $str);
  397.  
  398.   $runlevels = $$service[2];
  399.  
  400.   foreach $i (@$runlevels)
  401.   {
  402.     $priority = 0 + $$i[2];
  403.     $priority = 50 if ($priority == 0); #very rough guess
  404.  
  405.     if ($$i[1] eq "start")
  406.     {
  407.       $hash{$priority}{"start"} = [] if (!$hash{$priority}{"start"});
  408.       push @{$hash{$priority}{"start"}}, $$i[0];
  409.     }
  410.     else
  411.     {
  412.       $hash{$priority}{"stop"} = [] if (!$hash{$priority}{"stop"});
  413.       push @{$hash{$priority}{"stop"}}, $$i[0];
  414.     }
  415.   }
  416.  
  417.   foreach $priority (keys %hash)
  418.   {
  419.     $line  = sprintf ("%0.2d", $priority) . "\t";
  420.     $line .= &concat_filerc_runlevels (@{$hash{$priority}{"stop"}}) . "\t";
  421.     $line .= &concat_filerc_runlevels (@{$hash{$priority}{"start"}}) . "\t";
  422.     $line .= $initd_path . "/" . $$service{"script"} . "\n";
  423.  
  424.     push @$buff, $line;
  425.   }
  426. }
  427.  
  428. sub set_filerc_services
  429. {
  430.   my ($services) = @_;
  431.   my ($buff, $lineno, $line, $file);
  432.   my ($rcd_path, $initd_path, $relative_path) = &sysv_get_paths ();
  433.  
  434.   $file = "/etc/runlevel.conf";
  435.  
  436.   $buff = &Utils::File::load_buffer ($file);
  437.   &Utils::File::join_buffer_lines ($buff);
  438.  
  439.   $lineno = 0;
  440.  
  441.   # We prepare the file for storing the configuration, save the initial comments
  442.   # and delete the rest
  443.   while ($$buff[$lineno] =~ /^#.*/)
  444.   {
  445.     $lineno++;
  446.   }
  447.  
  448.   for ($i = $lineno; $i < scalar (@$buff); $i++)
  449.   {
  450.     $$buff[$i] =~ /.*\/etc\/init\.d\/(.*)/;
  451.  
  452.     # we need to keep the forbidden services and the services that only start in rcS.d
  453.     if (!&Init::ServicesList::is_forbidden ($1))
  454.     {
  455.       delete $$buff[$i];
  456.     }
  457.   }
  458.  
  459.   # Now we append the services
  460.   foreach $service (@$services)
  461.   {
  462.     &set_filerc_service ($buff, $initd_path, $service);
  463.   }
  464.  
  465.   @$buff = sort @$buff;
  466.  
  467.   push @$buff, "\n";
  468.   &Utils::File::clean_buffer ($buff);
  469.   &Utils::File::save_buffer ($buff, $file);
  470. }
  471.  
  472. # this functions get a list of the services that run on a bsd init
  473. sub get_bsd_service_info
  474. {
  475.   my ($service) = @_;
  476.   my ($script);
  477.   my (%hash);
  478.     my (@arr, @rl);
  479.  
  480.   $script = $service;
  481.   $script =~ s/^.*\///;
  482.   $script =~ s/^rc\.//;
  483.  
  484.   return undef if (! Utils::File::exists ($service));
  485.  
  486.   return undef if (&Init::ServicesList::is_forbidden ($script));
  487.  
  488.   $hash {"script"} = $service;
  489.  
  490.   # we hardcode the fourth runlevel, it's the graphical one
  491.   if ( -x $service)
  492.   {
  493.     push @arr, { "name"   => 4,
  494.                  "action" => "start" };
  495.   }
  496.   else
  497.   {
  498.     push @arr, { "name"   => 4,
  499.                  "action" => "stop" };
  500.   }
  501.  
  502.     push @rl, { "runlevel" => \@arr };
  503.   
  504.     $hash{"runlevels"} = \@rl;
  505.   $hash{"role"} = &Init::ServicesList::get_role ($script);
  506.   
  507.   return \%hash;
  508. }
  509.  
  510. sub get_bsd_services
  511. {
  512.   my (%ret);
  513.   my ($files) = [ "rc.M", "rc.inet2", "rc.4" ];
  514.   my ($file);
  515.  
  516.   foreach $i (@$files)
  517.   {
  518.     $file = "/etc/rc.d/" . $i;
  519.     $fd = &Utils::File::open_read_from_names ($file);
  520.  
  521.     if (!$fd) {
  522.       &Utils::Report::do_report ("rc_file_read_failed", $file);
  523.       return undef;
  524.     }
  525.  
  526.     while (<$fd>)
  527.     {
  528.       $line = $_;
  529.  
  530.       if ($line =~ /^if[ \t]+\[[ \t]+\-x[ \t]([0-9a-zA-Z\/\.\-_]+) .*\]/)
  531.       {
  532.         my (%hash);
  533.         $service = $1;
  534.  
  535.         $hash = &get_bsd_service_info ($service);
  536.  
  537.         if ($hash ne undef)
  538.         {
  539.           $ret{$service} = $hash;
  540.         }
  541.       }
  542.     }
  543.  
  544.     Utils::File::close_file ($fd);
  545.   }
  546.  
  547.   return \%ret;
  548. }
  549.  
  550. # This function stores the configuration in a bsd init
  551. sub set_bsd_services
  552. {
  553.   my ($services) = @_;
  554.   my ($script, $runlevels);
  555.  
  556.     foreach $service (@$services)
  557.     {
  558.     $script = $$service[0];
  559.     $runlevels = $$service[2];
  560.     $runlevel  = $$runlevels[0];
  561.  
  562.     $action = $$runlevel[1];
  563.  
  564.     if ($action eq "start")
  565.     {
  566.       &Utils::File::run ("chmod ugo+x $script");
  567.     }
  568.     else
  569.     {
  570.       &Utils::File::run ("chmod ugo-x $script");
  571.     }
  572.   }
  573. }
  574.  
  575. # these functions get a list of the services that run on a gentoo init
  576. sub get_gentoo_service_status
  577. {
  578.   my ($script, $runlevel) = @_;
  579.   my ($services) = &get_gentoo_services_by_runlevel ($runlevel);
  580.  
  581.   foreach $i (@$services)
  582.   {
  583.     return 1 if ($i eq $script);
  584.   }
  585.  
  586.   return 0;
  587. }
  588.  
  589. sub get_gentoo_runlevels
  590. {
  591.   my($raw_output) = Utils::File::run_backtick("rc-status -l");
  592.   my(@runlevels) = split(/\n/,$raw_output);
  593.  
  594.   return @runlevels;
  595. }
  596.  
  597. sub get_gentoo_services_by_runlevel
  598. {
  599.   my($runlevel) = @_;
  600.   my($raw_output) = Utils::File::run_backtick("rc-status $runlevel");
  601.   my(@raw_lines) = split(/\n/,$raw_output);
  602.   my(@services);
  603.   my($line);
  604.  
  605.   foreach $line (@raw_lines)
  606.   {
  607.     if ($line !~ /^Runlevel/)
  608.     {
  609.       $line=(split(" ",$line))[0];
  610.         push(@services,$line);
  611.       }
  612.   }
  613.  
  614.   return \@services
  615. }
  616.  
  617. sub get_gentoo_services_list
  618. {
  619.   my ($service, @services);
  620.  
  621.   foreach $service (<$gst_prefix/etc/init.d/*>)
  622.   {
  623.     if (-x $service)
  624.     {
  625.       $service =~ s/.*\///;
  626.       push @services, $service;
  627.     }
  628.   }
  629.  
  630.   return \@services;
  631. }
  632.  
  633. sub gentoo_service_exists
  634. {
  635.   my($service) = @_;
  636.   my($services) = &get_gentoo_services_list();
  637.  
  638.   foreach $i (@$services)
  639.   {
  640.     return 1 if ($i =~ /$service/);
  641.   }
  642.  
  643.   return 0;
  644. }
  645.  
  646. sub get_gentoo_runlevels_by_service
  647. {
  648.   my ($service) = @_;
  649.   my(@runlevels,@services_in_runlevel,@contain_runlevels, $runlevel);
  650.   my ($elem);
  651.  
  652.   # let's do some caching to improve performance
  653.   if ($gentoo_services_hash eq undef)
  654.   {
  655.     @runlevels = &get_gentoo_runlevels ();
  656.  
  657.     foreach $runlevel (@runlevels)
  658.     {
  659.       $$gentoo_services_hash{$runlevel} = &get_gentoo_services_by_runlevel ($runlevel);
  660.     }
  661.   }
  662.  
  663.   if (&gentoo_service_exists($service))
  664.   {
  665.     foreach $runlevel (keys %$gentoo_services_hash)
  666.     {
  667.       $services_in_runlevel = $$gentoo_services_hash {$runlevel};
  668.  
  669.       foreach $elem (@$services_in_runlevel)
  670.       {
  671.         push (@contain_runlevels, $runlevel) if ($elem eq $service);
  672.       }
  673.     }
  674.   }
  675.  
  676.   return @contain_runlevels;
  677. }
  678.  
  679. sub get_gentoo_runlevel_status_by_service
  680. {
  681.   my ($service) = @_;
  682.   my (@arr, @ret);
  683.   my (@runlevels) = &get_gentoo_runlevels();
  684.   my (@started) = &get_gentoo_runlevels_by_service($service);
  685.   my (%start_runlevels) = map { $started[$_], 1 } 0 .. $#started;
  686.  
  687.   foreach $runlevel (@runlevels)
  688.   {
  689.     if (defined $start_runlevels{$runlevel})
  690.     {
  691.       push @arr, [ $runlevel, "start", 0 ];
  692.     }
  693.     else
  694.     {
  695.       push @arr, [ $runlevel, "stop", 0 ];
  696.     }
  697.   }
  698.  
  699.   return \@arr;
  700. }
  701.  
  702. sub get_gentoo_service_info
  703. {
  704.     my ($service) = @_;
  705.     my ($script, @actions, @runlevels);
  706.     my ($role);
  707.     
  708.     # We have to check out if the service is in the "forbidden" list
  709.     return if (&Init::ServicesList::is_forbidden ($service));
  710.  
  711.   $runlevels = &get_gentoo_runlevel_status_by_service ($service);
  712.   $role = &Init::ServicesList::get_role ($service);
  713.  
  714.   return ($service, $role, $runlevels);
  715. }
  716.  
  717. sub get_gentoo_services
  718. {
  719.   my ($service);
  720.   my (@arr);
  721.   my ($service_list) = &get_gentoo_services_list ();
  722.  
  723.   foreach $service (@$service_list)
  724.   {
  725.     my (@info);
  726.  
  727.     @info = &get_gentoo_service_info ($service);
  728.     push @arr, \@info if scalar (@info);
  729.   }
  730.  
  731.   return \@arr;
  732. }
  733.  
  734. sub set_gentoo_service_status
  735. {
  736.   my ($script, $rl, $action) = @_;
  737.  
  738.   if ($action eq "start")
  739.   {
  740.     &Utils::File::run ("rc-update add $script $rl");
  741.   }
  742.   elsif ($action eq "stop")
  743.   {
  744.     &Utils::File::run ("rc-update del $script $rl");
  745.   }
  746. }
  747.  
  748. # This function stores the configuration in gentoo init
  749. sub set_gentoo_services
  750. {
  751.   my ($services) = @_;
  752.   my ($action, $rl, $script, $arr);
  753.  
  754.   foreach $service (@$services)
  755.   {
  756.     $script = $$service[0];
  757.     $arr = $$service[2];
  758.  
  759.     foreach $i (@$arr)
  760.     {
  761.       $action = $$i[1];
  762.       $rl = $$i[0];
  763.       &set_gentoo_service_status ($script, $rl, $action);
  764.     }
  765.   }
  766. }
  767.  
  768. # rcNG functions, mostly for FreeBSD
  769. sub get_rcng_status_by_service
  770. {
  771.   my ($service) = @_;
  772.   my ($fd, $line, $active);
  773.  
  774.   # This is the only difference between rcNG and archlinux
  775.   if ($gst_dist eq "archlinux")
  776.   {
  777.       return &Utils::File::exists ("/var/run/daemons/$service");
  778.   }
  779.   else
  780.   {
  781.     $fd = &Utils::File::run_pipe_read ("/etc/rc.d/$service rcvar");
  782.  
  783.     while (<$fd>)
  784.     {
  785.       $line = $_;
  786.  
  787.       if ($line =~ /^\$.*=YES$/)
  788.       {
  789.         $active = 1;
  790.         last;
  791.       }
  792.     }
  793.  
  794.     Utils::File::close_file ($fd);
  795.     return $active;
  796.   }
  797. }
  798.  
  799. sub get_rcng_service_info
  800. {
  801.   my ($service) = @_;
  802.   my ($script, @actions, @runlevels);
  803.   my (%hash, @arr, @rl);
  804.  
  805.   # We have to check if the service is in the "forbidden" list
  806.   return undef if (&Init::ServicesList::is_forbidden ($service));
  807.  
  808.   $hash{"script"} = $service;
  809.  
  810.   if (get_rcng_status_by_service ($service))
  811.   {
  812.     push @arr, { "name"   => "default",
  813.                  "action" => "start" };
  814.   }
  815.   else
  816.   {
  817.     push @arr, { "name"   => "default",
  818.                  "action" => "stop" };
  819.   }
  820.  
  821.   push @rl,  { "runlevel", \@arr };
  822.  
  823.   $hash {"runlevels"} = \@rl;
  824.   $hash {"role"} = &Init::ServicesList::get_role ($service);
  825.  
  826.   return \%hash;
  827. }
  828.  
  829. sub get_rcng_services
  830. {
  831.   my ($service);
  832.   my (%ret);
  833.  
  834.   foreach $service (<$gst_prefix/etc/rc.d/*>)
  835.   {
  836.     my (%hash);
  837.  
  838.     $service =~ s/.*\///;
  839.     $hash = &get_rcng_service_info ($service);
  840.  
  841.     $ret{$service} = $hash if ($hash ne undef);
  842.   }
  843.  
  844.   return \%ret;
  845. }
  846.  
  847. # These functions store the configuration of a rcng init
  848. sub set_rcng_service_status
  849. {
  850.   my ($service, $action) = @_;
  851.   my ($fd, $key, $res);
  852.   my ($default_rcconf) = "/etc/defaults/rc.conf";
  853.   my ($rcconf) = "/etc/rc.conf";
  854.  
  855.   if (&Utils::File::exists ("/etc/rc.d/$service"))
  856.   {
  857.     $fd = &Utils::File::run_pipe_read ("/etc/rc.d/$service rcvar");
  858.  
  859.     while (<$fd>)
  860.     {
  861.       if (/^\$(.*)=.*$/)
  862.       {
  863.         # to avoid cluttering rc.conf with duplicated data,
  864.         # we first look in the defaults/rc.conf for the key
  865.         $key = $1;
  866.         $res = &Utils::Parse::get_sh_bool ($default_rcconf, $key);
  867.  
  868.         if ($res == $action)
  869.         {
  870.           &Utils::Replace::set_sh ($rcconf, $key);
  871.         }
  872.         else
  873.         {
  874.           &Utils::Replace::set_sh_bool ($rcconf, $key, "YES", "NO", $action);
  875.         }
  876.       }
  877.     }
  878.  
  879.     &Utils::File::close_file ($fd);
  880.   }
  881.   elsif (&Utils::File::exists ("/usr/local/etc/rc.d/$service.sh"))
  882.   {
  883.     if ($action)
  884.     {
  885.       Utils::File::copy_file ("/usr/local/etc/rc.d/$service.sh.sample",
  886.                               "/usr/local/etc/rc.d/$service.sh");
  887.     }
  888.     else
  889.     {
  890.       Utils::File::remove ("/usr/local/etc/rc.d/$service.sh");
  891.     }
  892.   }
  893. }
  894.  
  895. sub set_archlinux_service_status
  896. {
  897.   my ($script, $active) = @_;
  898.   my $rcconf = '/etc/rc.conf';
  899.   my ($daemons);
  900.  
  901.   $daemons = &Utils::Parse::get_sh ($rcconf, "DAEMONS");
  902.  
  903.   if (($daemons =~ m/$script/) && !$active)
  904.   {
  905.     $daemons =~ s/$script[ \t]*//;
  906.   }
  907.   elsif (($daemons !~ m/$script/) && $active)
  908.   {
  909.     $daemons =~ s/network/network $script/g;
  910.   }
  911.  
  912.   &Utils::Replace::set_sh ($rcconf, "DAEMONS", $daemons);
  913. }
  914.  
  915. sub set_rcng_services
  916. {
  917.   my ($services) = @_;
  918.   my ($action, $runlevels, $script, $func);
  919.  
  920.   # archlinux stores services differently
  921.   if ($gst_dist eq "archlinux")
  922.   {
  923.     $func = \&set_archlinux_service_status;
  924.   }
  925.   else
  926.   {
  927.     $func = \&set_rcng_service_status;
  928.   }
  929.  
  930.   foreach $service (@$services)
  931.   {
  932.     $script    = $$service[0];
  933.     $runlevels = $$service[2];
  934.     $runlevel  = $$runlevels[0];
  935.     $action    = ($$runlevel[1] eq "start")? 1 : 0;
  936.  
  937.     &$func ($script, $action);
  938.   }
  939. }
  940.  
  941. # SuSE functions, quite similar to SysV, but not equal...
  942. sub get_suse_service_info ($service)
  943. {
  944.   my ($service) = @_;
  945.   my (%hash, @arr, @ret);
  946.                                                                                                                                                              
  947.   # We have to check if the service is in the "forbidden" list
  948.   return undef if (&Init::ServicesList::is_forbidden ($service));
  949.                                                                                                                                                              
  950.   $hash{"script"} = $service;
  951.  
  952.   foreach $link (<$rcd_path/rc[0-9S].d/S[0-9][0-9]$service>)
  953.   {
  954.     $link =~ s/$rcd_path\///;
  955.     $link =~ /rc([0-6])\.d\/S[0-9][0-9].*/;
  956.     $runlevel = $1;
  957.  
  958.     push @arr, { "name"   => $runlevel,
  959.                  "action" => "start" };
  960.   }
  961.  
  962.   foreach $link (<$rcd_path/boot.d/S[0-9][0-9]$service>)
  963.   {
  964.     push @arr, {"name"   => "B",
  965.                 "action" => "start" };
  966.   }
  967.  
  968.   if (scalar @arr > 0)
  969.   {
  970.     push @ret, { "runlevel" => \@arr };
  971.     $hash{"runlevels"} = \@ret;
  972.     $hash{"role"} = &Init::ServicesList::get_role ($service);
  973.   }
  974.  
  975.   return \%hash;
  976. }
  977.  
  978. sub get_suse_services
  979. {
  980.   my ($service, %ret);
  981.  
  982.   ($rcd_path, $initd_path) = &get_sysv_paths ();
  983.  
  984.   foreach $service (<$gst_prefix/etc/init.d/*>)
  985.   {
  986.     my (%hash);
  987.  
  988.     next if (-d $service || ! -x $service);
  989.  
  990.     $service =~ s/.*\///;
  991.     $hash = &get_suse_service_info ($service);
  992.  
  993.     $ret{$service} = $hash if ($hash ne undef);
  994.   }
  995.  
  996.   return \%ret;
  997. }
  998.  
  999. # This function stores the configuration in suse init
  1000. sub set_suse_services
  1001. {
  1002.   my ($services) = @_;
  1003.   my ($action, $runlevels, $script, $rllist);
  1004.  
  1005.   foreach $service (@$services)
  1006.   {
  1007.     $script = $$service[0];
  1008.     $runlevels = $$service[2];
  1009.     $rllist = "";
  1010.  
  1011.     &Utils::File::run ("insserv -r $script");
  1012.  
  1013.     foreach $rl (@$runlevels)
  1014.     {
  1015.       if ($$rl[1] eq "start")
  1016.       {
  1017.         $rllist .= $$rl[0] . ",";
  1018.       }
  1019.     }
  1020.  
  1021.     if ($rllist ne "")
  1022.     {
  1023.       $rllist =~ s/,$//;
  1024.  
  1025.       &Utils::File::run ("insserv $script,start=$rllist");
  1026.     }
  1027.   }
  1028. }
  1029.  
  1030. # generic functions to get the available services
  1031. sub get_init_type
  1032. {
  1033.   my $gst_dist;
  1034.  
  1035.   $gst_dist = $Utils::Backend::tool{"platform"};
  1036.  
  1037.   if (($gst_dist =~ /debian/) && (Utils::File::exists ("/etc/runlevel.conf")))
  1038.   {
  1039.     return "file-rc";
  1040.   }
  1041.   elsif ($gst_dist =~ /slackware/)
  1042.   {
  1043.     return "bsd";
  1044.   }
  1045.   elsif (($gst_dist =~ /freebsd/) || ($gst_dist =~ /archlinux/))
  1046.   {
  1047.     return "rcng";
  1048.   }
  1049.   elsif (($gst_dist =~ /gentoo/) || ($gst_dist =~ /^vlos/))
  1050.   {
  1051.     return "gentoo";
  1052.   }
  1053.   elsif ($gst_dist =~ /suse/)
  1054.   {
  1055.     return "suse";
  1056.   }
  1057.   else
  1058.   {
  1059.     return "sysv";
  1060.   }
  1061. }
  1062.  
  1063. sub get
  1064. {
  1065.   $type = &get_init_type ();
  1066.  
  1067.   return &get_sysv_services ()   if ($type eq "sysv");
  1068.   return &get_filerc_services () if ($type eq "file-rc");
  1069.   return &get_bsd_services ()    if ($type eq "bsd");
  1070.   return &get_gentoo_services () if ($type eq "gentoo");
  1071.   return &get_rcng_services ()   if ($type eq "rcng");
  1072.   return &get_suse_services ()   if ($type eq "suse");
  1073.  
  1074.   return undef;
  1075. }
  1076.  
  1077. sub set
  1078. {
  1079.     my ($services) = @_;
  1080.  
  1081.   $type = &get_init_type ();
  1082.  
  1083.   &set_sysv_services   ($services) if ($type eq "sysv");
  1084.   &set_filerc_services ($services) if ($type eq "file-rc");
  1085.   &set_bsd_services    ($services) if ($type eq "bsd");
  1086.   &set_gentoo_services ($services) if ($type eq "gentoo");
  1087.   &set_rcng_services   ($services) if ($type eq "rcng");
  1088.   &set_suse_services   ($services) if ($type eq "suse");
  1089. }
  1090.  
  1091. 1;
  1092.