add print test page
This commit is contained in:
82
README.md
82
README.md
@@ -235,23 +235,19 @@ Use `trace` only while debugging a concrete problem. It may include submitted bi
|
||||
|
||||
### `nwwebui` service log level
|
||||
|
||||
The `nwwebui` service has its own named log level:
|
||||
The `nwwebui` service has its own numeric log level:
|
||||
|
||||
```perl
|
||||
$nw_log_level = 'info';
|
||||
$nw_log_level = 'info';
|
||||
```
|
||||
|
||||
Supported values:
|
||||
Typical meanings:
|
||||
|
||||
```text
|
||||
error = only real errors
|
||||
warning = errors and warnings
|
||||
info = normal operational messages
|
||||
debug = additional diagnostic information
|
||||
trace = very verbose request/connection tracing
|
||||
```
|
||||
- `0` = errors only
|
||||
- `1` = informational messages
|
||||
- `2` = debug output
|
||||
|
||||
Older numeric values are still accepted for compatibility, but named values are preferred.## Installed components
|
||||
## Installed components
|
||||
|
||||
### Binaries
|
||||
|
||||
@@ -344,6 +340,18 @@ $nw_cert_file = '/etc/mars_nwe/server.crt';
|
||||
$nw_key_file = '/etc/mars_nwe/server.key';
|
||||
```
|
||||
|
||||
### Print queue test action
|
||||
|
||||
The print queue page can submit a small test job to an existing MARS_NWE queue
|
||||
through the ncpfs `nprint` tool. This verifies the queue through the NetWare
|
||||
print-queue path instead of only checking the local Unix/CUPS command.
|
||||
|
||||
The helper path can be adjusted in `smart.conf`:
|
||||
|
||||
```perl
|
||||
$smart_nprint_path = '/usr/bin/nprint';
|
||||
```
|
||||
|
||||
## Recent SMArT WebUI features
|
||||
|
||||
The current WebUI includes several usability and safety improvements:
|
||||
@@ -435,6 +443,26 @@ Typical access URLs:
|
||||
|
||||
For production use, HTTPS should be preferred.
|
||||
|
||||
## Native helper logging
|
||||
|
||||
The native helper programs `check_login` and `smart_userlist` read their log
|
||||
destination and verbosity from `smart.conf` when called by the WebUI.
|
||||
|
||||
They use the same Perl frontend settings:
|
||||
|
||||
```perl
|
||||
$smart_log_path = '/var/log/mars_nwe/smart.log';
|
||||
$smart_debug_level = 'info';
|
||||
```
|
||||
|
||||
The generated `config.h` also provides fallback defaults for these values, so
|
||||
the helpers can still write useful diagnostics when they are executed manually
|
||||
or before `smart.conf` could be loaded.
|
||||
|
||||
`check_login` logs authentication and authorization results, but never logs the
|
||||
submitted password. `smart_userlist` keeps its tab-separated user-list output
|
||||
on stdout unchanged and writes diagnostics only to the configured log file.
|
||||
|
||||
## Unix user discovery helper
|
||||
|
||||
The WebUI user editor can assign a MARS_NWE bindery user to a local Unix user.
|
||||
@@ -455,38 +483,6 @@ $smart_userlist_path = '/usr/libexec/mars_nwe/smart_userlist';
|
||||
If the path is not set explicitly, SMArT falls back to the standard libexec
|
||||
location generated by the build system.
|
||||
|
||||
When called by the WebUI, the helper also reads `smart.conf` so diagnostics can
|
||||
use `$smart_log_path` and `$smart_debug_level`.
|
||||
|
||||
## Summary
|
||||
|
||||
SMArT is now an integrated part of the `mars_nwe` release. It includes a dedicated `nwwebui` service, form-based sessions, PAM authentication with configurable administrator group restriction, service control, validation pages, import helpers, improved bindery command handling, and configurable logging.
|
||||
|
||||
## Logging overview
|
||||
|
||||
SMArT uses two related but separate log-level settings:
|
||||
|
||||
- `$nw_log_level` controls the native `nwwebui` HTTP/HTTPS frontend and writes
|
||||
to `$nw_log_file`.
|
||||
- `$smart_debug_level` controls the Perl application scripts and native helper
|
||||
tools such as `check_login` and `smart_userlist`; these messages are written
|
||||
to `$smart_log_path`.
|
||||
|
||||
Both settings use the same named levels:
|
||||
|
||||
```text
|
||||
error
|
||||
warning
|
||||
info
|
||||
debug
|
||||
trace
|
||||
```
|
||||
|
||||
`info` is the recommended normal setting. Use `debug` or `trace` only while
|
||||
troubleshooting a specific problem. Trace logging may include submitted bindery
|
||||
payload data and can produce a large amount of output.
|
||||
|
||||
The login helper logs authentication and authorization results, but never logs
|
||||
the submitted password. `smart_userlist` keeps its tab-separated user list on
|
||||
stdout and writes diagnostics only to the configured SMArT log file.
|
||||
|
||||
|
||||
341
apply.pl
341
apply.pl
@@ -596,39 +596,6 @@ sub redirect_msg( $$ )
|
||||
}
|
||||
|
||||
|
||||
sub smart_log_level_value( $ )
|
||||
{
|
||||
my $level = $_[0];
|
||||
|
||||
$level = 'info' unless defined( $level ) && $level ne '';
|
||||
$level = lc( $level );
|
||||
|
||||
return 0 if $level eq 'error';
|
||||
return 1 if $level eq 'warning' || $level eq 'warn';
|
||||
return 2 if $level eq 'info';
|
||||
return 3 if $level eq 'debug';
|
||||
return 4 if $level eq 'trace';
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
sub smart_current_log_level()
|
||||
{
|
||||
my $level = 'info';
|
||||
|
||||
$level = $smart_debug_level if defined( $smart_debug_level ) && $smart_debug_level ne '';
|
||||
$level = $smart_log_level if defined( $smart_log_level ) && $smart_log_level ne '';
|
||||
|
||||
return smart_log_level_value( $level );
|
||||
}
|
||||
|
||||
sub smart_log_enabled( $ )
|
||||
{
|
||||
my $level = $_[0];
|
||||
|
||||
return smart_log_level_value( $level ) <= smart_current_log_level();
|
||||
}
|
||||
|
||||
sub apply_log_line( $$ )
|
||||
{
|
||||
my( $level, $msg ) = @_;
|
||||
@@ -636,17 +603,12 @@ sub apply_log_line( $$ )
|
||||
$level = 'INFO' unless defined( $level ) && $level ne '';
|
||||
$msg = '' unless defined( $msg );
|
||||
|
||||
return if ! smart_log_enabled( $level );
|
||||
|
||||
my( $sec, $min, $hour, $mday, $mon, $year ) = localtime( time() );
|
||||
my $ts = sprintf( "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
$year + 1900, $mon + 1, $mday, $hour, $min, $sec );
|
||||
|
||||
my $version = defined( $smart_version ) && $smart_version ne '' ? $smart_version : '0.99.pl28';
|
||||
my $level_text = uc( $level );
|
||||
$level_text = 'WARNING' if $level_text eq 'WARN';
|
||||
|
||||
my $line = '[' . $ts . '] [' . $level_text . '] [SMArT ' . $version . '] [apply.pl] ' . $msg . "\n";
|
||||
my $line = '[' . $ts . '] [' . $level . '] [SMArT ' . $version . '] [apply.pl] ' . $msg . "\n";
|
||||
|
||||
if( defined( $bindery_log_fh ) )
|
||||
{
|
||||
@@ -851,17 +813,6 @@ sub run_bindery_cmd( @ )
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub apply_trace_log( $ )
|
||||
{
|
||||
apply_log_line( 'TRACE', $_[0] );
|
||||
}
|
||||
|
||||
sub apply_debug_log( $ )
|
||||
{
|
||||
apply_log_line( 'DEBUG', $_[0] );
|
||||
}
|
||||
|
||||
|
||||
sub run_bindery_pipe( $$ )
|
||||
{
|
||||
my( $cmd, $payload ) = @_;
|
||||
@@ -872,21 +823,19 @@ sub run_bindery_pipe( $$ )
|
||||
$cmd = '' unless defined( $cmd );
|
||||
$payload = '' unless defined( $payload );
|
||||
|
||||
apply_log_line( 'INFO', 'bindery pipe command: ' . $cmd );
|
||||
|
||||
my $log_payload = $payload;
|
||||
$log_payload =~ s/\r/\\r/g;
|
||||
$log_payload =~ s/\n/\\n/g;
|
||||
$log_payload = substr( $log_payload, 0, 500 ) . '...' if length( $log_payload ) > 500;
|
||||
apply_trace_log( 'bindery pipe payload=' . $log_payload );
|
||||
|
||||
apply_trace_log( 'bindery pipe trace: entered run_bindery_pipe' );
|
||||
apply_log_line( 'INFO', 'bindery pipe command: ' . $cmd . ' payload=' . $log_payload );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: entered run_bindery_pipe' );
|
||||
|
||||
my $tmpdir = '/run/mars-nwe-webui';
|
||||
$tmpdir = '/tmp' if ! -d $tmpdir || ! -w $tmpdir;
|
||||
|
||||
my $tmp = $tmpdir . '/smart-bindery-' . $$ . '-' . int( rand( 1000000 ) ) . '.in';
|
||||
apply_trace_log( 'bindery pipe trace: temp file ' . $tmp );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: temp file ' . $tmp );
|
||||
|
||||
my $tfh;
|
||||
if( ! sysopen( $tfh, $tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600 ) )
|
||||
@@ -897,8 +846,8 @@ sub run_bindery_pipe( $$ )
|
||||
return 0;
|
||||
}
|
||||
|
||||
apply_trace_log( 'bindery pipe trace: temp file opened' );
|
||||
apply_trace_log( 'bindery pipe trace: writing payload via syswrite length=' . length( $payload ) );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: temp file opened' );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: writing payload via syswrite length=' . length( $payload ) );
|
||||
|
||||
my $offset = 0;
|
||||
my $len = length( $payload );
|
||||
@@ -930,7 +879,7 @@ sub run_bindery_pipe( $$ )
|
||||
$offset += $written;
|
||||
}
|
||||
|
||||
apply_trace_log( 'bindery pipe trace: payload written bytes=' . $offset );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: payload written bytes=' . $offset );
|
||||
|
||||
if( ! close( $tfh ) )
|
||||
{
|
||||
@@ -941,18 +890,18 @@ sub run_bindery_pipe( $$ )
|
||||
return 0;
|
||||
}
|
||||
|
||||
apply_trace_log( 'bindery pipe trace: temp file closed' );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: temp file closed' );
|
||||
|
||||
my $shell_cmd = $cmd . ' < ' . apply_shell_quote( $tmp );
|
||||
apply_trace_log( 'bindery pipe shell command: ' . $shell_cmd );
|
||||
apply_log_line( 'INFO', 'bindery pipe shell command: ' . $shell_cmd );
|
||||
|
||||
my $output = `$shell_cmd 2>&1`;
|
||||
my $rc = $?;
|
||||
|
||||
apply_trace_log( 'bindery pipe trace: shell command returned rc=' . ( $rc >> 8 ) );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: shell command returned rc=' . ( $rc >> 8 ) );
|
||||
|
||||
unlink( $tmp );
|
||||
apply_trace_log( 'bindery pipe trace: temp file removed' );
|
||||
apply_log_line( 'INFO', 'bindery pipe trace: temp file removed' );
|
||||
|
||||
$output = '' unless defined( $output );
|
||||
$output =~ s/\r//g;
|
||||
@@ -1317,15 +1266,76 @@ EOF
|
||||
}
|
||||
elsif( $c[1] eq 'queues' )
|
||||
{
|
||||
my $is_delete = scalar( keys( %p ) ) == 0;
|
||||
|
||||
if( defined( $p{name} ) || defined( $p{command} ) || defined( $p{spool} ) || defined( $p{unix_print} ) || defined( $p{spool_dir} ) )
|
||||
{
|
||||
return( 1 ) if ! validate_queue_params();
|
||||
}
|
||||
|
||||
return( 1 ) if ! require_mars_nwe_service( 'print queues' );
|
||||
|
||||
$server = get_server();
|
||||
|
||||
if( defined( $p{test_print} ) )
|
||||
{
|
||||
open_bindery_command_log();
|
||||
drop_root();
|
||||
test_print_queue( $server, $c[2] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( $is_delete )
|
||||
{
|
||||
# Section 21 is the nwserv.conf print queue definition:
|
||||
# 21 QUEUE_NAME SPOOL_DIR UNIX_PRINT_COMMAND
|
||||
# Delete it before drop_root(), while apply.pl can still write nwserv.conf.
|
||||
apply_log_line( 'INFO', 'print queue config delete requested queue=' . $c[2] );
|
||||
my( $conf_removed, $raw_removed ) = delconfigqueue( $c[2] );
|
||||
apply_log_line( 'INFO', 'print queue config delete conf_removed=' . $conf_removed . ' raw_removed=' . $raw_removed . ' queue=' . $c[2] );
|
||||
writeconfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( $c[2] ne 'add_new' )
|
||||
{
|
||||
$p{name} = $c[2] if ! defined( $p{name} ) || $p{name} eq '';
|
||||
}
|
||||
|
||||
$p{name} = normalize_queue_name( $p{name} );
|
||||
|
||||
if( $p{spool_dir} eq '' )
|
||||
{
|
||||
$p{spool_dir} = 'SYS:SYSTEM/' . $p{name} . '.QDR';
|
||||
}
|
||||
|
||||
my( $conf_removed, $raw_removed ) = delconfigqueue( $p{name} );
|
||||
my $queue_line = queue_config_line( $p{name}, $p{spool_dir}, $p{unix_print} );
|
||||
apply_log_line( 'INFO', 'print queue config save queue=' . $p{name} . ' conf_replaced=' . $conf_removed . ' raw_replaced=' . $raw_removed . ' line=' . $queue_line );
|
||||
addconfigline( $queue_line );
|
||||
writeconfig();
|
||||
}
|
||||
|
||||
open_bindery_command_log();
|
||||
drop_root();
|
||||
|
||||
|
||||
$server = get_server();
|
||||
|
||||
if( $is_delete )
|
||||
{
|
||||
if( queue_exists_in_bindery( $server, $c[2] ) )
|
||||
{
|
||||
return( 1 ) if ! run_bindery_cmd( 'nwborm', '-S', $server, '-t', '3', '-o', $c[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
apply_log_line( 'INFO', 'bindery queue removal skipped, queue not present in bindery: ' . $c[2] );
|
||||
}
|
||||
|
||||
bindery_success_page( 'Print queue deleted', 'Print queue configuration and bindery object were removed if present.', '/settings/queues' );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( $c[2] eq 'add_new' )
|
||||
{
|
||||
return( 1 ) if ! run_bindery_cmd( 'nwbocreate', '-S', $server, '-t', '3', '-o', $p{name} );
|
||||
@@ -1367,25 +1377,11 @@ EOF
|
||||
return( 1 ) if ! run_bindery_cmd( 'nwbprm', '-S', $server, '-t', '3', '-o', $c[2], '-p', 'Q_UNIX_PRINT' );
|
||||
return( 1 ) if ! run_bindery_cmd( 'nwbprm', '-S', $server, '-t', '3', '-o', $c[2], '-p', 'Q_DIRECTORY' );
|
||||
}
|
||||
|
||||
if( scalar( keys( %p ) ) == 0 )
|
||||
{
|
||||
return( 1 ) if ! run_bindery_cmd( 'nwborm', '-S', $server, '-t', '3', '-o', $c[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( $p{spool_dir} eq '' )
|
||||
{
|
||||
$id = ( split( ' ', ( grep( /^$c[2] /, split( "\n", `nwbols -S $server` ) ) )[0] ) )[1]; # Woohoo... ;)
|
||||
$p{spool_dir} = 'SYS:SYSTEM/' . $id . '.QDR';
|
||||
}
|
||||
|
||||
write_property_string( $c[2], 3, 'Q_UNIX_PRINT', 0, 31, $p{unix_print} );
|
||||
write_property_string( $c[2], 3, 'Q_DIRECTORY', 0, 31, $p{spool_dir} );
|
||||
}
|
||||
|
||||
bindery_success_page( 'Print queue saved', 'Print queue bindery settings were saved successfully.', '/settings/queues' );
|
||||
|
||||
write_property_string( $c[2], 3, 'Q_UNIX_PRINT', 0, 31, $p{unix_print} );
|
||||
write_property_string( $c[2], 3, 'Q_DIRECTORY', 0, 31, $p{spool_dir} );
|
||||
|
||||
bindery_success_page( 'Print queue saved', 'Print queue configuration and bindery settings were saved successfully.', '/settings/queues' );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
@@ -1520,6 +1516,187 @@ sub sanitize_number_value( $ )
|
||||
return $v;
|
||||
}
|
||||
|
||||
sub queue_config_name( $ )
|
||||
{
|
||||
my $line = $_[0];
|
||||
|
||||
$line = '' unless defined( $line );
|
||||
$line =~ s/^\s*21\s+//i;
|
||||
$line =~ s/^\s+//;
|
||||
$line =~ s/\s+$//;
|
||||
|
||||
return ( split( /\s+/, $line, 2 ) )[0];
|
||||
}
|
||||
|
||||
|
||||
sub queue_test_result_page( $$$$ )
|
||||
{
|
||||
my( $queue, $ok, $message, $output ) = @_;
|
||||
|
||||
$queue = apply_html_escape( $queue );
|
||||
$message = apply_html_escape( $message );
|
||||
$output = apply_html_escape( $output );
|
||||
|
||||
my $title = $ok ? 'Print queue test sent' : 'Print queue test failed';
|
||||
my $color = $ok ? '#2f5b24' : '#8a1f16';
|
||||
my $bg = $ok ? '#edf7e8' : '#fff0ed';
|
||||
|
||||
print <<EOF;
|
||||
HTTP/1.0 200 OK
|
||||
Content-Type: text/html
|
||||
$server_id
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>SMArT Print queue test</TITLE>
|
||||
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
||||
<style>
|
||||
BODY { background:#f6f2ea; color:#2e261d; font-family: Arial, Helvetica, sans-serif; margin:0; padding:24px; }
|
||||
.box { max-width:850px; margin:30px auto; background:#fbf7f1; border:1px solid #ddcfba; border-radius:18px; overflow:hidden; box-shadow:0 6px 18px rgba(80,55,30,0.08); }
|
||||
.head { background:#d7c0a0; padding:14px 16px; font-weight:bold; font-size:22px; }
|
||||
.body { padding:16px; }
|
||||
.status { margin:0 0 14px 0; padding:12px 14px; border-radius:12px; background:$bg; color:$color; font-weight:bold; }
|
||||
PRE { white-space:pre-wrap; background:#fffdf9; border:1px solid #ddcfba; border-radius:12px; padding:12px; overflow:auto; }
|
||||
A.button { display:inline-block; margin-top:14px; padding:9px 14px; border-radius:10px; background:#b84434; color:white; text-decoration:none; font-weight:bold; }
|
||||
</style>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<div class="box">
|
||||
<div class="head">$title</div>
|
||||
<div class="body">
|
||||
<div class="status">$message</div>
|
||||
<p><b>Queue:</b> <tt>$queue</tt></p>
|
||||
<p><b>Command output:</b></p>
|
||||
<PRE>$output</PRE>
|
||||
<a class="button" href="/settings/queues" target="OPTS">Back to print queues</a>
|
||||
</div>
|
||||
</div>
|
||||
</BODY>
|
||||
</HTML>
|
||||
EOF
|
||||
}
|
||||
|
||||
sub test_print_queue( $$ )
|
||||
{
|
||||
my( $server, $queue ) = @_;
|
||||
|
||||
$server = '' unless defined( $server );
|
||||
$queue = normalize_queue_name( $queue );
|
||||
|
||||
if( $queue eq '' )
|
||||
{
|
||||
queue_test_result_page( $queue, 0, 'Queue name is empty.', '' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $nprint = defined( $smart_nprint_path ) && $smart_nprint_path ne '' ? $smart_nprint_path : '/usr/bin/nprint';
|
||||
|
||||
if( ! -x $nprint )
|
||||
{
|
||||
my $msg = 'nprint helper not found or not executable: ' . $nprint;
|
||||
apply_log_line( 'ERROR', 'print queue test failed queue=' . $queue . ' error=' . $msg );
|
||||
queue_test_result_page( $queue, 0, $msg, '' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $tmpdir = '/run/mars-nwe-webui';
|
||||
$tmpdir = '/tmp' if ! -d $tmpdir || ! -w $tmpdir;
|
||||
|
||||
my $tmp = $tmpdir . '/smart-test-print-' . $$ . '-' . int( rand( 1000000 ) ) . '.txt';
|
||||
|
||||
if( ! open( my $fh, '>', $tmp ) )
|
||||
{
|
||||
my $msg = 'Could not create test print file ' . $tmp . ': ' . $!;
|
||||
apply_log_line( 'ERROR', 'print queue test failed queue=' . $queue . ' error=' . $msg );
|
||||
queue_test_result_page( $queue, 0, $msg, '' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $ts = scalar( localtime( time() ) );
|
||||
|
||||
print( $fh "SMArT / MARS_NWE print queue test\n" );
|
||||
print( $fh "Server: $server\n" );
|
||||
print( $fh "Queue: $queue\n" );
|
||||
print( $fh "Time: $ts\n" );
|
||||
print( $fh "\nIf you can read this, the NetWare print queue accepted a test job.\n" );
|
||||
|
||||
if( ! close( $fh ) )
|
||||
{
|
||||
my $msg = 'Could not close test print file ' . $tmp . ': ' . $!;
|
||||
unlink( $tmp );
|
||||
apply_log_line( 'ERROR', 'print queue test failed queue=' . $queue . ' error=' . $msg );
|
||||
queue_test_result_page( $queue, 0, $msg, '' );
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $cmd = join( ' ',
|
||||
apply_shell_quote( $nprint ),
|
||||
'-S', apply_shell_quote( $server ),
|
||||
'-q', apply_shell_quote( $queue ),
|
||||
'-d', apply_shell_quote( 'SMArT test print' ),
|
||||
apply_shell_quote( $tmp )
|
||||
);
|
||||
|
||||
apply_log_line( 'INFO', 'print queue test command: ' . $cmd );
|
||||
|
||||
my $output = `$cmd 2>&1`;
|
||||
my $rc = $?;
|
||||
|
||||
unlink( $tmp );
|
||||
|
||||
$output = '' unless defined( $output );
|
||||
$output =~ s/\r//g;
|
||||
|
||||
if( $rc != 0 )
|
||||
{
|
||||
my $exit = $rc >> 8;
|
||||
apply_log_line( 'ERROR', 'print queue test failed rc=' . $exit . ' queue=' . $queue . ' output=' . $output );
|
||||
queue_test_result_page( $queue, 0, 'nprint returned an error.', $output );
|
||||
return 0;
|
||||
}
|
||||
|
||||
apply_log_line( 'INFO', 'print queue test ok queue=' . $queue . ( $output ne '' ? ' output=' . $output : '' ) );
|
||||
queue_test_result_page( $queue, 1, 'Test job was submitted with nprint.', $output );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
sub queue_config_line( $$$ )
|
||||
{
|
||||
my( $name, $spool, $command ) = @_;
|
||||
|
||||
$name = normalize_queue_name( $name );
|
||||
$spool = '' unless defined( $spool );
|
||||
$command = '' unless defined( $command );
|
||||
|
||||
$spool =~ s/^\s+//;
|
||||
$spool =~ s/\s+$//;
|
||||
$command =~ s/^\s+//;
|
||||
$command =~ s/\s+$//;
|
||||
|
||||
return '21 ' . $name . ' ' . $spool . ' ' . $command;
|
||||
}
|
||||
|
||||
sub queue_exists_in_bindery( $$ )
|
||||
{
|
||||
my( $server, $name ) = @_;
|
||||
|
||||
$name = normalize_queue_name( $name );
|
||||
return 0 if $name eq '';
|
||||
|
||||
my @queues = split( "\n", `nwbols -t 3 -S $server 2>/dev/null` );
|
||||
|
||||
foreach my $q ( @queues )
|
||||
{
|
||||
my @c = split( ' ', $q );
|
||||
return 1 if defined( $c[0] ) && uc( $c[0] ) eq uc( $name );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sub putp()
|
||||
{
|
||||
$cc =~ s/.*\?//;
|
||||
|
||||
@@ -122,6 +122,49 @@ sub delconfigline( $ )
|
||||
@conf = grep( !/^$_[0] /i, grep( !/^$_[0]$/i, @conf ) );
|
||||
}
|
||||
|
||||
sub queue_config_name_from_line( $ )
|
||||
{
|
||||
my $line = $_[0];
|
||||
|
||||
$line = '' unless defined( $line );
|
||||
$line =~ s/[\r\n]//g;
|
||||
$line =~ s/#.*//;
|
||||
$line =~ s/^\s*21\s+//i;
|
||||
$line =~ s/^\s+//;
|
||||
$line =~ s/\s+$//;
|
||||
|
||||
return ( split( /\s+/, $line, 2 ) )[0];
|
||||
}
|
||||
|
||||
sub delconfigqueue( $ )
|
||||
{
|
||||
my $name = $_[0];
|
||||
my $conf_before = scalar( @conf );
|
||||
my $raw_before = scalar( @rawconf );
|
||||
|
||||
$name = '' unless defined( $name );
|
||||
$name =~ s/^\s+//;
|
||||
$name =~ s/\s+$//;
|
||||
$name = uc( $name );
|
||||
|
||||
return( 0, 0 ) if $name eq '';
|
||||
|
||||
@conf = grep {
|
||||
my $qname = queue_config_name_from_line( $_ );
|
||||
!( $_ =~ /^\s*21(?:\s|$)/i && uc( $qname ) eq $name )
|
||||
} @conf;
|
||||
|
||||
@rawconf = grep {
|
||||
my $raw = $_;
|
||||
my $qname = queue_config_name_from_line( $raw );
|
||||
!( $raw =~ /^\s*21(?:\s|$)/i && uc( $qname ) eq $name )
|
||||
} @rawconf;
|
||||
|
||||
return( $conf_before - scalar( @conf ), $raw_before - scalar( @rawconf ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub normalize_line( $ )
|
||||
{
|
||||
my $x = $_[0];
|
||||
@@ -207,12 +250,17 @@ sub writeconfig_compact()
|
||||
|
||||
sub writeconfig_markers()
|
||||
{
|
||||
my( %secmap, %emitted );
|
||||
my( $line, $active_key, $inside_active );
|
||||
my( %secmap, %emitted, %managed );
|
||||
my( $line, $active_key, $inside_active, $sec, $key );
|
||||
|
||||
%secmap = build_marker_map();
|
||||
$inside_active = '';
|
||||
|
||||
foreach $key ( keys( %secmap ) )
|
||||
{
|
||||
$managed{$key} = 1;
|
||||
}
|
||||
|
||||
open( CONF, '>' . $mars_config ) or die "Could not write $mars_config: $!";
|
||||
|
||||
foreach $line ( @rawconf )
|
||||
@@ -249,9 +297,40 @@ sub writeconfig_markers()
|
||||
next;
|
||||
}
|
||||
|
||||
$sec = section_of_line( $line );
|
||||
if( $sec ne '' )
|
||||
{
|
||||
$key = grouped_section_key( $sec );
|
||||
|
||||
if( $managed{$key} )
|
||||
{
|
||||
# This section was changed in @conf. Do not write the stale
|
||||
# raw line again from @rawconf. If the section has no ACTIVE
|
||||
# marker, it is emitted once after the raw file has been copied.
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
print CONF $line;
|
||||
}
|
||||
|
||||
foreach $key ( sort {
|
||||
my $aa = $a; my $bb = $b;
|
||||
$aa =~ s/-.*//; $bb =~ s/-.*//;
|
||||
$aa <=> $bb
|
||||
} keys( %secmap ) )
|
||||
{
|
||||
next if $emitted{$key};
|
||||
|
||||
print CONF "\n";
|
||||
foreach my $entry ( @{ $secmap{$key} } )
|
||||
{
|
||||
print CONF $entry . "\n";
|
||||
}
|
||||
|
||||
$emitted{$key} = 1;
|
||||
}
|
||||
|
||||
close( CONF );
|
||||
}
|
||||
|
||||
|
||||
89
settings.pl
89
settings.pl
@@ -327,6 +327,51 @@ sub sanitize_cups_printer_name( $ )
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub queue_config_fields( $ )
|
||||
{
|
||||
my $line = $_[0];
|
||||
|
||||
$line = '' unless defined( $line );
|
||||
$line =~ s/^\s*21\s+//i;
|
||||
$line =~ s/^\s+//;
|
||||
$line =~ s/\s+$//;
|
||||
|
||||
my( $name, $spool, $cmd ) = split( /\s+/, $line, 3 );
|
||||
|
||||
$name = '' unless defined( $name );
|
||||
$spool = '' unless defined( $spool );
|
||||
$cmd = '' unless defined( $cmd );
|
||||
|
||||
return( $name, $spool, $cmd );
|
||||
}
|
||||
|
||||
sub queue_config_by_name( $ )
|
||||
{
|
||||
my $wanted = uc( $_[0] );
|
||||
|
||||
foreach my $line ( getconfig( 21 ) )
|
||||
{
|
||||
my( $name, $spool, $cmd ) = queue_config_fields( $line );
|
||||
return( $spool, $cmd ) if uc( $name ) eq $wanted;
|
||||
}
|
||||
|
||||
return( '', '' );
|
||||
}
|
||||
|
||||
sub queue_names_from_config()
|
||||
{
|
||||
my @names = ();
|
||||
|
||||
foreach my $line ( getconfig( 21 ) )
|
||||
{
|
||||
my( $name, $spool, $cmd ) = queue_config_fields( $line );
|
||||
push( @names, $name ) if $name ne '';
|
||||
}
|
||||
|
||||
return @names;
|
||||
}
|
||||
|
||||
|
||||
sub cups_queue_name( $ )
|
||||
{
|
||||
my $s = sanitize_cups_printer_name( $_[0] );
|
||||
@@ -3409,17 +3454,37 @@ $settings_nav_bar
|
||||
</TD>
|
||||
</TR>
|
||||
EOF
|
||||
my %queue_seen = ();
|
||||
my @queue_names = ();
|
||||
|
||||
@c = sort( split( "\n", `nwbols -t 3 -S $server` ) );
|
||||
foreach $c ( @c )
|
||||
{
|
||||
my @c = split( ' ', $c );
|
||||
next if ! defined( $c[0] ) || $c[0] eq '';
|
||||
next if $queue_seen{uc( $c[0] )};
|
||||
push( @queue_names, $c[0] );
|
||||
$queue_seen{uc( $c[0] )} = 1;
|
||||
}
|
||||
|
||||
foreach my $q ( queue_names_from_config() )
|
||||
{
|
||||
next if $queue_seen{uc( $q )};
|
||||
push( @queue_names, $q );
|
||||
$queue_seen{uc( $q )} = 1;
|
||||
}
|
||||
|
||||
foreach my $q ( sort( @queue_names ) )
|
||||
{
|
||||
print <<EOF;
|
||||
<TR BGCOLOR="#fbf7f1">
|
||||
<TD>
|
||||
<A HREF="/settings/queues/$c[0]">$c[0]</A>
|
||||
<A HREF="/settings/queues/$q">$q</A>
|
||||
</TD>
|
||||
<TD ALIGN=RIGHT>
|
||||
<A HREF="/apply/queues/$c[0]" onclick="return confirm('Delete queue $c[0]?')">Delete</A><BR>
|
||||
<A HREF="/apply/queues/$q?test_print=1">Test print</A>
|
||||
|
|
||||
<A HREF="/apply/queues/$q" onclick="return confirm('Delete queue $q?')">Delete</A><BR>
|
||||
</TD>
|
||||
</TR>
|
||||
EOF
|
||||
@@ -3448,6 +3513,10 @@ EOF
|
||||
{
|
||||
$unix_print = read_property_string( $c[2], 3, 'Q_UNIX_PRINT' );
|
||||
$spool_dir = read_property_string( $c[2], 3, 'Q_DIRECTORY' );
|
||||
|
||||
my( $cfg_spool, $cfg_cmd ) = queue_config_by_name( $c[2] );
|
||||
$spool_dir = $cfg_spool if ( ! defined( $spool_dir ) || $spool_dir eq '' ) && $cfg_spool ne '';
|
||||
$unix_print = $cfg_cmd if ( ! defined( $unix_print ) || $unix_print eq '' ) && $cfg_cmd ne '';
|
||||
}
|
||||
elsif( $selected_cups_printer ne '' )
|
||||
{
|
||||
@@ -3576,6 +3645,22 @@ EOF
|
||||
<INPUT NAME="spool_dir" TYPE=TEXT SIZE=32 VALUE="$spool_dir"><BR>
|
||||
</TD>
|
||||
</TR>
|
||||
EOF
|
||||
if( $c[2] ne 'add_new' )
|
||||
{
|
||||
print <<EOF;
|
||||
<TR BGCOLOR="#fbf7f1">
|
||||
<TD>
|
||||
<B>Queue test:</B><BR>
|
||||
<SMALL>Submit a small test job with nprint.</SMALL>
|
||||
</TD>
|
||||
<TD ALIGN=RIGHT>
|
||||
<A HREF="/apply/queues/$c[2]?test_print=1">Test print queue</A><BR>
|
||||
</TD>
|
||||
</TR>
|
||||
EOF
|
||||
}
|
||||
print <<EOF;
|
||||
<TR BGCOLOR="#d7c0a0">
|
||||
<TD>
|
||||
<INPUT TYPE=SUBMIT VALUE="OK">
|
||||
|
||||
@@ -62,13 +62,9 @@ $smart_static_dir = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/static';
|
||||
$smart_log_path = '@MARS_NWE_LOG_DIR@/smart.log';
|
||||
|
||||
# Path to the PAM-based login helper used for SMArT authentication.
|
||||
# The helper reads this smart.conf file for logging settings and the required
|
||||
# admin group. Passwords are never written to the log.
|
||||
$smart_check_login = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/check_login';
|
||||
|
||||
# Path to the native Unix-user enumeration helper used by the user editor.
|
||||
# The helper writes diagnostics to $smart_log_path and keeps the user list on
|
||||
# stdout for the WebUI.
|
||||
$smart_userlist_path = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart_userlist';
|
||||
|
||||
# Unix group allowed to log in to the SMArT/nwwebui admin interface.
|
||||
@@ -80,7 +76,7 @@ $smart_userlist_path = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart_userlist';
|
||||
# existing installations: the root user is allowed because its primary Unix
|
||||
# group is normally also "root". Do not add normal users to the "root" group.
|
||||
#
|
||||
# For delegated administration, build with a dedicated group, for example:
|
||||
# For delegated administration, use a dedicated group instead, for example:
|
||||
#
|
||||
# cmake -DMARS_NWE_SMART_ADMIN_GROUP=nwadmin ...
|
||||
# groupadd nwadmin
|
||||
@@ -90,6 +86,8 @@ $smart_userlist_path = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart_userlist';
|
||||
# login session before NSS/PAM reports the new membership.
|
||||
$smart_admin_group = '@MARS_NWE_SMART_ADMIN_GROUP@';
|
||||
|
||||
|
||||
|
||||
# Path to the SMArT service-control helper.
|
||||
$smart_control_path = '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/control';
|
||||
|
||||
@@ -132,9 +130,6 @@ $nw_bind_ip = '0.0.0.0';
|
||||
|
||||
# Log level used by the native nwwebui frontend service.
|
||||
#
|
||||
# This controls the C-based HTTP/HTTPS frontend process and is written to
|
||||
# $nw_log_file. It is separate from $smart_debug_level below.
|
||||
#
|
||||
# Supported values, from quiet to verbose:
|
||||
#
|
||||
# error - only real errors
|
||||
@@ -187,13 +182,14 @@ $nw_key_file = '@MARS_NWE_INSTALL_FULL_CONFDIR@/server.key';
|
||||
$smart_session_dir = '/run/mars-nwe-webui';
|
||||
$smart_session_timeout = 3600;
|
||||
|
||||
# SMArT Perl/helper logging verbosity.
|
||||
|
||||
# SMArT Perl logging verbosity.
|
||||
#
|
||||
# This controls log messages written by the Perl CGI-style helper scripts and
|
||||
# native SMArT helper tools such as apply.pl, check_login and smart_userlist.
|
||||
# These messages are written to:
|
||||
# This controls log messages written by the Perl CGI-style helper scripts
|
||||
# such as apply.pl. The messages are written to the SMArT log file configured
|
||||
# for the WebUI, normally:
|
||||
#
|
||||
# $smart_log_path
|
||||
# /var/log/mars_nwe/smart.log
|
||||
#
|
||||
# Supported values, from quiet to verbose:
|
||||
#
|
||||
@@ -207,13 +203,11 @@ $smart_session_timeout = 3600;
|
||||
#
|
||||
# $smart_debug_level = 'info';
|
||||
#
|
||||
# Use 'debug' or 'trace' only while troubleshooting a concrete problem. Trace
|
||||
# logging may include submitted bindery payload data and can produce a lot of
|
||||
# output. After debugging, switch back to 'info'.
|
||||
$smart_debug_level = 'info';
|
||||
#
|
||||
# Use 'trace' only while debugging a concrete problem. Trace logging may
|
||||
# include submitted bindery payload data and can produce a lot of log output.
|
||||
# After debugging, switch back to 'info'.
|
||||
$smart_debug_level = 'info';
|
||||
|
||||
|
||||
# ncpfs nprint executable used by the queue test action.
|
||||
$smart_nprint_path = '/usr/bin/nprint';
|
||||
|
||||
Reference in New Issue
Block a user