#!/usr/bin/env perl #-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- # Functions for manipulating system services, like daemons and network. # # Copyright (C) 2000-2001 Ximian, Inc. # # Authors: 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. require "___scriptsdir___/file.pl"; require "___scriptsdir___/report.pl"; # --- Service/daemon utilities --- # # Portable SysV rc script and service manipulation. # The only subs you should be interested in are # xst_service_sysv_restart, # xst_service_sysv_get_status and # xst_service_sysv_set_status. # All the other stuff is low-level action. # Where is the SysV subsystem installed? sub xst_service_sysv_get_paths { my %dist_map = ( "redhat-6.0" => ["/etc/rc.d/", "/etc/rc.d/init.d"], "redhat-6.1" => ["/etc/rc.d/", "/etc/rc.d/init.d"], "redhat-6.2" => ["/etc/rc.d/", "/etc/rc.d/init.d"], "redhat-7.0" => ["/etc/rc.d/", "/etc/rc.d/init.d"] ); return @{$dist_map{$xst_dist}}; } # Those runlevels that are usually used. Maybe we should add # the current running runlevel, using the "runlevel" command. sub xst_service_sysv_get_runlevels { my %dist_map = ( "redhat-6.0" => [3, 5], "redhat-6.1" => [3, 5], "redhat-6.2" => [3, 5], "redhat-7.0" => [3, 5] ); return @{$dist_map{$xst_dist}}; } # 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 xst_service_sysv_get_status { my ($service) = @_; my ($rc_path, $initd_path, $res); &xst_report_enter (); ($rcd_path, $initd_path) = &xst_service_sysv_get_paths (); $res = 0; if (-f "$initd_path/$service") { $res = !&xst_file_run ("$initd_path/$service status"); &xst_report ("service_status_running", $service) if $res; &xst_report ("service_status_stopped", $service) if !$res; } else { &xst_report ("service_sysv_not_found", $service); } &xst_report_leave (); return $res; } # Setup a link, at the designated runlevel, for the defined # service. $pre is something like "S01" or "K99". sub xst_service_sysv_add_link { my ($runlevel, $pre, $service) = @_; my ($rcd_path, $initd_path); ($rcd_path, $initd_path) = &xst_service_sysv_get_paths (); symlink ("$initd_path/$service", "$rcd_path/rc$runlevel.d/$pre$service"); &xst_report_enter (); &xst_report ("service_sysv_add_link", "$rcd_path/rc$runlevel.d/$pre$service"); &xst_report_leave (); } # Remove any links matching re at the given runlevel. sub xst_service_sysv_remove_link { my ($runlevel, $re) = @_; local *RC_DIR; my $link; my $dir; my ($rcd_path, $initd_path); &xst_report_enter (); ($rcd_path, $initd_path) = &xst_service_sysv_get_paths (); $dir = "$xst_prefix/$rcd_path/rc$runlevel.d"; if (!(opendir RC_DIR, $dir)) { &xst_report ("service_sysv_no_runlevel", $runlevel, $dir); &xst_report_leave (); return; } foreach $link (readdir (RC_DIR)) { if ($link =~ /$re/) { &xst_report ("service_sysv_remove_link", "$dir/$link"); unlink ("$dir/$link"); } } &xst_report_leave (); } # 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 xst_service_sysv_set_links_active { my ($pri, $service) = @_; foreach $runlevel (&xst_service_sysv_get_runlevels ()) { &xst_service_sysv_remove_link ($runlevel, "K[0-9]+$service"); &xst_service_sysv_remove_link ($runlevel, "S[0-9]+$service"); &xst_service_sysv_add_link ($runlevel, "S$pri", $service); } } # Set stop links and remove start links at the usual runlevels. sub xst_service_sysv_set_links_inactive { my ($pri, $service) = @_; foreach $runlevel (&xst_service_sysv_get_runlevels ()) { &xst_service_sysv_remove_link ($runlevel, "S[0-9]+$service"); &xst_service_sysv_add_link ($runlevel, "K$pri", $service); } } # Set links for active/inactive service at the given priority. sub xst_service_sysv_set_links { my ($pri, $service, $active) = @_; if ($active) { &xst_service_sysv_set_links_active ($pri, $service); } else { &xst_service_sysv_set_links_inactive (100 - $pri, $service); } } # Run the init.d script for the corresponding service, with # arg, which can be "stop", "start" or "restart". sub xst_service_sysv_run_initd_script { my ($service, $arg) = @_; my ($rc_path, $initd_path); my $str; my %map = ("restart" => "restarted", "stop" => "stopped", "start" => "started"); &xst_report_enter (); if (!exists $map{$arg}) { &xst_report ("service_sysv_op_unk", $arg); &xst_report_leave (); return -1; } $str = $map{$arg}; ($rcd_path, $initd_path) = &xst_service_sysv_get_paths (); if (-f "$initd_path/$service") { if (!&xst_file_run ("$init_path/$service $arg")) { &xst_report ("service_sysv_op_success", $service, $str); &xst_report_leave (); return 0; } } &xst_report ("service_sysv_op_failed", $service, $str); &xst_report_leave (); return -1; } sub xst_service_sysv_restart { my ($pri, $service); &xst_service_sysv_set_links ($pri, $service, 1); &xst_service_sysv_run_initd_script ($service, "restart"); } # Start or stop the service, depending on $active. Set # links accordingly. sub xst_service_sysv_set_status { my ($pri, $service, $active) = @_; $status = &xst_service_sysv_get_status ($service); &xst_service_sysv_set_links ($pri, $service, $active) if ($status != $active); if ($status) { # if it's already active and you want it active, restart. $arg = $active? "restart" : "stop"; } else { # normal operation. $arg = $active? "start" : "stop"; } return &xst_service_sysv_run_initd_script ($service, $arg); } 1;