# Up2us -- RPM package manager manager for linux and beyond # THIS MODULE: External program execution. # $Id: execute.pm,v 1.3 2003/04/03 22:40:47 tomj Exp $ # Copyright Tom Jennings 2002-2003 # tomj@wps.com, http://wps.com # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU 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 General Public License for more details. # # You should have received a copy of the GNU 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. # OVERVIEW: # Executes programs for which we have configuration. Basically, # it builds configuration for the indicated repository and invoke # the program after building a command line. Checks for errors and # all that rot. # # SOFTWARE STRUCTURE: these routines contain no interface-related # anything. They mostly return text string error messages which can # be displayed as the caller sees fit. # Error messages and such. my $cfgerr= "Config item \"%s-path\" must be an absolute pathname."; my $forkU= "Some weird fork error what gone and killted us."; my $forkerr= "The \"%s-path\" program exited with code %d.\n\n(Whole enchilada was \"%s\")."; my $forkoop= "The impossible has happened: fork() returned?"; ############################################################# # # $error= &run_prog ("programname", "repositoryname", @ARGS); # # Executes the specified program, after building config files that # refer to the given repository. Config items named programname-* # should exist in up2us's config (some are mandatory, some not). # The list of args is optional; not all programs use them, but if # present they replace the macro names in config item "prog-args" # named $1..$9, eg. filenames and such. sub run_prog { my $prog= shift; # logical name of program, my $rep= shift; # repository name, my @args= @_; # optional args &build_config_for ($rep); # make config files, my $e= &write_config_data; # flush files to disk, return $e if $e ne $OK; # The path to the program is mandatory, and it must begin with / # and contain at least one other /. my $pathname= &cfg_item ("$prog-path"); # prog to execute, return sprintf ($cfgerr, $prog) if $pathname !~ m"^/.*/"; # Build a command line, first doing any macro substitutions. my $a= &cfg_item ("$prog-args"); # program args, $a= "" if not defined $a; # (eg. up2date) for (my $i= 1; scalar @args; ++$i) { # substitute all/any, $_= shift @args; $a =~ s/\$$i/$_/g; # make substitution, } @args= split (' ', $a); # turn into a list, # Now run what we brung. $p= "$pathname " . join (' ', @args); # the whole thing, my $pid= fork(); # split 'twain, return $forkU if not defined $pid; # something wrong if ($pid != 0) { # yo, it's us, while ((my $foo= waitpid ($pid, &WNOHANG())) == 0) { &while_idle(); # update interface } if ($? != 0) { $? &= 0xffff; my $exit= $? >> 8; # I took the trouble my $sig= $? & 127; # to look it up, my $core= $? & 128; # someday useful? return sprintf ($forkerr, $prog, $exit, $p); } else { # success, return $OK; } } else { # we're the child, &logorrhea ("Executing $p\n"); exec ($pathname, @args); # go run program, } return $forkoop; } return 1;