Blame local/fixproc

Packit fcad23
#!/usr/bin/perl
Packit fcad23
# 
Packit fcad23
# fixproc [-min n] [-max n] [-check | -kill | -restart | -exist | -fix] proc ...
Packit fcad23
# 
Packit fcad23
# fixproc exit code:
Packit fcad23
# 	0	ok
Packit fcad23
# 	1	check failed
Packit fcad23
# 	2	cannot restart
Packit fcad23
# 	3	cannot kill
Packit fcad23
# 	4	fix failed	if fix is defined as kill or restart, then
Packit fcad23
# 				cannot kill or cannot restart is return instead
Packit fcad23
# 	10	fixproc error
Packit fcad23
# 
Packit fcad23
#
Packit fcad23
# Fixes a process named "proc" by performing the specified action.  The
Packit fcad23
# actions can be check, kill, restart, exist, or fix.  The action is specified
Packit fcad23
# on the command line or is read from a default database, which describes
Packit fcad23
# the default action to take for each process.  The database format and
Packit fcad23
# the meaning of each action are described below.
Packit fcad23
# 
Packit fcad23
# database format
Packit fcad23
# ---------------
Packit fcad23
# 
Packit fcad23
# name	foo			required
Packit fcad23
# cmd	/a/b/name args		required
Packit fcad23
# min	number			optional, defaults to 1
Packit fcad23
# max	number			optional, defaults to 1
Packit fcad23
# 
Packit fcad23
# check	{null, exist, shell}	optional, defaults to exist if not defined
Packit fcad23
# [shell command		shell commands needed only if check=shell
Packit fcad23
#  ...
Packit fcad23
#  shell command
Packit fcad23
#  end_shell]			keyword end_shell marks end of shell commands
Packit fcad23
# fix	{kill, restart, shell}	required
Packit fcad23
# [shell command			shell commands needed only if fix=shell
Packit fcad23
#  ...
Packit fcad23
#  shell command
Packit fcad23
#  end_shell]			keyword end_shell marks end of shell commands
Packit fcad23
# 
Packit fcad23
# Blank lines and lines beginning with "#" are ignored.
Packit fcad23
# 
Packit fcad23
#
Packit fcad23
# Example:
Packit fcad23
# 
Packit fcad23
# name	test1
Packit fcad23
# cmd	nice /home/kong/z/test1 > /dev/null &
Packit fcad23
# max	2
Packit fcad23
# fix	shell
Packit fcad23
# 	xterm&
Packit fcad23
# 	nice /home/kong/z/test1 > /dev/null &
Packit fcad23
# 	end_shell
Packit fcad23
# 
Packit fcad23
# 
Packit fcad23
# actions
Packit fcad23
# -------
Packit fcad23
# There are 5 possible actions:  kill, restart, fix, exist, check.  Fix is
Packit fcad23
# defined to be the kill action, the restart action, or a series of shell
Packit fcad23
# commands.  Check is optionally defined in the database.  If check is not
Packit fcad23
# defined, it defaults to exist.
Packit fcad23
# 
Packit fcad23
# If the action is specified on the cmd line, it is executed regardless of
Packit fcad23
# check.  The commands executed for each action type is as follow:
Packit fcad23
# 
Packit fcad23
#   switch action:
Packit fcad23
# 	kill:
Packit fcad23
# 	  kill process, wait 5 seconds, kill -9 if still exist
Packit fcad23
# 	  if still exist
Packit fcad23
# 	    return "cannot kill"
Packit fcad23
# 	  else
Packit fcad23
# 	    return "ok"
Packit fcad23
# 
Packit fcad23
# 	restart:	
Packit fcad23
# 	  execute kill
Packit fcad23
# 	  if kill returned "cannot kill"
Packit fcad23
# 	    return "cannot kill"
Packit fcad23
# 	  restart by issuing cmd to shell
Packit fcad23
# 	  if check defined
Packit fcad23
# 	    execute check
Packit fcad23
# 	    if check succeeds
Packit fcad23
# 	      return "ok"
Packit fcad23
# 	    else
Packit fcad23
# 	      return "cannot restart"
Packit fcad23
# 
Packit fcad23
# 	fix:
Packit fcad23
# 	  if fix=kill
Packit fcad23
# 	    execute kill
Packit fcad23
# 	  else if fix=restart
Packit fcad23
# 	    execute restart
Packit fcad23
# 	  else
Packit fcad23
# 	    execute shell commands
Packit fcad23
# 	    execute check
Packit fcad23
# 
Packit fcad23
# 	check:
Packit fcad23
# 	  if check defined as null
Packit fcad23
# 	    return "fixproc error"
Packit fcad23
# 	  else
Packit fcad23
# 	    execute check
Packit fcad23
# 	    if check succeeds
Packit fcad23
# 	      return (execute exist)
Packit fcad23
# 	    return "check failed"
Packit fcad23
# 
Packit fcad23
# 	exist:
Packit fcad23
# 	  if proc exists in ps && (min <= num. of processes <= max)
Packit fcad23
# 	    return "ok"
Packit fcad23
# 	  else
Packit fcad23
# 	    return "check failed"
Packit fcad23
# 
Packit fcad23
# 
Packit fcad23
# If the action is not specified on the cmd line, the default action is the
Packit fcad23
# fix action defined in the database.  Fix is only executed if check fails:
Packit fcad23
# 
Packit fcad23
# 	if fix defined
Packit fcad23
# 	  if check is not defined as null
Packit fcad23
# 	    execute check
Packit fcad23
# 	    if check succeeds
Packit fcad23
# 	      return "ok"
Packit fcad23
# 	  execute action defined for fix  
Packit fcad23
# 	else
Packit fcad23
# 	  return "fixproc error"
Packit fcad23
# 
Packit fcad23
# 
Packit fcad23
# If proc is not specified on the command line, return "fixproc error." 
Packit fcad23
# Multiple proc's can be defined on the cmd line.   When an error occurs
Packit fcad23
# when multiple proc's are specified, the first error encountered halts the
Packit fcad23
# script.
Packit fcad23
# 
Packit fcad23
# For check shell scripts, any non-zero exit code means the check has failed.
Packit fcad23
#
Packit fcad23
#
Packit fcad23
# Timothy Kong		3/1995
Packit fcad23
Packit fcad23
use File::Temp qw(tempfile);
Packit fcad23
Packit fcad23
$database_file = '/local/etc/fixproc.conf';
Packit fcad23
Packit fcad23
$debug = 0;			# specify debug level using -dN
Packit fcad23
				# currently defined: -d1
Packit fcad23
Packit fcad23
$no_error = 0;
Packit fcad23
$check_failed_error = 1;
Packit fcad23
$cannot_restart_error = 2;
Packit fcad23
$cannot_kill_error = 3;
Packit fcad23
$cannot_fix_error = 4;
Packit fcad23
$fixproc_error = 10;
Packit fcad23
Packit fcad23
$min = 1;
Packit fcad23
$max = 1;
Packit fcad23
$cmd_line_action = '';
Packit fcad23
%min = ();
Packit fcad23
%max = ();
Packit fcad23
%cmd = ();
Packit fcad23
%check = ();
Packit fcad23
%fix = ();
Packit fcad23
$shell_lines = ();
Packit fcad23
@proc_list = ();
Packit fcad23
Packit fcad23
$shell_header = "#!/bin/sh\n";
Packit fcad23
$shell_end_marker = 'shell_end_marker';
Packit fcad23
Packit fcad23
&read_args();
Packit fcad23
&read_database();
Packit fcad23
# &dump_database();		# debug only
Packit fcad23
Packit fcad23
# change the default min. and max. number of processes allowed
Packit fcad23
if ($min != 1)
Packit fcad23
  {
Packit fcad23
    for $name ( keys (%min) )
Packit fcad23
      {
Packit fcad23
	$min{$name} = $min;
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
if ($max != 1)
Packit fcad23
  {
Packit fcad23
    for $name ( keys (%max) )
Packit fcad23
      {
Packit fcad23
	$max{$name} = $max;
Packit fcad23
      }
Packit fcad23
  }
Packit fcad23
    
Packit fcad23
# work on one process at a time
Packit fcad23
for $proc ( @proc_list )
Packit fcad23
  {
Packit fcad23
    $error_code = &work_on_proc ($proc);
Packit fcad23
Packit fcad23
############# uncomment next line when fully working ############
Packit fcad23
#    exit $error_code if ($error_code);
Packit fcad23
Packit fcad23
    die "error_code = $error_code\n" if ($error_code);
Packit fcad23
  }
Packit fcad23
Packit fcad23
Packit fcad23
# create an executable shell script file
Packit fcad23
sub create_sh_script
Packit fcad23
{
Packit fcad23
  local ($file) = pop (@_);
Packit fcad23
  local ($fh) = pop (@_);
Packit fcad23
  local ($i) = pop (@_);
Packit fcad23
Packit fcad23
  printf (STDERR "create_sh_script\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  while ( $shell_lines[$i] ne $shell_end_marker )
Packit fcad23
    {
Packit fcad23
      printf ($fh "%s", $shell_lines[$i]);
Packit fcad23
      $i++;
Packit fcad23
    }
Packit fcad23
  close ($fh);
Packit fcad23
  chmod 0755, $file;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub do_fix
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
Packit fcad23
  printf (STDERR "do_fix\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  if ($fix{$proc} eq '')
Packit fcad23
    {
Packit fcad23
      $! = $fixproc_error;
Packit fcad23
      die "$0: internal error 4\n";
Packit fcad23
    }
Packit fcad23
  if ($fix{$proc} eq 'kill')
Packit fcad23
    {
Packit fcad23
      return &do_kill ($proc);
Packit fcad23
    }
Packit fcad23
  elsif ($fix{$proc} eq 'restart')
Packit fcad23
    {
Packit fcad23
      return &do_restart ($proc);
Packit fcad23
    }
Packit fcad23
  else
Packit fcad23
    {
Packit fcad23
      # it must be "shell", so execute the shell script defined in database
Packit fcad23
      local ($tmpfh, $tmpfile) = tempfile("fix_XXXXXXXX", DIR => "/tmp");
Packit fcad23
Packit fcad23
      &create_sh_script ($fix{$proc}, $tmpfh, $tmpfile);
Packit fcad23
Packit fcad23
      	# return code is number divided by 256
Packit fcad23
      $error_code = (system "$tmpfile") / 256;
Packit fcad23
      unlink($tmpfile);
Packit fcad23
      return ($fix_failed_error) if ($error_code != 0);
Packit fcad23
        # sleep needed here?
Packit fcad23
      return &do_exist ($proc);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub do_check
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
Packit fcad23
  printf (STDERR "do_check\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  if ($check{$proc} eq '')
Packit fcad23
    {
Packit fcad23
      $! = $fixproc_error;
Packit fcad23
      die "$0: internal error 2\n";
Packit fcad23
    }
Packit fcad23
Packit fcad23
  if ($check{$proc} ne 'exist')
Packit fcad23
    {
Packit fcad23
      # if not "exist", then it must be "shell", so execute the shell script
Packit fcad23
      # defined in database
Packit fcad23
Packit fcad23
      local ($tmpfh, $tmpfile) = tempfile("check_XXXXXXXX", DIR => "/tmp");
Packit fcad23
Packit fcad23
      &create_sh_script ($fix{$proc}, $tmpfh, $tmpfile);
Packit fcad23
Packit fcad23
      	# return code is number divided by 256
Packit fcad23
      $error_code = (system "$tmpfile") / 256;
Packit fcad23
      unlink($tmpfile);
Packit fcad23
      return ($check_failed_error) if ($error_code != 0);
Packit fcad23
Packit fcad23
      # check passed, continue
Packit fcad23
    }
Packit fcad23
  return &do_exist ($proc);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub do_exist
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
Packit fcad23
  printf (STDERR "do_exist\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  # do ps, check to see if min <= no. of processes <= max
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  open (COMMAND, "/bin/ps -e | /bin/grep $proc | /bin/wc -l |")
Packit fcad23
    || die "$0: can't run ps-grep-wc command\n";
Packit fcad23
  $proc_count = <COMMAND>;
Packit fcad23
  if (($proc_count < $min{$proc}) || ($proc_count > $max{$proc}))
Packit fcad23
    {
Packit fcad23
      return $check_failed_error;
Packit fcad23
    }
Packit fcad23
  return $no_error;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub do_kill
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
  local ($second_kill_needed);
Packit fcad23
Packit fcad23
  printf (STDERR "do_kill\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  # first try kill
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  open (COMMAND, "/bin/ps -e | /bin/grep $proc |")
Packit fcad23
    || die "$0: can't run ps-grep-awk command\n";
Packit fcad23
  while (<COMMAND>)
Packit fcad23
    {
Packit fcad23
      # match the first field of ps -e
Packit fcad23
      $! = $fixproc_error;
Packit fcad23
      /^\s*(\d+)\s/ || die "$0: can't match ps -e output\n";
Packit fcad23
      system "kill $1";
Packit fcad23
    }
Packit fcad23
Packit fcad23
  # if process still exist, try kill -9
Packit fcad23
  sleep 2;
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  open (COMMAND, "/bin/ps -e | /bin/grep $proc |")
Packit fcad23
    || die "$0: can't run ps-grep-awk command\n";
Packit fcad23
  $second_kill_needed = 0;
Packit fcad23
  while (<COMMAND>)
Packit fcad23
    {
Packit fcad23
      # match the first field of ps -e
Packit fcad23
      $! = $fixproc_error;
Packit fcad23
      /^\s*(\d+)\s/ || die "$0: can't match ps -e output\n";
Packit fcad23
      system "kill -9 $1";
Packit fcad23
      $second_kill_needed = 1;
Packit fcad23
    }
Packit fcad23
  return ($no_error) if ($second_kill_needed == 0);
Packit fcad23
Packit fcad23
  # see if kill -9 worked
Packit fcad23
  sleep 2;
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  open (COMMAND, "/bin/ps -e | /bin/grep $proc |")
Packit fcad23
    || die "$0: can't run ps-grep-awk command\n";
Packit fcad23
  while (<COMMAND>)
Packit fcad23
    {				# a process still exist, return error
Packit fcad23
      return $cannot_kill_error;
Packit fcad23
    }
Packit fcad23
  return $no_error;		# good, all dead
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub do_restart
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
  local ($error_code);
Packit fcad23
Packit fcad23
  printf (STDERR "do_restart\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  $error_code = &do_kill ($proc);
Packit fcad23
  return $error_code if ($error_code != $no_error);
Packit fcad23
  die "$0: internal error 3\n" if ($cmd{$proc} eq '');
Packit fcad23
  system "$cmd{$proc}";
Packit fcad23
  # sleep needed here?
Packit fcad23
  if ($check{$proc} ne 'null')
Packit fcad23
    {
Packit fcad23
      return $no_error if (&do_check($proc) == $no_error);
Packit fcad23
      return $cannot_restart_error;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub work_on_proc
Packit fcad23
{
Packit fcad23
  local ($proc) = pop(@_);
Packit fcad23
  local ($error_code);
Packit fcad23
Packit fcad23
  printf (STDERR "work_on_proc\n") if ($debug > 0);
Packit fcad23
Packit fcad23
  if ($cmd_line_action eq '')
Packit fcad23
    {
Packit fcad23
      # perform action from database
Packit fcad23
Packit fcad23
      if ($check{$proc} ne 'null')
Packit fcad23
	{
Packit fcad23
	  $error_code = &do_check ($proc);
Packit fcad23
	  if ($error_code != $check_failed_error)
Packit fcad23
	    {
Packit fcad23
	      return $error_code;
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      return &do_fix ($proc);
Packit fcad23
    }
Packit fcad23
  else
Packit fcad23
    {
Packit fcad23
      # perform action from command line
Packit fcad23
Packit fcad23
      $error_code = $no_error;
Packit fcad23
      if ($cmd_line_action eq 'kill')
Packit fcad23
	{
Packit fcad23
	  $error_code = &do_kill ($proc);
Packit fcad23
	}
Packit fcad23
      elsif ($cmd_line_action eq 'restart')
Packit fcad23
	{
Packit fcad23
	  $error_code = &do_restart ($proc);
Packit fcad23
	}
Packit fcad23
      elsif ($cmd_line_action eq 'fix')
Packit fcad23
	{
Packit fcad23
	  $error_code = &do_fix ($proc);
Packit fcad23
	}
Packit fcad23
      elsif ($cmd_line_action eq 'check')
Packit fcad23
	{
Packit fcad23
	  if ( $check{$proc} eq 'null' )
Packit fcad23
	    {
Packit fcad23
	      exit $fixproc_error;
Packit fcad23
	    }
Packit fcad23
	  $error_code = &do_check ($proc);
Packit fcad23
	}
Packit fcad23
      elsif ($cmd_line_action eq 'exist')
Packit fcad23
	{
Packit fcad23
	  $error_code = &do_exist ($proc);
Packit fcad23
	}
Packit fcad23
      else
Packit fcad23
	{
Packit fcad23
	  $! = $fixproc_error;
Packit fcad23
	  die "$0: internal error 1\n";
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub dump_database
Packit fcad23
{
Packit fcad23
  local ($name);
Packit fcad23
Packit fcad23
  for $name (keys(%cmd))
Packit fcad23
    {
Packit fcad23
      printf ("name\t%s\n", $name);
Packit fcad23
      printf ("cmd\t%s\n", $cmd{$name});
Packit fcad23
      printf ("min\t%s\n", $min{$name});
Packit fcad23
      printf ("max\t%s\n", $max{$name});
Packit fcad23
      if ( $check{$name} =~ /[0-9]+/ )
Packit fcad23
	{
Packit fcad23
	  printf ("check\tshell\n");
Packit fcad23
	  $i = $check{$name};
Packit fcad23
	  while ( $shell_lines[$i] ne $shell_end_marker )
Packit fcad23
	    {
Packit fcad23
	      printf ("%s", $shell_lines[$i]);
Packit fcad23
	      $i++;
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      else
Packit fcad23
	{
Packit fcad23
	  printf ("check\t%s\n", $check{$name});
Packit fcad23
	}
Packit fcad23
      if ( $fix{$name} =~ /[0-9]+/ )
Packit fcad23
	{
Packit fcad23
	  printf ("fix\tshell\n");
Packit fcad23
	  $i = $fix{$name};
Packit fcad23
	  while ( $shell_lines[$i] ne $shell_end_marker )
Packit fcad23
	    {
Packit fcad23
	      printf ("%s", $shell_lines[$i]);
Packit fcad23
	      $i++;
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      else
Packit fcad23
	{
Packit fcad23
	  printf ("fix\t%s\n", $fix{$name});
Packit fcad23
	}
Packit fcad23
      printf ("\n");
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub read_database
Packit fcad23
{
Packit fcad23
  local ($in_check_shell_lines) = 0;
Packit fcad23
  local ($in_fix_shell_lines) = 0;
Packit fcad23
  local ($name) = '';
Packit fcad23
  local ($str1);
Packit fcad23
  local ($str2);
Packit fcad23
Packit fcad23
  $! = $fixproc_error;
Packit fcad23
  open (DB, $database_file) || die 'cannot open database file $database_file\n';
Packit fcad23
  while (<DB>)
Packit fcad23
    {
Packit fcad23
      if ((! /\S/) || (/^[ \t]*#.*$/))
Packit fcad23
	{
Packit fcad23
		# ignore blank lines or lines beginning with "#"
Packit fcad23
	}
Packit fcad23
      elsif ($in_check_shell_lines)
Packit fcad23
	{
Packit fcad23
	  if ( /^\s*end_shell\s*$/ )
Packit fcad23
	    {
Packit fcad23
	      $in_check_shell_lines = 0;
Packit fcad23
	      push (@shell_lines, $shell_end_marker);
Packit fcad23
	    }
Packit fcad23
	  else
Packit fcad23
	    {
Packit fcad23
	      push (@shell_lines, $_);
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      elsif ($in_fix_shell_lines)
Packit fcad23
	{
Packit fcad23
	  if ( /^\s*end_shell\s*$/ )
Packit fcad23
	    {
Packit fcad23
	      $in_fix_shell_lines = 0;
Packit fcad23
	      push (@shell_lines, $shell_end_marker);
Packit fcad23
	    }
Packit fcad23
	  else
Packit fcad23
	    {
Packit fcad23
	      push (@shell_lines, $_);
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
      else
Packit fcad23
	{
Packit fcad23
	  if ( ! /^\s*(\S+)\s+(\S.*)\s*$/ )
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: syntax error in database\n$_";
Packit fcad23
	    }
Packit fcad23
	  $str1 = $1;
Packit fcad23
	  $str2 = $2;
Packit fcad23
	  if ($str1 eq 'name')
Packit fcad23
	    {
Packit fcad23
	      &finish_db_entry($name);
Packit fcad23
	      $name = $str2;
Packit fcad23
	    }
Packit fcad23
	  elsif ($str1 eq 'cmd')
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: cmd specified before name in database\n$_\n"
Packit fcad23
	        if ($name eq '');
Packit fcad23
	      die "$0: cmd specified multiple times for $name in database\n"
Packit fcad23
		if ($cmd{$name} ne '');
Packit fcad23
	      $cmd{$name} = $str2;
Packit fcad23
	    }
Packit fcad23
	  elsif ($str1 eq 'min')
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: min specified before name in database\n$_\n"
Packit fcad23
	        if ($name eq '');
Packit fcad23
	      die "$0: min specified multiple times in database\n$_\n"
Packit fcad23
		if ($min{$name} ne '');
Packit fcad23
	      die "$0: non-numeric min value in database\n$_\n"
Packit fcad23
		if ( ! ($str2 =~ /[0-9]+/ ));
Packit fcad23
	      $min{$name} = $str2;
Packit fcad23
	    }
Packit fcad23
	  elsif ($str1 eq 'max')
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: max specified before name in database\n$_\n"
Packit fcad23
	        if ($name eq '');
Packit fcad23
	      die "$0: max specified multiple times in database\n$_\n"
Packit fcad23
		if ($max{$name} ne '');
Packit fcad23
	      die "$0: non-numeric max value in database\n$_\n"
Packit fcad23
		if ( ! ($str2 =~ /[0-9]+/ ));
Packit fcad23
	      $max{$name} = $str2;
Packit fcad23
	    }
Packit fcad23
	  elsif ($str1 eq 'check')
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: check specified before name in database\n$_\n"
Packit fcad23
	        if ($name eq '');
Packit fcad23
	      die "$0: check specified multiple times in database\n$_\n"
Packit fcad23
		if ($check{$name} ne '');
Packit fcad23
	      if ( $str2 eq 'shell' )
Packit fcad23
		{
Packit fcad23
		  # if $check{$name} is a number, it is a pointer into
Packit fcad23
		  # $shell_lines[] where the shell commands are kept
Packit fcad23
		  $shell_lines[$#shell_lines+1] = $shell_header;
Packit fcad23
		  $check{$name} = $#shell_lines;
Packit fcad23
		  $in_check_shell_lines = 1;
Packit fcad23
		}
Packit fcad23
	      else
Packit fcad23
		{
Packit fcad23
		  $check{$name} = $str2;
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
	  elsif ($str1 eq 'fix')
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: fix specified before name in database\n$_\n"
Packit fcad23
	        if ($name eq '');
Packit fcad23
	      die "$0: fix specified multiple times in database\n$_\n"
Packit fcad23
		if ($fix{$name} ne '');
Packit fcad23
	      if ( $str2 eq 'shell' )
Packit fcad23
		{
Packit fcad23
		  # if $fix{$name} is a number, it is a pointer into
Packit fcad23
		  # $shell_lines[] where the shell commands are kept
Packit fcad23
		  $shell_lines[$#shell_lines+1] = $shell_header;
Packit fcad23
		  $fix{$name} = $#shell_lines;
Packit fcad23
		  $in_fix_shell_lines = 1;
Packit fcad23
		}
Packit fcad23
	      else
Packit fcad23
		{
Packit fcad23
		  $fix{$name} = $str2;
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
  &finish_db_entry($name);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub finish_db_entry
Packit fcad23
{
Packit fcad23
  local ($name) = pop(@_);
Packit fcad23
Packit fcad23
  if ($name ne '')
Packit fcad23
    {
Packit fcad23
      $! = $fixproc_error;
Packit fcad23
      die "$0: fix not defined for $name in database\n"
Packit fcad23
	if ($fix{$name} eq '');
Packit fcad23
      die "$0: cmd not defined for $name in database\n"
Packit fcad23
	if ($cmd{$name} eq '');
Packit fcad23
      $check{$name} = 'exist' if ($check{$name} eq '');
Packit fcad23
      $max{$name} = 1 if ($max{$name} eq '');
Packit fcad23
      $min{$name} = 1 if ($min{$name} eq '');
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
sub read_args
Packit fcad23
{
Packit fcad23
  local ($i) = 0;
Packit fcad23
  local ($arg);
Packit fcad23
  local ($action_arg_count) = 0;
Packit fcad23
Packit fcad23
  while ( $i <= $#ARGV )
Packit fcad23
    {
Packit fcad23
      $arg = $ARGV[$i];
Packit fcad23
      if (($arg eq '-min') || ($arg eq '-max'))
Packit fcad23
	{
Packit fcad23
	  if (($i == $#ARGV - 1) || ($ARGV[$i+1] =~ /\D/))  # \D is non-numeric
Packit fcad23
	    {
Packit fcad23
	      $! = $fixproc_error;
Packit fcad23
	      die "$0: numeric arg missing after -min or -max\n";
Packit fcad23
	    }
Packit fcad23
	  if ($arg eq '-min')
Packit fcad23
	    {
Packit fcad23
	      $min = $ARGV[$i+1];
Packit fcad23
	    }
Packit fcad23
	  else
Packit fcad23
	    {
Packit fcad23
	      $max = $ARGV[$i+1];
Packit fcad23
	    }
Packit fcad23
	  $i += 2;
Packit fcad23
	}
Packit fcad23
      elsif ($arg eq '-kill')
Packit fcad23
	{
Packit fcad23
	  $cmd_line_action = 'kill';
Packit fcad23
	  $action_arg_count++;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg eq '-check')
Packit fcad23
	{
Packit fcad23
	  $cmd_line_action = 'check';
Packit fcad23
	  $action_arg_count++;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg eq '-restart')
Packit fcad23
	{
Packit fcad23
	  $cmd_line_action = 'restart';
Packit fcad23
	  $action_arg_count++;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg eq '-exist')
Packit fcad23
	{
Packit fcad23
	  $cmd_line_action = 'exist';
Packit fcad23
	  $action_arg_count++;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg eq '-fix')
Packit fcad23
	{
Packit fcad23
	  $cmd_line_action = 'fix';
Packit fcad23
	  $action_arg_count++;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg =~ /-d(\d)$/)
Packit fcad23
	{
Packit fcad23
	  $debug = $1;
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
      elsif ($arg =~ /^-/)
Packit fcad23
	{
Packit fcad23
	  $! = $fixproc_error;
Packit fcad23
	  die "$0: unknown switch $arg\n";
Packit fcad23
	}
Packit fcad23
      else
Packit fcad23
	{
Packit fcad23
	  push (@proc_list, $arg);
Packit fcad23
	  $i++;
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
    $! = $fixproc_error;
Packit fcad23
    die "$0: no process specified\n" if ($#proc_list == -1);
Packit fcad23
    die "$0: more than one action specified\n" if ($action_arg_count > 1);
Packit fcad23
  }
Packit fcad23