#!/usr/bin/env perl # Functions for manipulating system services, like daemons and network. # # Copyright (C) 2002 Ximian, Inc. # # Authors: Carlos Garnacho Parro , # Hans Petter Jansson , # Arturo Espinosa # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. $rcd_path; $initd_path; $relative_path; $SCRIPTSDIR = "@scriptsdir@"; $FILESDIR = "@filesdir@"; if ($SCRIPTSDIR =~ /^@scriptsdir[@]/) { $FILESDIR = "files"; $SCRIPTSDIR = "."; $DOTIN = ".in"; } use File::Copy; require "$SCRIPTSDIR/file.pl$DOTIN"; require "$SCRIPTSDIR/report.pl$DOTIN"; require "$SCRIPTSDIR/service-list.pl$DOTIN"; # Where is the SysV subsystem installed? sub gst_service_sysv_get_paths { my %dist_map = ( # gst_dist => [rc.X dirs location, init.d scripts location, relative path location] "redhat-5.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-6.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-6.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-6.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-7.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-7.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-7.3" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-8.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "redhat-9" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "openna-1.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "rhel-5" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "rhel-6" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "rhel-7" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-7.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-7.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-9.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-9.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-9.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-10.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-10.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandrake-10.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandriva-2006.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandriva-2006.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandriva-2007.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "mandriva-2007.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "yoper-2.2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "blackpanther-4.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "conectiva-9" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "conectiva-10" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "debian-2.2" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-3.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-3.1" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-4.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-5.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-6.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-7.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-8.0" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "debian-testing" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-5.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-5.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-6.06" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-6.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-7.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-7.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-8.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-8.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-9.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-9.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-10.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-10.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-11.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-11.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-12.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-12.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-13.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-13.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-14.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-14.10" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "ubuntu-15.04" => ["$gst_prefix/etc", "$gst_prefix/etc/init.d", "../init.d"], "suse-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d", "../"], "suse-9.0" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-9.1" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-10.0" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-10.1" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-10.2" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-10.3" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-10.4" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-11.0" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-11.1" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-11.2" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "suse-11.3" => ["$gst_prefix/etc/init.d", "$gst_prefix/etc/init.d", "../"], "turbolinux-7.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "pld-1.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "pld-1.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "pld-1.99" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "pld-2.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "pld-2.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-2" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-3" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-4" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-5" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "rpath" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-15" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-16" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-17" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-18" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-19" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-20" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "fedora-21" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "vine-3.0" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "vine-3.1" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], "ark" => ["$gst_prefix/etc/rc.d", "$gst_prefix/etc/rc.d/init.d", "../init.d"], ); my $res; $res = $dist_map{$gst_dist}; &gst_report ("service_sysv_unsupported", $gst_dist) if ($res eq undef); return @$res; } # Those runlevels that are usually used. Maybe we should add # the current running runlevel, using the "runlevel" command. sub gst_service_sysv_get_runlevels { my %dist_map = ( "redhat-5.2" => [3, 5], "redhat-6.0" => [3, 5], "redhat-6.1" => [3, 5], "redhat-6.2" => [3, 5], "redhat-7.0" => [3, 5], "redhat-7.1" => [3, 5], "redhat-7.2" => [3, 5], "redhat-7.3" => [3, 5], "redhat-8.0" => [3, 5], "redhat-9" => [3, 5], "openna-1.0" => [3, 5], "rhel-5" => [3, 5], "rhel-6" => [3, 5], "rhel-7" => [3, 5], "mandrake-7.1" => [3, 5], "mandrake-7.2" => [3, 5], "mandrake-9.0" => [3, 5], "mandrake-9.1" => [3, 5], "mandrake-9.2" => [3, 5], "mandrake-10.0" => [3, 5], "mandrake-10.1" => [3, 5], "mandrake-10.2" => [3, 5], "mandriva-2006.0" => [3, 5], "mandriva-2006.1" => [3, 5], "mandriva-2007.0" => [3, 5], "mandriva-2007.1" => [3, 5], "yoper-2.2" => [3, 5], "blackpanther-4.0" => [3, 5], "conectiva-9" => [3, 5], "conectiva-10" => [3, 5], "debian-2.2" => [2, 3], "debian-3.0" => [2, 3], "debian-3.1" => [2, 3], "debian-4.0" => [2, 3], "debian-5.0" => [2, 3], "debian-6.0" => [2, 3], "debian-7.0" => [2, 3], "debian-8.0" => [2, 3], "debian-testing" => [2, 3], "ubuntu-5.04" => [2, 3], "ubuntu-5.10" => [2, 3], "ubuntu-6.06" => [2, 3], "ubuntu-6.10" => [2, 3], "ubuntu-7.04" => [2, 3], "ubuntu-7.10" => [2, 3], "ubuntu-8.04" => [2, 3], "ubuntu-8.10" => [2, 3], "ubuntu-9.04" => [2, 3], "ubuntu-9.10" => [2, 3], "ubuntu-10.04" => [2, 3], "ubuntu-10.10" => [2, 3], "ubuntu-11.04" => [2, 3], "ubuntu-11.10" => [2, 3], "ubuntu-12.04" => [2, 3], "ubuntu-12.10" => [2, 3], "ubuntu-13.04" => [2, 3], "ubuntu-13.10" => [2, 3], "ubuntu-14.04" => [2, 3], "ubuntu-14.10" => [2, 3], "ubuntu-15.04" => [2, 3], "suse-7.0" => [3, 5], "suse-9.0" => [3, 5], "suse-9.1" => [3, 5], "suse-10.0" => [3, 5], "suse-10.1" => [3, 5], "suse-10.2" => [3, 5], "suse-10.3" => [3, 5], "suse-10.4" => [3, 5], "suse-11.0" => [3, 5], "suse-11.1" => [3, 5], "suse-11.2" => [3, 5], "suse-11.3" => [3, 5], "turbolinux-7.0" => [3, 5], "pld-1.0" => [3, 5], "pld-1.1" => [3, 5], "pld-1.99" => [3, 5], "pld-2.0" => [3, 5], "pld-3.0" => [3, 5], "fedora-1" => [3, 5], "fedora-2" => [3, 5], "fedora-3" => [3, 5], "fedora-4" => [3, 5], "fedora-5" => [3, 5], "rpath" => [3, 5], "fedora-15" => [3, 5], "fedora-16" => [3, 5], "fedora-17" => [3, 5], "fedora-18" => [3, 5], "fedora-19" => [3, 5], "fedora-20" => [3, 5], "fedora-21" => [3, 5], "vine-3.0" => [3, 5], "vine-3.1" => [3, 5], "ark" => [3, 5], ); my $res; $res = $dist_map{$gst_dist}; &gst_report ("service_sysv_unsupported", $gst_dist) if ($res eq undef); return @$res; } sub gst_service_get_runlevel_roles { my (%dist_map, %runlevels, $desc, $distro); %dist_map = ( "redhat-5.2" => "redhat-5.2", "redhat-6.0" => "redhat-5.2", "redhat-6.1" => "redhat-5.2", "redhat-6.2" => "redhat-5.2", "redhat-7.0" => "redhat-5.2", "redhat-7.1" => "redhat-5.2", "redhat-7.2" => "redhat-5.2", "redhat-7.3" => "redhat-5.2", "redhat-8.0" => "redhat-5.2", "redhat-9" => "redhat-5.2", "openna-1.0" => "redhat-5.2", "rhel-5" => "redhat-5.2", "rhel-6" => "redhat-5.2", "rhel-7" => "redhat-5.2", "mandrake-7.1" => "redhat-5.2", "mandrake-7.2" => "redhat-5.2", "mandrake-9.0" => "redhat-5.2", "mandrake-9.1" => "redhat-5.2", "mandrake-9.2" => "redhat-5.2", "mandrake-10.0" => "redhat-5.2", "mandrake-10.1" => "redhat-5.2", "mandrake-10.2" => "redhat-5.2", "mandriva-2006.0" => "redhat-5.2", "mandriva-2006.1" => "redhat-5.2", "mandriva-2007.0" => "redhat-5.2", "mandriva-2007.1" => "redhat-5.2", "yoper-2.2" => "redhat-5.2", "blackpanther-4.0" => "redhat-5.2", "conectiva-9" => "redhat-5.2", "conectiva-10" => "redhat-5.2", "debian-2.2" => "debian-2.2", "debian-3.0" => "debian-2.2", "debian-3.1" => "debian-2.2", "debian-4.0" => "debian-2.2", "debian-5.0" => "debian-2.2", "debian-6.0" => "debian-2.2", "debian-7.0" => "debian-2.2", "debian-8.0" => "debian-2.2", "debian-testing" => "debian-2.2", "ubuntu-5.04" => "debian-2.2", "ubuntu-5.10" => "debian-2.2", "ubuntu-6.06" => "debian-2.2", "ubuntu-6.10" => "debian-2.2", "ubuntu-7.04" => "debian-2.2", "ubuntu-7.10" => "debian-2.2", "ubuntu-8.04" => "debian-2.2", "ubuntu-8.10" => "debian-2.2", "ubuntu-9.04" => "debian-2.2", "ubuntu-9.10" => "debian-2.2", "ubuntu-10.04" => "debian-2.2", "ubuntu-10.10" => "debian-2.2", "ubuntu-11.04" => "debian-2.2", "ubuntu-11.10" => "debian-2.2", "ubuntu-12.04" => "debian-2.2", "ubuntu-12.10" => "debian-2.2", "ubuntu-13.04" => "debian-2.2", "ubuntu-13.10" => "debian-2.2", "ubuntu-14.04" => "debian-2.2", "ubuntu-14.10" => "debian-2.2", "ubuntu-15.04" => "debian-2.2", "suse-7.0" => "redhat-5.2", "suse-9.0" => "redhat-5.2", "suse-9.1" => "redhat-5.2", "suse-10.0" => "redhat-5.2", "suse-10.1" => "redhat-5.2", "suse-10.2" => "redhat-5.2", "suse-10.3" => "redhat-5.2", "suse-10.4" => "redhat-5.2", "suse-11.0" => "redhat-5.2", "suse-11.1" => "redhat-5.2", "suse-11.2" => "redhat-5.2", "suse-11.3" => "redhat-5.2", "turbolinux-7.0" => "redhat-5.2", "pld-1.0" => "redhat-5.2", "pld-1.1" => "redhat-5.2", "pld-1.99" => "redhat-5.2", "fedora-1" => "redhat-5.2", "fedora-2" => "redhat-5.2", "fedora-3" => "redhat-5.2", "fedora-4" => "redhat-5.2", "fedora-5" => "redhat-5.2", "rpath" => "redhat-5.2", "fedora-15" => "redhat-5.2", "fedora-16" => "redhat-5.2", "fedora-17" => "redhat-5.2", "fedora-18" => "redhat-5.2", "fedora-19" => "redhat-5.2", "fedora-20" => "redhat-5.2", "fedora-21" => "redhat-5.2", "vine-3.0" => "redhat-5.2", "vine-3.1" => "redhat-5.2", "ark" => "redhat-5.2", "slackware-9.1.0" => "slackware-9.1.0", "slackware-10.0.0" => "slackware-9.1.0", "slackware-10.1.0" => "slackware-9.1.0", "slackware-10.2.0" => "slackware-9.1.0", "slackware-11.0.0" => "slackware-9.1.0", "slackware-12.0.0" => "slackware-9.1.0", "slackware-12.1.0" => "slackware-9.1.0", "slackware-12.2.0" => "slackware-9.1.0", "slackware-13.0.0" => "slackware-9.1.0", "slackware-13.1.0" => "slackware-9.1.0", "slackware-13.37.0" => "slackware-9.1.0", "slackware-14.0.0" => "slackware-9.1.0", "slackware-14.1.0" => "slackware-9.1.0", "gentoo" => "gentoo", "vlos-1.2" => "gentoo", "archlinux" => "freebsd-5", "freebsd-5" => "freebsd-5", "freebsd-6" => "freebsd-5", "freebsd-7" => "freebsd-5", "freebsd-8" => "freebsd-5", "freebsd-9" => "freebsd-5", "freebsd-10" => "freebsd-5", ); %runlevels= ( "redhat-5.2" => {"0" => "HALT", "1" => "RECOVER", "2" => "NONE", "3" => "TEXT", "4" => "NONE", "5" => "GRAPHICAL", "6" => "REBOOT" }, "debian-2.2" => {"0" => "HALT", "1" => "RECOVER", "2" => "NONE", "3" => "NONE", "4" => "NONE", "5" => "NONE", "6" => "REBOOT" }, "gentoo" => {"boot" => "BOOT", "default" => "GRAPHICAL", "nonetwork" => "RECOVER" }, "freebsd-5" => {"rc" => "GRAPHICAL" }, "slackware-9.1.0" => {"4" => "GRAPHICAL" } ); $distro = $dist_map{$gst_dist}; $desc = $runlevels{$distro}; return $runlevels{$distro}; } # --- Plain process utilities --- # # Get owners list (login) of named process. sub gst_service_proc_get_owners { my ($service) = @_; my ($user, $pid, $command); my ($fd); my (@arr); &gst_report_enter (); $fd = gst_file_run_pipe_read ("ps acx -o user,pid,command"); while (<$fd>) { /(.*)[ \t]+(.*)[ \t]+(.*)/; $user = $1; $pid = $2; $command = $3; push @arr, $user if ($command eq $service); } &gst_report_leave (); return \@arr; } # Stops all instances of a process sub gst_service_proc_stop_all { my ($service) = @_; return &gst_file_run ("killall $service"); } # Starts instances of a process for a given list of users sub gst_service_proc_start_all { my ($cmd, $users) = @_; my ($fqcmd, $fqsu); $fqcmd = &gst_file_get_cmd_path ($cmd); $fqsu = &gst_file_locate_tool ("su"); foreach $user (@$users) { # Can't use gst_file_run_bg here, since it clobbers the quotes. system ("$fqsu $user -c \"$fqcmd &\" >/dev/null 2>/dev/null"); } } sub gst_service_sysv_list_dir { my ($path) = @_; my ($service, @services); foreach $service (<$path/*>) { if (-x $service) { $service =~ s/.*\///; push @services, $service; } } return \@services; } sub gst_service_sysv_list_available { my ($rcd_path, $initd_path); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); return &gst_service_sysv_list_dir ($initd_path); } # Return 1 or 0: is the service running? # Depends on the rc script to support the "status" arg. # Maybe we should do something more portable. sub gst_service_sysv_get_status { my ($service) = @_; my ($rc_path, $initd_path, $res); my ($pid); &gst_report_enter (); # Stolen from RedHat's /etc/rc.d/init.d/functions:status # FIXME: portable to other UNIXES? $pid = &gst_file_run_backtick ("pidof -o %PPID -x $service"); chomp $pid; if ($pid) { $res = 1; &gst_report ("service_status_running", $service); } else { $res = 0; &gst_report ("service_status_stopped", $service); } # ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); # $res = 0; # # if (-f "$initd_path/$service") # { # $res = &gst_file_run ("$initd_path/$service status")? 0 : 1; # &gst_report ("service_status_running", $service) if $res; # &gst_report ("service_status_stopped", $service) if !$res; # } &gst_report_leave (); return $res; } # If any of the passed services is running, return true. sub gst_service_sysv_get_status_any { my (@services) = @_; my $i; foreach $i (@services) { return 1 if &gst_service_sysv_get_status ($i); } return 0; } # Set start links and remove stop links at the usual runlevels. # Old start link is removed, in case the priority is different from $pri. sub gst_service_sysv_set_links_active { my ($pri, $service) = @_; foreach $runlevel (&gst_service_sysv_get_runlevels ()) { &gst_service_sysv_remove_link ($runlevel, $service); &gst_service_sysv_add_link ($runlevel, "S", $pri, $service); } } # Set stop links and remove start links at the usual runlevels. sub gst_service_sysv_set_links_inactive { my ($pri, $service) = @_; foreach $runlevel (&gst_service_sysv_get_runlevels ()) { &gst_service_sysv_remove_link ($runlevel, "$service"); &gst_service_sysv_add_link ($runlevel, "K", $pri, $service); } } # Set links for active/inactive service at the given priority. sub gst_service_sysv_set_links { my ($pri, $service, $active) = @_; if ($active) { &gst_service_sysv_set_links_active ($pri, $service); } else { &gst_service_sysv_set_links_inactive (100 - $pri, $service); } } # Start or stop the service, depending on $active. Set # links accordingly. $force makes this function use # start/stop only, without considerations for restart. # Not to be called from parse/replace tables, due to last $force # param: use the following two functions instead. sub gst_service_sysv_set_status_do { my ($priority, $service, $active, $force) = @_; my ($arg, $status); &gst_service_sysv_set_links ($priority, $service, $active); $status = &gst_service_sysv_get_status ($service); if ($status && !$force) { # if it's already active and you want it active, restart. $arg = $active? "restart" : "stop"; } else { # normal operation. $arg = $active? "start" : "stop"; } return &gst_service_sysv_run_initd_script ($service, $arg); } sub gst_service_sysv_set_status { my ($priority, $service, $active) = @_; return &gst_service_sysv_set_status_do ($priority, $service, $active, 0); } sub gst_service_sysv_force_status { my ($priority, $service, $active) = @_; return &gst_service_sysv_set_status_do ($priority, $service, $active, 1); } sub gst_service_sysv_install_script { my ($service, $file) = @_; my ($res, $rcd_path, $initd_path); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); if (!copy ("$FILESDIR/$file", "$initd_path/$service")) { &gst_report ("file_copy_failed", "$FILESDIR/$file", "$initd_path/$service"); return -1; } chmod (0755, "$initd_path/$service"); return 0; } # THESE ARE THE FUNCTIONS WHICH EXTRACT THE CONFIGURATION FROM THE COMPUTER # we are going to extract the name of the script sub gst_service_sysv_get_service_name { my ($service) = @_; $service =~ s/$initd_path\///; return $service; } # This function gets the state of the service along the runlevels, # it also returns the average priority sub gst_service_sysv_get_runlevels_status { my ($service) = @_; my ($link); my ($runlevel, $action, $priority); my (@arr, @ret); foreach $link (<$rcd_path/rc[0-6].d/[SK][0-9][0-9]$service>) { $link =~ s/$rcd_path\///; $link =~ /rc([0-6])\.d\/([SK])([0-9][0-9]).*/; ($runlevel,$action,$priority)=($1,$2,$3); if ($action eq "S") { push @arr, { "name" => $runlevel, "priority" => $priority, "action" => "start" }; } elsif ($action eq "K") { push @arr, { "name" => $runlevel, "priority" => (100 - $priority), "action" => "stop" }; } } return undef if (scalar(@arr) eq 0); push @ret, { "runlevel" => \@arr }; return \@ret; } # We are going to extract the information of the service sub gst_service_sysv_get_service_info { my ($service) = @_; my ($script, @actions, @runlevels); my %hash, $role; # Return if it's a directory return undef if (-d $service); # We have to check if the service is executable return undef unless (-x $service); $script = &gst_service_sysv_get_service_name ($service); # We have to check out if the service is in the "forbidden" list return undef if (&gst_service_list_service_is_forbidden ($script)); $runlevels = &gst_service_sysv_get_runlevels_status($script); $hash{"script"} = $script; $hash{"runlevels"} = $runlevels unless ($runlevels eq undef); $hash{"role"} = &gst_service_get_role ($script); return \%hash; } # This function gets an ordered array of the available services from a SysV system sub gst_service_sysv_get_services { my ($service); my (@arr,%ret); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); foreach $service (<$initd_path/*>) { my (%hash); $hash = &gst_service_sysv_get_service_info ($service); if ($hash ne undef) { $ret{$service} = $hash; } } return \%ret; } # This functions get an ordered array of the available services from a file-rc system sub gst_service_filerc_get_runlevels_status { my ($start_service, $stop_service, $priority) = @_; my (@arr, @ret); # we start with the runlevels in which the service starts if ($start_service !~ /-/) { my (@runlevels); @runlevels = split /,/, $start_service; foreach $runlevel (@runlevels) { push @arr, { "name" => $runlevel, "action" => "start", "priority" => $priority}; } } # now let's go with the runlevels in which the service stops if ($stop_service !~ /-/) { my (@runlevels); @runlevels = split /,/, $stop_service; foreach $runlevel (@runlevels) { push @arr, { "name" => $runlevel, "action" => "stop", "priority" => $priority}; } } push @ret, {"runlevel" => \@arr}; return \@ret; } sub gst_service_filerc_get_service_info { my ($line, %ret) = @_; my %hash; my @runlevels; if ($line =~ /^([0-9][0-9])[\t ]+([0-9\-S,]+)[\t ]+([0-9\-S,]+)[\t ]+\/etc\/init\.d\/(.*)/) { $priority = $1; $stop_service = $2; $start_service = $3; $script = $4; return undef if (&gst_service_list_service_is_forbidden ($script)); $hash{"script"} = $script; $hash{"runlevels"} = &gst_service_filerc_get_runlevels_status ($start_service, $stop_service, $priority); $hash{"role"} = &gst_service_get_role ($script); return (\%hash); } return undef; } sub gst_service_filerc_get_services { my ($script); my (%ret); open FILE, "$gst_prefix/etc/runlevel.conf" or return undef; while ($line = ) { if ($line !~ /^#.*/) { my (%hash); my ($start_service, $stop_service); $hash = &gst_service_filerc_get_service_info ($line); if ($hash ne undef) { $script = $$hash{"script"}; if ($ret{$script} eq undef) { $ret{$script} = $hash; } else { my (@runlevels); # We need to mix the runlevels @runlevels = $$hash{"runlevels"}[0]{"runlevel"}; foreach $runlevel (@runlevels) { push @{$ret{$script}{"runlevels"}[0]{"runlevel"}}, $runlevel; } } } } } return \%ret; } # this functions get a list of the services that run on a bsd init sub gst_service_bsd_get_service_info { my ($service) = @_; my ($script); my (%hash); my (@arr, @rl); $script = $service; $script =~ s/^.*\///; $script =~ s/^rc\.//; return undef if (! gst_file_exists ($service)); return undef if (&gst_service_list_service_is_forbidden ($script)); $hash {"script"} = $service; # we hardcode the fourth runlevel, it's the graphical one if ( -x $service) { push @arr, { "name" => 4, "action" => "start" }; } else { push @arr, { "name" => 4, "action" => "stop" }; } push @rl, { "runlevel" => \@arr }; $hash{"runlevels"} = \@rl; $hash{"role"} = &gst_service_get_role ($script); return \%hash; } sub gst_service_bsd_get_services { my (%ret); my ($files) = [ "rc.M", "rc.inet2", "rc.4" ]; my ($file); foreach $i (@$files) { $file = "/etc/rc.d/" . $i; $fd = &gst_file_open_read_from_names ($file); if (!$fd) { &gst_report ("rc_file_read_failed", $file); return undef; } while (<$fd>) { $line = $_; if ($line =~ /^if[ \t]+\[[ \t]+\-x[ \t]([0-9a-zA-Z\/\.\-_]+) .*\]/) { my (%hash); $service = $1; $hash = &gst_service_bsd_get_service_info ($service); if ($hash ne undef) { $ret{$service} = $hash; } } } gst_file_close ($fd); } return \%ret; } # these functions get a list of the services that run on a gentoo init sub gst_service_gentoo_get_service_status { my ($script, $runlevel) = @_; my ($services) = &gst_service_gentoo_get_services_by_runlevel ($runlevel); foreach $i (@$services) { return 1 if ($i eq $script); } return 0; } sub gst_service_gentoo_get_runlevels { my($raw_output) = gst_file_run_backtick("rc-status -l"); my(@runlevels) = split(/\n/,$raw_output); return @runlevels; } sub gst_service_gentoo_get_services_by_runlevel { my($runlevel) = @_; my($raw_output) = gst_file_run_backtick("rc-status $runlevel"); my(@raw_lines) = split(/\n/,$raw_output); my(@services); my($line); foreach $line (@raw_lines) { if ($line !~ /^Runlevel/) { $line=(split(" ",$line))[0]; push(@services,$line); } } return \@services } sub gst_service_gentoo_get_services_list { return &gst_service_sysv_list_dir ("/etc/init.d/"); } sub gst_service_gentoo_service_exist { my($service) = @_; my($services) = &gst_service_gentoo_get_services_list(); foreach $i (@$services) { return 1 if ($i =~ /$service/); } return 0; } sub gst_service_gentoo_get_runlevels_by_service { my ($service) = @_; my(@runlevels,@services_in_runlevel,@contain_runlevels, $runlevel); my ($elem); # let's do some caching to improve performance if ($gentoo_services_hash eq undef) { @runlevels = &gst_service_gentoo_get_runlevels (); foreach $runlevel (@runlevels) { $$gentoo_services_hash{$runlevel} = &gst_service_gentoo_get_services_by_runlevel ($runlevel); } } if (&gst_service_gentoo_service_exist($service)) { foreach $runlevel (keys %$gentoo_services_hash) { $services_in_runlevel = $$gentoo_services_hash {$runlevel}; foreach $elem (@$services_in_runlevel) { push (@contain_runlevels, $runlevel) if ($elem eq $service); } } } return @contain_runlevels; } sub gst_service_gentoo_runlevel_status_by_service { my ($service) = @_; my (@arr, @ret); my (@runlevels) = &gst_service_gentoo_get_runlevels(); my (@started) = &gst_service_gentoo_get_runlevels_by_service($service); my (%start_runlevels) = map { $started[$_], 1 } 0 .. $#started; foreach $runlevel (@runlevels) { if (defined $start_runlevels{$runlevel}) { push @arr, { "name" => $runlevel, "action" => "start" }; } else { push @arr, { "name" => $runlevel, "action" => "stop" }; } } push @ret, { "runlevel" => \@arr }; return @ret; } sub gst_service_gentoo_get_service_info { my ($service) = @_; my ($script, @actions, @runlevels); my %hash; # We have to check out if the service is in the "forbidden" list return undef if (&gst_service_list_service_is_forbidden ($service)); my($runlevels) = &gst_service_gentoo_runlevel_status_by_service ($service); $hash{"script"} = $service; $hash{"runlevels"} = $runlevels unless ($runlevels eq undef); $hash{"role"} = &gst_service_get_role ($service); return \%hash; } sub gst_service_gentoo_get_services { my ($service); my (%ret); my ($service_list) = &gst_service_gentoo_get_services_list (); foreach $service (@$service_list) { my (%hash); $hash = &gst_service_gentoo_get_service_info ($service); $ret{$service} = $hash if ($hash ne undef); } return \%ret; } # rcNG functions, mostly for FreeBSD sub gst_service_archlinux_status_by_service { my ($service) = @_; return 1 if( -f "/var/run/daemons/$service"); return 0; } sub gst_service_rcng_status_by_service { my ($service) = @_; my ($fd, $line, $active); $fd = &gst_file_run_pipe_read ("/etc/rc.d/$service rcvar"); while (<$fd>) { $line = $_; if ($line =~ /^\$.*=YES$/) { $active = 1; last; } } gst_file_close ($fd); return $active; } sub gst_service_rcng_get_service_info { my ($service) = @_; my ($script, @actions, @runlevels); my (%hash, @arr, @rl); # We have to check if the service is in the "forbidden" list return undef if (&gst_service_list_service_is_forbidden ($service)); $hash{"script"} = $service; if (gst_service_rcng_status_by_service ($service)) { push @arr, { "name" => "rc", "action" => "start" }; } else { push @arr, { "name" => "rc", "action" => "stop" }; } push @rl, { "runlevel", \@arr }; $hash {"runlevels"} = \@rl; $hash{"role"} = &gst_service_get_role ($service); return \%hash; } sub gst_service_archlinux_get_service_info { my ($service) = @_; my ($script, @actions, @runlevels); my (%hash, @arr, @rl); # We have to check if the service is in the "forbidden" list return undef if (&gst_service_list_service_is_forbidden ($service)); $hash{"script"} = $service; if (&gst_service_archlinux_status_by_service ($service)) { push @arr, { "name" => "rc", "action" => "start" }; } else { push @arr, { "name" => "rc", "action" => "stop" }; } push @rl, { "runlevel", \@arr }; $hash {"runlevels"} = \@rl; $hash{"role"} = &gst_service_get_role ($service); return \%hash; } sub gst_service_archlinux_get_services { my ($service); my (%ret); foreach $service (<$gst_prefix/etc/rc.d/*>) { my (%hash); $service =~ s/.*\///; $hash = &gst_service_archlinux_get_service_info ($service); $ret{$service} = $hash if ($hash ne undef); } return \%ret; } sub gst_service_rcng_get_services { my ($service); my (%ret); foreach $service (<$gst_prefix/etc/rc.d/*>) { my (%hash); $service =~ s/.*\///; $hash = &gst_service_rcng_get_service_info ($service); $ret{$service} = $hash if ($hash ne undef); } return \%ret; } # SuSE functions, quite similar to SysV, but not equal... sub gst_service_suse_get_service_info ($service) { my ($service) = @_; my (%hash, @arr, @ret); # We have to check if the service is in the "forbidden" list return undef if (&gst_service_list_service_is_forbidden ($service)); $hash{"script"} = $service; foreach $link (<$rcd_path/rc[0-9S].d/S[0-9][0-9]$service>) { $link =~ s/$rcd_path\///; $link =~ /rc([0-6])\.d\/S[0-9][0-9].*/; $runlevel = $1; push @arr, { "name" => $runlevel, "action" => "start" }; } foreach $link (<$rcd_path/boot.d/S[0-9][0-9]$service>) { push @arr, {"name" => "B", "action" => "start" }; } if (scalar @arr > 0) { push @ret, { "runlevel" => \@arr }; $hash{"runlevels"} = \@ret; $hash{"role"} = &gst_service_get_role ($service); } return \%hash; } sub gst_service_suse_get_services { my ($service, %ret); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); foreach $service (<$gst_prefix/etc/init.d/*>) { my (%hash); next if (-d $service || ! -x $service); $service =~ s/.*\///; $hash = &gst_service_suse_get_service_info ($service); $ret{$service} = $hash if ($hash ne undef); } return \%ret; } # generic functions to get the available services sub gst_get_init_type { if (($gst_dist =~ /debian/) && (stat ("$gst_prefix/etc/runlevel.conf"))) { return "file-rc"; } elsif ($gst_dist =~ /slackware/) { return "bsd"; } elsif ($gst_dist =~ /freebsd/) { return "rcng"; } elsif ($gst_dist =~ /archlinux/) { return "archlinux"; } elsif (($gst_dist =~ /gentoo/) || ($gst_dist =~ /^vlos/)) { return "gentoo"; } elsif ($gst_dist =~ /suse/) { return "suse"; } else { return "sysv"; } } sub gst_service_get_services { $type = &gst_get_init_type (); return &gst_service_sysv_get_services () if ($type eq "sysv"); return &gst_service_filerc_get_services () if ($type eq "file-rc"); return &gst_service_bsd_get_services () if ($type eq "bsd"); return &gst_service_gentoo_get_services () if ($type eq "gentoo"); return &gst_service_rcng_get_services () if ($type eq "rcng"); return &gst_service_suse_get_services () if ($type eq "suse"); return &gst_service_archlinux_get_services() if ($type eq "archlinux"); return undef; } # This function gets the runlevel that is in use sub gst_service_sysv_get_default_runlevel { my (@arr); @arr = split / /, `/sbin/runlevel` ; $arr[1] =~ s/\n//; return $arr[1]; } sub gst_service_get_default_runlevel { my ($type) = &gst_get_init_type (); return "default" if ($type eq "gentoo"); return "rc" if ($type eq "rcng"); return "rc" if ($type eq "archlinux"); return &gst_service_sysv_get_default_runlevel (); } # THESE ARE THE FUNCTIONS WHICH APPLY THE CHANGES MADE TO THE CONFIGURATION OF THE COMPUTER sub gst_service_sysv_add_link { my ($runlevel, $action, $priority, $service) = @_; my ($prio) = sprintf ("%0.2d",$priority); symlink ("$relative_path/$service", "$rcd_path/rc$runlevel.d/$action$prio$service"); &gst_report_enter (); &gst_report ("service_sysv_add_link", "$rcd_path/rc$runlevel.d/$action$prio$service"); &gst_report_leave (); } sub gst_service_sysv_remove_link { my ($runlevel, $script) = @_; foreach $link (<$rcd_path/rc$runlevel.d/[SK][0-9][0-9]$script>) { &gst_report ("service_sysv_remove_link", "$link"); unlink ("$link"); &gst_report_leave (); } } # These are the functions for storing the service settings from XML in SysV sub gst_service_sysv_set_service { my ($service) = @_; my ($script, $priority, $runlevels); my ($action); ($rcd_path, $initd_path, $relative_path) = &gst_service_sysv_get_paths (); $script = $$service{"script"}; $runlevels = $$service{"runlevels"}[0]{"runlevel"}; # pass though all the runlevels checking if the service must be started, stopped or removed for ($i = 0; $i <= 6; $i++) { &gst_service_sysv_remove_link ($i, $script); $action = undef; foreach $j (@$runlevels) { if ($i == $$j{"name"}) { $found = 1; $action = $$j{"action"}; $priority = $$j{"priority"}; $priority = 50 if (!$priority); #very rough guess } } if ($action ne undef) { if ($action eq "start") { &gst_service_sysv_add_link ($i, "S", $priority, $script); } else { &gst_service_sysv_add_link ($i, "K", 100 - $priority, $script); } } } } sub gst_service_sysv_set_services { my ($services, $runlevel) = @_; foreach $i (@$services) { &gst_service_sysv_set_service($i); } } sub gst_service_filerc_concat_runlevels { my (@runlevels) = @_; $str = join (",", sort (@runlevels)); return ($str) ? $str : "-"; } sub gst_service_filerc_set_service { my ($buff, $service) = @_; my (%hash, $priority, $line, $str); $arr = $$service{"runlevels"}[0]{"runlevel"}; foreach $i (@$arr) { $priority = 0 + $$i{"priority"}; $priority = 50 if ($priority == 0); #very rough guess if ($$i{"action"} eq "start") { $hash{$priority}{"start"} = [] if (!$hash{$priority}{"start"}); push @{$hash{$priority}{"start"}}, $$i{"name"}; } else { $hash{$priority}{"stop"} = [] if (!$hash{$priority}{"stop"}); push @{$hash{$priority}{"stop"}}, $$i{"name"}; } } foreach $priority (keys %hash) { $line = sprintf ("%0.2d", $priority) . "\t"; $line .= &gst_service_filerc_concat_runlevels (@{$hash{$priority}{"stop"}}) . "\t"; $line .= &gst_service_filerc_concat_runlevels (@{$hash{$priority}{"start"}}) . "\t"; $line .= "/etc/init.d/" . $$service{"script"} . "\n"; push @$buff, $line; } } # This is the function for storing the service settings from XML in file-rc sub gst_service_filerc_set_services { my ($services, $runlevel) = @_; my ($buff, $lineno, $line, $file); my ($rcd_path, $initd_path, $relative_path) = &gst_service_sysv_get_paths (); $file = "$gst_prefix/etc/runlevel.conf"; $buff = &gst_file_buffer_load ($file); &gst_file_buffer_join_lines ($buff); $lineno = 0; # We prepare the file for storing the configuration, save the initial comments # and delete the rest while ($$buff[$lineno] =~ /^#.*/) { $lineno++; } for ($i = $lineno; $i < scalar (@$buff); $i++) { $$buff[$i] =~ /.*\/etc\/init\.d\/(.*)/; # we need to keep the forbidden services and the services that only start in rcS.d if (!gst_service_list_service_is_forbidden ($1)) { delete $$buff[$i]; } } # Now we append the services foreach $service (@$services) { &gst_service_filerc_set_service ($buff, $service); } @$buff = sort @$buff; push @$buff, "\n"; &gst_file_buffer_clean ($buff); &gst_file_buffer_save ($buff, $file); } sub gst_service_bsd_set_services { my ($services, $runlevel) = @_; my ($script, $runlevels); foreach $service (@$services) { $script = $$service{"script"}; $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0]; $action = $$runlevels {"action"}; if ($action eq "start") { &gst_file_run ("chmod ugo+x $script"); } else { &gst_file_run ("chmod ugo-x $script"); } } } sub gst_service_gentoo_set_services { my ($services, $runlevel) = @_; my ($action); foreach $service (@$services) { $script = $$service{"script"}; $arr = $$service{"runlevels"}[0]{"runlevel"}; foreach $i (@$arr) { $action = $$i{"action"}; $rl = $$i{"name"}; if ( $action eq "start") { &gst_file_run ("rc-update add $script $rl"); } elsif ($action eq "stop") { &gst_file_run ("rc-update del $script $rl"); } } } } sub gst_service_rcng_set_status { my ($service, $action) = @_; my ($fd, $key, $res); my ($default_rcconf) = "/etc/defaults/rc.conf"; my ($rcconf) = "/etc/rc.conf"; if (&gst_file_exists ("/etc/rc.d/$service")) { $fd = &gst_file_run_pipe_read ("/etc/rc.d/$service rcvar"); while (<$fd>) { if (/^\$(.*)=.*$/) { # to avoid cluttering rc.conf with duplicated data, # we first look in the defaults/rc.conf for the key $key = $1; $res = &gst_parse_sh_bool ($default_rcconf, $key); if ($res == $action) { &gst_replace_sh ($rcconf, $key); } else { &gst_replace_sh_bool ($rcconf, $key, "YES", "NO", $action); } } } &gst_file_close ($fd); } elsif (&gst_file_exists ("/usr/local/etc/rc.d/$service.sh")) { if ($action) { gst_file_copy ("/usr/local/etc/rc.d/$service.sh.sample", "/usr/local/etc/rc.d/$service.sh"); } else { gst_file_remove ("/usr/local/etc/rc.d/$service.sh"); } } } sub gst_service_rcng_set_services { my ($services, $runlevel) = @_; my ($action, $runlevels, $script); foreach $service (@$services) { $script = $$service {"script"}; $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0]; $action = ($$runlevels {"action"} eq "start")? 1 : 0; &gst_service_rcng_set_status ($script, $action); } } sub gst_service_suse_set_services { my ($services, $runlevel) = @_; my ($action, $runlevels, $script, $rllist); foreach $service (@$services) { $script = $$service{"script"}; $runlevels = $$service{"runlevels"}[0]{"runlevel"}; $rllist = ""; &gst_file_run ("insserv -r $script"); foreach $rl (@$runlevels) { if ($$rl{"action"} eq "start") { $rllist .= $$rl{"name"} . ","; } } if ($rllist ne "") { $rllist =~ s/,$//; &gst_file_run ("insserv $script,start=$rllist"); } } } sub gst_service_archlinux_set_status { my ($script, $active) = @_; my $rcconf = '/etc/rc.conf'; open DATA, "$rcconf"; my @rcconflines = ; close (DATA); open DATAOUT, ">", "$rcconf"; if(($active) && (! -f "/var/run/daemons/$script")) { &gst_service_archlinux_run_script($script,"start"); } if((!$active) && ( -f "/var/run/daemons/$script")) { &gst_service_archlinux_run_script($script,"start"); } foreach my $line (@rcconflines) { if($line =~ /\DAEMONS=/) { if($line =~ m/$script/) { if(!$active) { $line =~ s/$script //; } } else { if($active) { $line =~ s/network/network $script/g; } } } print DATAOUT "$line"; } close (DATAOUT); } sub gst_service_archlinux_set_services { my ($services, $runlevel) = @_; my ($action, $runlevels, $script); foreach $service (@$services) { $script = $$service {"script"}; $runlevels = $$service{"runlevels"}[0]{"runlevel"}[0]; $action = ($$runlevels {"action"} eq "start")? 1 : 0; &gst_service_archlinux_set_status ($script, $action); } } sub gst_service_set_services { my ($services, $runlevel) = @_; $type = &gst_get_init_type (); &gst_service_sysv_set_services ($services, $runlevel) if ($type eq "sysv"); &gst_service_filerc_set_services ($services, $runlevel) if ($type eq "file-rc"); &gst_service_bsd_set_services ($services, $runlevel) if ($type eq "bsd"); &gst_service_gentoo_set_services ($services, $runlevel) if ($type eq "gentoo"); &gst_service_rcng_set_services ($services, $runlevel) if ($type eq "rcng"); &gst_service_suse_set_services ($services, $runlevel) if ($type eq "suse"); &gst_service_archlinux_set_services ($services, $runlevel) if ($type eq "archlinux"); } sub gst_service_set_conf { my ($hash) = @_; my ($services, $runlevel); return unless $hash; $services = $$hash{"services"}[0]{"service"}; return unless $services; $runlevel = $$hash{"runlevel"}; return unless $runlevel; &gst_service_set_services($services, $runlevel); } # stuff for checking whether service is running sub gst_service_debian_get_status { my ($service) = @_; my ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); my ($output, $pidfile); $output = `grep "\/var\/run\/.*\.pid" $initd_path\/$service`; if ($output =~ /.*(\/var\/run\/.*\.pid).*/ ) { $pidfile = $1; $pidval = `cat $pidfile`; return 0 if $pidval eq ""; $pid = `ps h $pidval`; if ($pid eq "") { return 0; } else { return 1; } } return undef; } sub gst_service_redhat_get_status { my ($service) = @_; my ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); if (-f "/var/lock/subsys/$service") { return 1; } return 0; } sub gst_service_gentoo_get_status { my ($service) = @_; $line = `/etc/init.d/$service status`; return 1 if ($line =~ /started/); return 0; } sub gst_service_rcng_get_status { my ($service) = @_; $line = gst_file_run_backtick ("/etc/rc.d/$service forcestatus"); return 1 if ($line =~ /pid [0-9]*/); # hacky as hell, we need to check services in /usr/local/etc/rc.d # and there's no standard way to check they're running return 1 if (-f "/var/run/$service.pid"); # we give up, the service isn't running return 0; } sub gst_service_archlinux_get_status { my ($service) = @_; return 1 if( -f "/var/run/daemons/$service"); return 0; } sub gst_service_suse_get_status { my ($service) = @_; $line = gst_file_run_backtick ("/etc/init.d/$service status"); return 1 if ($line =~ /running/); return 0; } # returns true if the service is already running sub gst_service_get_status { my ($service) = @_; my %dist_map = ( "debian-2.2" => \&gst_service_debian_get_status, "debian-3.0" => \&gst_service_debian_get_status, "debian-3.1" => \&gst_service_debian_get_status, "debian-4.0" => \&gst_service_debian_get_status, "debian-5.0" => \&gst_service_debian_get_status, "debian-6.0" => \&gst_service_debian_get_status, "debian-7.0" => \&gst_service_debian_get_status, "debian-8.0" => \&gst_service_debian_get_status, "debian-testing" => \&gst_service_debian_get_status, "ubuntu-5.04" => \&gst_service_debian_get_status, "ubuntu-5.10" => \&gst_service_debian_get_status, "ubuntu-6.06" => \&gst_service_debian_get_status, "ubuntu-6.10" => \&gst_service_debian_get_status, "ubuntu-7.04" => \&gst_service_debian_get_status, "ubuntu-7.10" => \&gst_service_debian_get_status, "ubuntu-8.04" => \&gst_service_debian_get_status, "ubuntu-8.10" => \&gst_service_debian_get_status, "ubuntu-9.04" => \&gst_service_debian_get_status, "ubuntu-9.10" => \&gst_service_debian_get_status, "ubuntu-10.04" => \&gst_service_debian_get_status, "ubuntu-10.10" => \&gst_service_debian_get_status, "ubuntu-11.04" => \&gst_service_debian_get_status, "ubuntu-11.10" => \&gst_service_debian_get_status, "ubuntu-12.04" => \&gst_service_debian_get_status, "ubuntu-12.10" => \&gst_service_debian_get_status, "ubuntu-13.04" => \&gst_service_debian_get_status, "ubuntu-13.10" => \&gst_service_debian_get_status, "ubuntu-14.04" => \&gst_service_debian_get_status, "ubuntu-14.10" => \&gst_service_debian_get_status, "ubuntu-15.04" => \&gst_service_debian_get_status, "redhat-5.2" => \&gst_service_redhat_get_status, "redhat-6.0" => \&gst_service_redhat_get_status, "redhat-6.1" => \&gst_service_redhat_get_status, "redhat-6.2" => \&gst_service_redhat_get_status, "redhat-7.0" => \&gst_service_redhat_get_status, "redhat-7.1" => \&gst_service_redhat_get_status, "redhat-7.2" => \&gst_service_redhat_get_status, "redhat-7.3" => \&gst_service_redhat_get_status, "redhat-8.0" => \&gst_service_redhat_get_status, "redhat-9" => \&gst_service_redhat_get_status, "rhel-5" => \&gst_service_redhat_get_status, "rhel-6" => \&gst_service_redhat_get_status, "rhel-7" => \&gst_service_redhat_get_status, "mandrake-7.2" => \&gst_service_redhat_get_status, "fedora-1" => \&gst_service_redhat_get_status, "fedora-2" => \&gst_service_redhat_get_status, "fedora-3" => \&gst_service_redhat_get_status, "fedora-4" => \&gst_service_redhat_get_status, "fedora-5" => \&gst_service_redhat_get_status, "fedora-15" => \&gst_service_redhat_get_status, "fedora-16" => \&gst_service_redhat_get_status, "fedora-17" => \&gst_service_redhat_get_status, "fedora-18" => \&gst_service_redhat_get_status, "fedora-19" => \&gst_service_redhat_get_status, "fedora-20" => \&gst_service_redhat_get_status, "fedora-21" => \&gst_service_redhat_get_status, "rpath" => \&gst_service_redhat_get_status, "suse-9.0" => \&gst_service_suse_get_status, "suse-9.1" => \&gst_service_suse_get_status, "suse-10.0" => \&gst_service_suse_get_status, "suse-10.1" => \&gst_service_suse_get_status, "suse-10.2" => \&gst_service_suse_get_status, "suse-10.3" => \&gst_service_suse_get_status, "suse-10.4" => \&gst_service_suse_get_status, "suse-11.0" => \&gst_service_suse_get_status, "suse-11.1" => \&gst_service_suse_get_status, "suse-11.2" => \&gst_service_suse_get_status, "suse-11.3" => \&gst_service_suse_get_status, "archlinux" => \&gst_service_archlinux_get_status, "gentoo" => \&gst_service_gentoo_get_status, "vlos-1.2" => \&gst_service_gentoo_get_status, "freebsd-5" => \&gst_service_rcng_get_status, "freebsd-6" => \&gst_service_rcng_get_status, "freebsd-7" => \&gst_service_rcng_get_status, "freebsd-8" => \&gst_service_rcng_get_status, "freebsd-9" => \&gst_service_rcng_get_status, "freebsd-10" => \&gst_service_rcng_get_status, ); my $proc; $proc = $dist_map {$gst_dist}; return undef if ($proc eq undef); return &$proc ($service); } # Functions to run a service sub gst_service_sysv_run_initd_script { my ($service, $arg) = @_; my ($rc_path, $initd_path); my $str; my %map = ("restart" => "restarted", "stop" => "stopped", "start" => "started"); &gst_report_enter (); if (!exists $map{$arg}) { &gst_report ("service_sysv_op_unk", $arg); &gst_report_leave (); return -1; } $str = $map{$arg}; ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); if (-f "$initd_path/$service") { if (!&gst_file_run ("$initd_path/$service $arg")) { &gst_report ("service_sysv_op_success", $service, $str); &gst_report_leave (); return 0; } } &gst_report ("service_sysv_op_failed", $service, $str); &gst_report_leave (); return -1; } sub gst_service_bsd_run_script { my ($service, $arg) = @_; my ($chmod) = 0; return if (!&gst_file_exists ($service)); # if it's not executable then chmod it if (!((stat ($service))[2] & (S_IXUSR || S_IXGRP || S_IXOTH))) { $chmod = 1; &gst_file_run ("chmod ugo+x $service"); } &gst_file_run ("$service $arg"); # return it to it's normal state if ($chmod) { &gst_file_run ("chmod ugo-x $service"); } } sub gst_service_gentoo_run_script { my ($service, $arg) = @_; my ($option); my %map = ("stop" => "stopped", "start" => "started" ); &gst_report_enter (); if (!exists $map{$arg}) { &gst_report ("service_sysv_op_unk", $arg); &gst_report_leave (); return -1; } if (&gst_service_gentoo_service_exist ($service)) { if (!&gst_file_run ("/etc/init.d/$service $arg")) { &gst_report ("service_sysv_op_success", $service, $str); &gst_report_leave (); return 0; } } &gst_report ("service_sysv_op_failed", $service, $str); &gst_report_leave (); return -1; } sub gst_service_rcng_run_script { my ($service, $arg) = @_; my ($farg); my %map = ("stop" => "forcestop", "start" => "forcestart" ); &gst_report_enter (); if (!exists $map{$arg}) { &gst_report ("service_sysv_op_unk", $arg); &gst_report_leave (); return -1; } $farg = $map {$arg}; if (!&gst_file_run ("/etc/rc.d/$service $farg")) { &gst_report ("service_sysv_op_success", $service, $str); &gst_report_leave (); return 0; } &gst_report ("service_sysv_op_failed", $service, $str); &gst_report_leave (); return -1; } sub gst_service_archlinux_run_script { my ($service, $arg) = @_; my ($farg); my %map = ("stop" => "stop", "start" => "start" ); &gst_report_enter (); if (!exists $map{$arg}) { &gst_report ("service_sysv_op_unk", $arg); &gst_report_leave (); return -1; } $farg = $map {$arg}; if (!&gst_file_run ("/etc/rc.d/$service $farg")) { &gst_report ("service_sysv_op_success", $service, $str); &gst_report_leave (); return 0; } &gst_report ("service_sysv_op_failed", $service, $str); &gst_report_leave (); return -1; } sub gst_service_run_script { my ($service, $arg) = @_; my ($proc, $type); my %map = ( "file-rc" => \&gst_service_sysv_run_initd_script, "sysv" => \&gst_service_sysv_run_initd_script, "bsd" => \&gst_service_bsd_run_script, "gentoo" => \&gst_service_gentoo_run_script, "rcng" => \&gst_service_rcng_run_script, "suse" => \&gst_service_sysv_run_initd_script, "archlinux" => \&gst_service_archlinux_run_script, ); $type = &gst_get_init_type (); $proc = $map {$type}; &$proc ($service, $arg); } # functions to know if a service will be installed sub gst_service_sysv_installed { my ($service) = @_; my ($res, $rcd_path, $initd_path); &gst_report_enter (); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); $res = 1; if (! -f "$initd_path/$service") { $res = 0; &gst_report ("service_sysv_not_found", $service); } &gst_report_leave (); return $res; } sub gst_service_bsd_installed { my ($service) = @_; return 1 if ( -f "$service"); return 0; } sub gst_service_gentoo_installed { my ($service) = @_; return 1 if ( -f "/etc/init.d/$service"); return 0; } sub gst_service_rcng_installed { my ($service) = @_; return 1 if ( -f "/etc/rc.d/$service"); return 1 if ( -f "/usr/local/etc/rc.d/$service.sh.sample"); return 0; } sub gst_service_installed { my ($service) = @_; my ($type); $type = &gst_get_init_type (); return &gst_service_sysv_installed ($service) if (($type eq "sysv") || ($type eq "file-rc") || ($type eq "suse")); return &gst_service_bsd_installed ($service) if ($type eq "bsd"); return &gst_service_gentoo_installed ($service) if ($type eq "gentoo"); return &gst_service_rcng_installed ($service) if ($type eq "rcng"); return &gst_service_rcng_installed ($service) if ($type eq "archlinux"); return 0; } sub gst_service_list_any_installed { my @service = @_; my $res; $res = 0; foreach $serv (@service) { if (gst_service_installed ($serv)) { $res = 1; } } return $res; } sub gst_service_bsd_set_status { my ($script, $active) = @_; my (@arr); if ($active) { &gst_file_run ("chmod ugo+x $script"); &gst_service_run_script ($script, "start"); } else { &gst_service_run_script ($script, "stop"); &gst_file_run ("chmod ugo-x $script"); } } sub gst_service_gentoo_set_status { my ($script, $force_now, $active) = @_; my (@arr); if ($active) { &gst_file_run ("rc-update add $script default"); &gst_file_run ("/etc/init.d/$script start") if ($force_now == 1); } else { &gst_file_run ("rc-update del $script default"); &gst_file_run ("/etc/init.d/$script stop") if ($force_now == 1); } } sub gst_service_suse_set_status { my ($script, $active) = @_; my (@runlevels, $rllist); my ($rcd_path, $initd_path); my ($rl); ($rcd_path, $initd_path) = &gst_service_sysv_get_paths (); @runlevels = &gst_service_sysv_get_runlevels (); if ($active) { $rllist = join ",", @runlevels; &gst_file_run ("insserv $script,start=$rllist"); &gst_service_run_script ($script, "start"); } else { # to remove a service from a few runlevels we need to run # insserv -r and then insserv blah,start=x,y,z foreach $link (<$rcd_path/rc[0-9S].d/S[0-9][0-9]$script>) { $link =~ s/$rcd_path\///; $link =~ /rc([0-9S])\.d\/S[0-9][0-9].*/; $rllist .= "$1,"; } foreach $link (<$rcd_path/boot.d/S[0-9][0-9]$service>) { $rllist .= "B,"; } # remove the default runlevels from the list foreach $runlevel (@runlevels) { $rllist =~ s/$runlevel,//; } $rllist =~ s/,$//; &gst_file_run ("insserv -r $script"); if ($rllist ne "") { &gst_file_run ("insserv $script,start=$rllist"); } &gst_service_run_script ($script, "stop"); } }