#!/usr/local/bin/perl
# run.cgi
# Run some command with the given parameters

require './custom-lib.pl';
$theme_no_table = 1;
&foreign_require("proc", "proc-lib.pl");
if ($ENV{'CONTENT_TYPE'} =~ /multipart\/form-data/i) {
	&ReadParseMime();
	}
else {
	&ReadParse();
	}
$| = 1;
&error_setup($text{'run_err'});
@cmds = &list_commands();
$cmd = $cmds[$in{'idx'}];
&can_run_command($cmd) || &error($text{'run_ecannot'});
$user = $cmd->{'user'} eq '*' ? $remote_user : $cmd->{'user'};
@user_info = getpwnam($user);
@user_info || &error(&text('run_ecmduser', $user));

# substitute parameters into command
$str = $displaystr = $cmd->{'cmd'};
foreach $a (@{$cmd->{'args'}}) {
	$n = $a->{'name'};
	if ($a->{'type'} == 0 || $a->{'type'} == 5 ||
	    $a->{'type'} == 6 || $a->{'type'} == 8) {
		$rv = $in{$n};
		}
	elsif ($a->{'type'} == 11) {
		$rv = $in{$n};
		$rv =~ s/\r//g;
		$rv =~ s/\n/ /g;
		}
	elsif ($a->{'type'} == 1 || $a->{'type'} == 2) {
		(@u = getpwnam($in{$n})) || &error($text{'run_euser'});
		$rv = $a->{'type'} == 1 ? $in{$n} : $u[2];
		}
	elsif ($a->{'type'} == 3 || $a->{'type'} == 4) {
		(@g = getgrnam($in{$n})) || &error($text{'run_egroup'});
		$rv = $a->{'type'} == 3 ? $in{$n} : $g[2];
		}
	elsif ($a->{'type'} == 7) {
		$rv = $in{$n} ? $a->{'opts'} : "";
		}
	elsif ($a->{'type'} == 9) {
		local $found;
		foreach $l (&read_opts_file($a->{'opts'})) {
			$found++ if ($l->[0] eq $in{$n});
			}
		$found || &error($text{'run_eopt'});
		$rv = $in{$n};
		}
	elsif ($a->{'type'} == 10) {
		$in{$n} || &error($text{'run_eupload'});
		$in{$n."_filename"} =~ /([^\/\\]+$)/;
		$rv = &tempname("$1");
		open(TEMP, ">$rv");
		print TEMP $in{$n};
		close(TEMP);
		chown($user_info[2], $user_info[3], $rv);
		push(@unlink, $rv);
		}
	$ENV{$n} = $rv;
	$env .= "$n='$rv'\n";
	$export .= " $n";
	if ($a->{'quote'}) {
		$str =~ s/\$$n/"\$$n"/g;
		$displaystr =~ s/\$$n/"$rv"/g;
		}
	else {
		$displaystr =~ s/\$$n/$rv/g;
		}
	}

# Run and display output
$| = 1;
&header($text{'run_title'}, "", -d "help" ? "run" : undef);
print "<center><font size=+2>$cmd->{'desc'}</font></center>\n";
print "<hr>\n";
if ($cmd->{'noshow'}) {
	print "<p>$text{'run_out2'}\n";
	}
else {
	print "<p>",&text('run_out',
			  "<tt>".&html_escape($displaystr)."</tt>"),"\n";
	}
print "<pre>" if (!$cmd->{'raw'});
if ($cmd->{'su'}) {
	$temp = &tempname();
	open(TEMP, ">$temp");
	print TEMP "#!/bin/sh\n";
	print TEMP $env;
	print TEMP "export $export\n" if ($export);
	print TEMP "$str\n";
	close(TEMP);
	chmod(0755, $temp);
	$got = &foreign_call("proc", "safe_process_exec",
	   		     "su - $user -c $temp", 0, 0,
			     STDOUT, undef, !$cmd->{'raw'}, 0,
			     $cmd->{'timeout'});
	unlink($temp);
	}
else {
	$got = &foreign_call("proc", "safe_process_exec", $str,
			     $user_info[2], undef, STDOUT, undef,
			     !$cmd->{'raw'}, 0, $cmd->{'timeout'});
	}
&additional_log('exec', undef, $displaystr);
if (!$got) { print "<i>$text{'run_noout'}</i>\n"; }
print "</pre>\n" if (!$cmd->{'raw'});
if ($proc::safe_process_exec_timeout) {
	print "<b>",&text('run_timeout', $cmd->{'timeout'}),"</b><p>\n";
	}
%cmdin = ( %$cmd, %in );
&webmin_log("exec", "command", $cmd->{'id'}, \%cmdin);
unlink(@unlink) if (@unlink);
print "<hr>\n";
&footer("", $text{'index_return'});

