control with more output and status

This commit is contained in:
Mario Fetka
2026-05-21 18:23:49 +02:00
parent 1f032a1d43
commit adf4081dfc
3 changed files with 273 additions and 102 deletions

View File

@@ -9,7 +9,7 @@ use warnings;
our ($server_id, $mars_nwe_service, $smart_systemctl_path, $cc, %p);
sub html_escape($)
sub html_escape
{
my ($s) = @_;
$s = '' unless defined $s;
@@ -20,8 +20,137 @@ sub html_escape($)
return $s;
}
sub handle_request()
sub run_systemctl_command
{
my ($systemctl, @args) = @_;
my $output = '';
my ($reader, $writer);
if( ! pipe( $reader, $writer ) )
{
return (1, 'Could not create pipe: ' . $! . "\n");
}
my $pid = fork();
if( ! defined( $pid ) )
{
close( $reader );
close( $writer );
return (1, 'Could not fork: ' . $! . "\n");
}
if( $pid == 0 )
{
close( $reader );
# Capture stdout for the web UI. Leave stderr untouched so systemctl
# warnings/errors still go to smart.log, matching the old behaviour.
open( STDOUT, '>&', $writer ) or exit 127;
close( $writer );
exec( $systemctl, @args ) or do {
print 'Could not execute ' . $systemctl . ': ' . $! . "\n";
exit 127;
};
}
close( $writer );
while( my $line = <$reader> )
{
$output .= $line;
}
close( $reader );
waitpid( $pid, 0 );
my $rc = $? >> 8;
return ( $rc, $output );
}
sub wait_for_service_state
{
my ($systemctl, $service, $wanted, $timeout) = @_;
my $elapsed = 0;
my $last_state = '';
my $ok = 0;
$timeout = 45 unless defined($timeout) && $timeout > 0;
print '# waiting for ' . html_escape($service) . ' to become ' . html_escape($wanted) . "\n";
while( $elapsed <= $timeout )
{
my ($state_rc, $state_output) = run_systemctl_command( $systemctl, 'is-active', $service );
my $state = $state_output;
$state =~ s/[\r\n]+$//;
$state =~ s/^\s+//;
$state =~ s/\s+$//;
$state = 'unknown' if $state eq '';
if( $state ne $last_state )
{
print sprintf( "[%2ds] state: %s\n", $elapsed, html_escape($state) );
$last_state = $state;
}
if( $wanted eq 'inactive' )
{
if( $state eq 'inactive' || $state eq 'failed' )
{
$ok = 1;
last;
}
}
elsif( $wanted eq 'active' )
{
if( $state eq 'active' )
{
$ok = 1;
last;
}
if( $state eq 'failed' )
{
last;
}
}
sleep( 1 );
$elapsed++;
}
if( $ok )
{
print "wait result: reached $wanted\n";
return 0;
}
print "wait result: timeout after $timeout seconds\n";
return 1;
}
sub append_command_output
{
my ($title, $rc, $output) = @_;
print '# ' . html_escape($title) . "\n";
if( defined($output) && $output ne '' )
{
print html_escape($output);
}
else
{
print "(no output)\n";
}
print "exit code: $rc\n";
}
sub handle_request
{
local $| = 1;
my $service = $mars_nwe_service || '@MARS_NWE_SYSTEMD_SERVICE@';
my $systemctl = $smart_systemctl_path || '@SYSTEMCTL_EXECUTABLE@';
my $query = defined($cc) ? $cc : '';
@@ -42,7 +171,7 @@ sub handle_request()
$action = $1;
}
print <<EOF;
print <<HTML_HEAD;
HTTP/1.0 200 OK
Content-Type: text/html
$server_id
@@ -61,12 +190,16 @@ a{color:#9f1f1f;text-decoration:none;font-weight:bold}a:hover{text-decoration:un
h1{margin-top:0;color:#9f1f1f}.meta{padding:12px 14px;background:#fbf6ef;border:1px solid #ecdcc8;border-radius:12px;margin-bottom:14px}
pre{background:#2b241f;color:#f8eadc;padding:16px;border-radius:12px;overflow:auto;white-space:pre-wrap}.ok{color:#2f6f35;font-weight:bold}.bad{color:#9f1f1f;font-weight:bold}
.actions a{display:inline-block;margin:5px 8px 5px 0;padding:9px 12px;border-radius:10px;background:#9f1f1f;color:#fff}.actions a.secondary{background:#6f5b4f}
.waitbox{display:flex;align-items:center;gap:14px;margin:14px 0;padding:14px 16px;border:1px solid #ecdcc8;border-radius:14px;background:#fbf6ef;color:#6f5b4f}
.spinner{width:30px;height:30px;border:4px solid #e5d6c6;border-top-color:#9f1f1f;border-radius:50%;animation:spin .9s linear infinite;flex:0 0 auto}
\@keyframes spin{to{transform:rotate(360deg)}}
.waittitle{font-weight:bold;color:#9f1f1f}.waitsub{font-size:13px;margin-top:3px}
</style>
</head>
<body>
<div class="box">
<h1>MARS_NWE service control</h1>
EOF
HTML_HEAD
if( $action eq '' )
{
@@ -80,48 +213,85 @@ EOF
print '<div class="meta">Action: <b>' . html_escape($action) . '</b><br>' . "\n";
print 'Service: <b>' . html_escape($service) . '</b><br>' . "\n";
print 'systemctl: <b>' . html_escape($systemctl) . '</b></div>' . "\n";
if( $action ne 'status' )
{
my $wait_text = 'Waiting for service state change';
if( $action eq 'stop' )
{
$wait_text = 'Stopping service, waiting until it is inactive';
}
elsif( $action eq 'start' )
{
$wait_text = 'Starting service, waiting until it is active';
}
elsif( $action eq 'restart' )
{
$wait_text = 'Restarting service, waiting until it is active';
}
print '<div id="waitbox" class="waitbox">' . "\n";
print '<div class="spinner" aria-hidden="true"></div>' . "\n";
print '<div><div class="waittitle">' . html_escape($wait_text) . '</div>' . "\n";
print '<div class="waitsub">This can take up to 45 seconds. Please wait until the final status appears below.</div></div>' . "\n";
print '</div>' . "\n";
print " " x 4096; # help browsers render the waiting box before the command finishes
}
print "<pre>\n";
my @cmd = ( $systemctl, $action, $service );
my $fh;
if( ! open( $fh, '-|', @cmd ) )
{
print 'Could not execute systemctl: ' . html_escape($!) . "\n";
print "</pre><p class=\"bad\">Failed.</p>\n";
print "<p><a href=\"/static/start.html\">Back</a></p>\n";
print "</div></body></html>\n";
return;
}
my $rc = 0;
my $output = '';
while( my $line = <$fh> )
if( $action eq 'status' )
{
print html_escape($line);
}
close($fh);
my $rc = $? >> 8;
if( $rc == 0 )
{
print "</pre><p class=\"ok\">Command completed successfully.</p>\n";
( $rc, $output ) = run_systemctl_command( $systemctl, '--no-pager', '--full', 'status', $service );
append_command_output( "systemctl --no-pager --full status $service", $rc, $output );
}
else
{
print "</pre><p class=\"bad\">Command failed with exit code $rc.</p>\n";
# Avoid repeated "unit file changed on disk" warnings after install/update.
my ( $reload_rc, $reload_output ) = run_systemctl_command( $systemctl, 'daemon-reload' );
append_command_output( 'systemctl daemon-reload', $reload_rc, $reload_output );
print "\n";
( $rc, $output ) = run_systemctl_command( $systemctl, $action, $service );
append_command_output( "systemctl $action $service", $rc, $output );
print "\n";
if( $rc == 0 )
{
my $wanted_state = ( $action eq 'stop' ) ? 'inactive' : 'active';
my $wait_rc = wait_for_service_state( $systemctl, $service, $wanted_state, 45 );
print "\n";
$rc = $wait_rc if $wait_rc != 0;
}
my ( $status_rc, $status_output ) = run_systemctl_command( $systemctl, '--no-pager', '--full', 'status', $service );
append_command_output( "systemctl --no-pager --full status $service", $status_rc, $status_output );
}
print <<EOF;
if( $rc == 0 )
{
print "</pre><script>var w=document.getElementById('waitbox');if(w){w.style.display='none';}</script><p class=\"ok\">Command completed successfully.</p>\n";
}
else
{
print "</pre><script>var w=document.getElementById('waitbox');if(w){w.style.display='none';}</script><p class=\"bad\">Command failed with exit code $rc.</p>\n";
}
print <<HTML_FOOT;
<div class="actions">
<a href="/cgi-bin/control?status" class="secondary">Status</a>
<a href="/cgi-bin/control?start">Start</a>
<a href="/cgi-bin/control?stop" class="secondary">Stop</a>
<a href="/cgi-bin/control?restart">Restart</a>
<a href="/service/control?status" class="secondary">Status</a>
<a href="/service/control?start">Start</a>
<a href="/service/control?stop" class="secondary">Stop</a>
<a href="/service/control?restart">Restart</a>
</div>
<p><a href="/static/start.html">Back</a></p>
</div>
</body>
</html>
EOF
HTML_FOOT
}
1;

View File

@@ -238,10 +238,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/general" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -399,10 +396,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/dirs" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -531,10 +525,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/configh" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -665,10 +656,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/security" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -788,10 +776,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/susers" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -955,10 +940,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/logging" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -1197,10 +1179,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
<TR BGCOLOR="#d7c0a0">
@@ -1325,10 +1304,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/volumes/$c[0]" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -1498,10 +1474,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
<TR BGCOLOR="#d7c0a0">
@@ -1586,10 +1559,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/devices/$c[0]" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -1704,10 +1674,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/smart" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -1813,10 +1780,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
<TR BGCOLOR="#d7c0a0">
@@ -1931,10 +1895,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/users/$c[2]" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -2053,10 +2014,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
<TR BGCOLOR="#d7c0a0">
@@ -2164,10 +2122,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/groups/$c[2]" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
@@ -2269,10 +2224,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>
<TR BGCOLOR="#d7c0a0">
@@ -2358,10 +2310,7 @@ TT { color:#5b4b38; }
</style>
</HEAD>
<BODY BGCOLOR="#f6f2ea">
<DIV STYLE="position:sticky;top:0;z-index:50;margin:0 0 12px 0;padding:8px 10px;background:#fffdfa;border:1px solid #ddcfba;border-radius:12px;box-shadow:0 4px 14px rgba(80,55,30,0.08);">
<A STYLE="display:inline-block;margin-right:10px;padding:7px 12px;border-radius:9px;background:#6d5d53;color:#fff;text-decoration:none;font-weight:bold;" HREF="javascript:history.back()">Back</A>
<A STYLE="display:inline-block;padding:7px 12px;border-radius:9px;background:#a32020;color:#fff;text-decoration:none;font-weight:bold;" HREF="/" TARGET="_top">Main menu</A>
</DIV>
$settings_nav_bar
<FORM ACTION="/apply/queues/$c[2]" METHOD=GET>
<TABLE BORDER=0 CELLSPACING=0 WIDTH=100%>

View File

@@ -115,11 +115,63 @@ if( ( $c[0] eq 'service' && $c[1] eq 'control' ) ||
{
# Service control must run before drop_root().
# /service/control is the preferred path; /cgi-bin/control is kept as a legacy alias.
my $rv = do( $smart_control_path );
if( ! defined $rv )
my @control_paths = ();
if( defined( $smart_control_path ) && $smart_control_path ne '' &&
$smart_control_path !~ /^\@.*\@/ )
{
error( 500 );
push( @control_paths, $smart_control_path );
}
push( @control_paths, $smart_libexec_dir . '/control' );
my %seen_control_path = ();
my $control_loaded = 0;
my $control_error = '';
foreach my $control_path ( @control_paths )
{
next if $seen_control_path{$control_path}++;
next if $control_path eq '';
if( ! -r $control_path )
{
$control_error .= "Cannot read control helper: $control_path: $!\n";
next;
}
my $rv = do( $control_path );
if( defined( $rv ) )
{
$control_loaded = 1;
last;
}
if( $@ ne '' )
{
$control_error .= "Could not compile control helper $control_path: $@\n";
}
else
{
$control_error .= "Could not load control helper $control_path: $!\n";
}
}
if( ! $control_loaded )
{
$control_error = 'Unknown control helper loading error.' if $control_error eq '';
print <<EOF;
HTTP/1.0 500 Internal server error
Content-Type: text/plain
$server_id
Could not load SMArT service control helper.
$control_error
EOF
exit;
}
handle_request();
exit;
}