# # SMArT # # Handle /settings/ requests # # Copyright 2001 Wilmer van der Gaast (lintux@lintux.cx) # # # 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 # # sub html_escape( $ ) { my $s = $_[0]; $s = '' unless defined $s; $s =~ s/&/&/g; $s =~ s//>/g; $s =~ s/"/"/g; return $s; } sub settings_nav_bar() { return <<'EOF_NAV';
Back Main menu Logout
EOF_NAV } sub delete_confirm_attr( $ ) { my $what = html_escape( $_[0] ); return ' onclick="return confirm(\'Delete ' . $what . '?\')"'; } sub advanced_link_row( $$ ) { my( $href, $label ) = @_; return qq|\t\n\t\t$label\n\t\n|; } sub advanced_category() { my $cat = $c[2]; $cat = 'all' if ! defined( $cat ) || $cat eq ''; if( $cat =~ /^(devices|security|users|queues|configh|stations|network|all)$/ ) { return $cat; } return 'all'; } sub advanced_section_visible( $$ ) { my( $cat, $section ) = @_; return 1 if $cat eq 'all'; return 1 if $cat eq 'devices' && $section =~ /^(5)$/; return 1 if $cat eq 'security' && $section =~ /^(8)$/; return 1 if $cat eq 'users' && $section =~ /^(17)$/; return 1 if $cat eq 'queues' && $section =~ /^(18|22)$/; return 1 if $cat eq 'configh' && $section =~ /^(50|80)$/; return 1 if $cat eq 'stations' && $section =~ /^(400|401|402)$/; return 1 if $cat eq 'network' && $section =~ /^(310)$/; return 0; } sub advanced_title( $ ) { my $cat = $_[0]; return 'Advanced device settings' if $cat eq 'devices'; return 'Advanced security settings' if $cat eq 'security'; return 'Advanced user / bindery settings' if $cat eq 'users'; return 'Advanced print queue settings' if $cat eq 'queues'; return 'Advanced precompiled / path settings' if $cat eq 'configh'; return 'Advanced station access settings' if $cat eq 'stations'; return 'Advanced network watchdog settings' if $cat eq 'network'; return 'Advanced settings'; } sub advanced_hidden_category_input( $ ) { my $cat = $_[0]; return '' if ! defined( $cat ) || $cat eq '' || $cat eq 'all'; return '' . "\n"; } sub cfg_int( $ ) { my $v = $_[0]; $v = '' unless defined $v; $v =~ s/^\s+//; $v =~ s/\s+$//; return 0 if $v eq ''; return oct( $v ) if $v =~ /^0x[0-9a-f]+$/i; return int( $v ); } sub cfg_checked( $$ ) { my( $value, $mask ) = @_; return ( cfg_int( $value ) & $mask ) ? ' CHECKED' : ''; } sub html_selected( $$ ) { return ( defined $_[0] && defined $_[1] && $_[0] eq $_[1] ) ? ' SELECTED' : ''; } sub option_012( $ ) { my $v = $_[0]; $v = '0' unless defined $v && $v ne ''; return '' . "\n" . '' . "\n" . '' . "\n"; } sub getconfiglines_without_section( $ ) { my @lines = getconfig( $_[0] ); foreach my $line ( @lines ) { $line =~ s/^\s*$_[0]\s+//; } return @lines; } $settings_nav_bar = settings_nav_bar(); sub kernel_network_interfaces() { my %interfaces = (); if( opendir( my $dh, '/sys/class/net' ) ) { foreach my $ifname ( readdir( $dh ) ) { next if $ifname =~ /^\./; next if $ifname =~ /[^-_\.A-Za-z0-9]/; $interfaces{$ifname} = 1; } closedir( $dh ); } return %interfaces; } sub ipx_enabled_interfaces() { my %ipx_interfaces = (); # Modern Linux IPX procfs format: # Network Node_Address Primary Device Frame_Type # AC100B98 000000000001 Yes Internal None # 00000022 508140F6AC45 No enp46s0u1u3u3 802.2 if( open( my $fh, '<', '/proc/net/ipx/interface' ) ) { while( my $line = <$fh> ) { chomp( $line ); $line =~ s/^\s+//; $line =~ s/\s+$//; next if $line eq ''; next if $line =~ /^Network\s+Node_Address\s+Primary\s+Device\s+Frame_Type/i; my @fields = split( /\s+/, $line ); # Device is the fourth column. Do not scan all tokens, otherwise # Network/Node/Frame_Type values can accidentally be treated as names. next if scalar( @fields ) < 5; my $dev = $fields[3]; next if ! defined( $dev ); next if $dev eq ''; next if lc( $dev ) eq 'internal'; next if $dev =~ /[^-_\.A-Za-z0-9]/; # Only show real Linux network interfaces. next if ! -e '/sys/class/net/' . $dev; $ipx_interfaces{$dev} = 1; } close( $fh ); } # Fallback for older distributions/tools, if present. This parser is kept # deliberately conservative and still verifies /sys/class/net/. if( open( my $fh, '<', '/proc/net/ipx_interfaces' ) ) { while( my $line = <$fh> ) { chomp( $line ); $line =~ s/^\s+//; $line =~ s/\s+$//; next if $line eq ''; next if $line =~ /^(Network|Net|Address|Node|Interface|Device)\b/i; foreach my $dev ( split( /\s+/, $line ) ) { next if ! defined( $dev ); next if $dev eq ''; next if lc( $dev ) eq 'internal'; next if $dev =~ /[^-_\.A-Za-z0-9]/; next if ! -e '/sys/class/net/' . $dev; $ipx_interfaces{$dev} = 1; } } close( $fh ); } return sort keys %ipx_interfaces; } sub network_interface_options( $ ) { my $current = $_[0]; my @interfaces = (); my %seen = (); my $html = ''; $current = '' unless defined $current; # Only show interfaces where IPX is currently active. The current value is # still preserved below, so an existing config entry is not lost if the # interface is temporarily down or IPX is not loaded at display time. foreach my $ifname ( ipx_enabled_interfaces() ) { next if $seen{$ifname}; push( @interfaces, $ifname ); $seen{$ifname} = 1; } # Keep special/manual values usable even if they are not real kernel interfaces. foreach my $ifname ( '*', 'auto', $current ) { next if !defined( $ifname ) || $ifname eq ''; next if $seen{$ifname}; push( @interfaces, $ifname ); $seen{$ifname} = 1; } foreach my $ifname ( @interfaces ) { my $selected = ( $ifname eq $current ) ? ' SELECTED' : ''; my $label = $ifname; $label = '* (all IPX interfaces)' if $ifname eq '*'; $label = 'auto' if $ifname eq 'auto'; $html .= '\t\t\t\t\n'; } return $html; } sub url_escape( $ ) { my $s = $_[0]; $s = '' unless defined $s; $s =~ s/([^A-Za-z0-9_\.\-])/sprintf("%%%02X", ord($1))/eg; return $s; } sub js_escape( $ ) { my $s = $_[0]; $s = '' unless defined $s; $s =~ s/\\/\\\\/g; $s =~ s/'/\\'/g; $s =~ s/\r/\\r/g; $s =~ s/\n/\\n/g; return $s; } sub smart_find_executable( @ ) { foreach my $p ( @_ ) { next if ! defined( $p ) || $p eq ''; return $p if -x $p; } return ''; } sub sanitize_cups_printer_name( $ ) { my $s = $_[0]; $s = '' unless defined $s; $s =~ s/[^-_\.A-Za-z0-9]//g; 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] ); $s = uc( $s ); $s =~ s/[^A-Z0-9_\-]/_/g; $s = 'PRINTQ' if $s eq ''; $s = substr( $s, 0, 47 ); return $s; } sub cups_print_command( $ ) { my $printer = sanitize_cups_printer_name( $_[0] ); my $template = $smart_cups_print_command_template; $template = '/usr/bin/lp -d %p -' unless defined( $template ) && $template ne ''; $template =~ s/%p/$printer/g; return $template; } sub cups_add_printer( $$$ ) { my( $printers, $seen, $name ) = @_; return if ! defined( $name ); $name =~ s/^\s+//; $name =~ s/\s+$//; return if $name eq ''; return if $name =~ /[^-_\.A-Za-z0-9]/; my $queue = cups_queue_name( $name ); my $name_key = lc( $name ); my $queue_key = lc( $queue ); # Deduplicate by both the original CUPS name and the generated MARS_NWE # queue name. This avoids duplicates when the same printer is discovered # through lpstat -e and a localized lpstat -p fallback. return if $seen->{'name:' . $name_key}; return if $seen->{'queue:' . $queue_key}; push( @$printers, { name => $name, queue => $queue, command => cups_print_command( $name ), } ); $seen->{'name:' . $name_key} = 1; $seen->{'queue:' . $queue_key} = 1; } sub cups_printers() { my @printers = (); my %seen = (); return @printers if ! defined( $smart_cups_enable ) || !$smart_cups_enable; return @printers if ! defined( $smart_cups_lpstat_path ) || $smart_cups_lpstat_path eq ''; return @printers if ! -x $smart_cups_lpstat_path; # Prefer "lpstat -e": it prints only destination names and is language # independent. If it returns at least one printer, do not run fallback # parsers, because some CUPS versions/locales can expose aliases there. if( open( my $fh, '-|', $smart_cups_lpstat_path, '-e' ) ) { while( my $line = <$fh> ) { chomp( $line ); $line =~ s/^\s+//; $line =~ s/\s+$//; next if $line eq ''; next if $line =~ /[\r\n]/; cups_add_printer( \@printers, \%seen, $line ); } close( $fh ); } return @printers if scalar( @printers ) > 0; # Fallback: "lpstat -v" is also mostly language independent because the # destination name follows "for :" on many systems. if( open( my $fh, '-|', $smart_cups_lpstat_path, '-v' ) ) { while( my $line = <$fh> ) { chomp( $line ); if( $line =~ /\bfor\s+([^:\s]+)\s*:/i ) { cups_add_printer( \@printers, \%seen, $1 ); } } close( $fh ); } return @printers if scalar( @printers ) > 0; # Last fallback: parse localized "lpstat -p" output. English starts with # "printer ", German starts with "Drucker ". if( open( my $fh, '-|', $smart_cups_lpstat_path, '-p' ) ) { while( my $line = <$fh> ) { chomp( $line ); if( $line =~ /^(?:printer|Drucker)\s+(\S+)/i ) { cups_add_printer( \@printers, \%seen, $1 ); } } close( $fh ); } return @printers; } sub cups_import_rows() { my $html = ''; my @printers = cups_printers(); if( scalar( @printers ) == 0 ) { return qq|\t\n\t\tCUPS printers detected on host\n\t\n\t\n\t\tCUPS support is enabled, but no printers were returned by lpstat.\n\t\n|; } $html .= qq|\t\n\t\tCUPS printers detected on host\n\t\n|; foreach my $printer ( @printers ) { my $name = ref( $printer ) eq 'HASH' ? $printer->{name} : $printer; my $queue = ref( $printer ) eq 'HASH' ? $printer->{queue} : cups_queue_name( $printer ); my $cmd = ref( $printer ) eq 'HASH' ? $printer->{command} : cups_print_command( $printer ); my $href = '/settings/queues/add_new?cups_printer=' . url_escape( $name ); $html .= "\t\n"; $html .= "\t\t" . html_escape( $name ) . "
Queue: " . html_escape( $queue ) . "   Command: " . html_escape( $cmd ) . "\n"; $html .= "\t\tAdd as print queue\n"; $html .= "\t\n"; } return $html; } sub cups_select_html( $ ) { my $current = sanitize_cups_printer_name( $_[0] ); my @printers = cups_printers(); my $html = ''; my $js = ''; return ( '', '' ) if scalar( @printers ) == 0; $html .= qq||; return ( $html, $js ); } sub ipx_interface_info( $ ) { my $want = $_[0]; my %info = (); return %info if ! defined( $want ) || $want eq ''; if( open( my $fh, '<', '/proc/net/ipx/interface' ) ) { while( my $line = <$fh> ) { chomp( $line ); $line =~ s/^\s+//; $line =~ s/\s+$//; next if $line eq ''; next if $line =~ /^Network\s+Node_Address\s+Primary\s+Device\s+Frame_Type/i; my @fields = split( /\s+/, $line ); next if scalar( @fields ) < 5; my $network = $fields[0]; my $dev = $fields[3]; my $frame = $fields[4]; next if ! defined( $dev ) || $dev ne $want; next if lc( $dev ) eq 'internal'; $info{network} = $network; $info{frame} = $frame; last; } close( $fh ); } return %info; } sub ipx_device_import_rows() { my $html = ''; my @ifaces = ipx_enabled_interfaces(); if( scalar( @ifaces ) == 0 ) { return qq|\t\n\t\tIPX interfaces detected on host\n\t\n\t\n\t\tNo active IPX interfaces were found in /proc/net/ipx/interface.\n\t\n|; } $html .= qq|\t\n\t\tIPX interfaces detected on host\n\t\n|; foreach my $iface ( @ifaces ) { my %info = ipx_interface_info( $iface ); my $net = $info{network}; my $frame = $info{frame}; my $delay = 1; $net = '0x0' if ! defined( $net ) || $net eq ''; $frame = '802.2' if ! defined( $frame ) || $frame eq '' || lc( $frame ) eq 'none'; my $href = '/settings/devices/add_new?ipx_iface=' . url_escape( $iface ); $html .= "\t\n"; $html .= "\t\t" . html_escape( $iface ) . "
Config line: 4 " . html_escape( $net ) . " " . html_escape( $iface ) . " " . html_escape( $frame ) . " " . html_escape( $delay ) . "\n"; $html .= "\t\tAdd as device\n"; $html .= "\t\n"; } return $html; } sub ipx_device_defaults_from_query() { my %defaults = (); $defaults{number} = ''; $defaults{interface} = ''; $defaults{frametype} = '802.2'; $defaults{delay} = 1; if( defined( $p{ipx_iface} ) && $p{ipx_iface} ne '' ) { my $iface = $p{ipx_iface}; $iface =~ s/[^-_\.A-Za-z0-9]//g; my %info = ipx_interface_info( $iface ); $defaults{interface} = $iface; $defaults{number} = defined( $info{network} ) && $info{network} ne '' ? $info{network} : '0x0'; $defaults{frametype} = defined( $info{frame} ) && $info{frame} ne '' && lc( $info{frame} ) ne 'none' ? $info{frame} : '802.2'; $defaults{delay} = 1; } return %defaults; } sub smart_bindery_values() { my( $bind_server, $bind_user, $bind_pass ) = ( '', '', '' ); if( open( my $fh, '<' . $smart_nwclient_path ) ) { my $line = <$fh>; close( $fh ); chomp( $line ) if defined( $line ); ( $bind_server, $bind_user, $bind_pass ) = split( '[/ ]', $line ) if defined( $line ); } $bind_server = '' unless defined( $bind_server ); $bind_user = '' unless defined( $bind_user ); $bind_pass = '' unless defined( $bind_pass ); return( $bind_server, $bind_user, $bind_pass ); } sub sync_server_hint_row( $$$$ ) { my( $checkbox_name, $current_name, $other_name, $direction ) = @_; $current_name = '' unless defined( $current_name ); $other_name = '' unless defined( $other_name ); my $msg = ''; if( $direction eq 'general_to_smart' ) { $msg = 'Also update the SMArT bindery server when saving. Current SMArT bindery server: '; $msg .= $other_name ne '' ? '' . html_escape( $other_name ) . '' : 'not set'; } else { $msg = 'Also update the MARS_NWE server name when saving. Current MARS_NWE server name: '; $msg .= $other_name ne '' ? '' . html_escape( $other_name ) . '' : 'not set'; } return qq|\t\n\t\tKeep server names in sync:
$msg\n\t\tYes \n\t\n|; } sub unix_user_import_rows() { my $html = ''; my @users = unix_userlist(); my %existing = (); my @candidates = (); foreach my $line ( getconfig( 13 ) ) { my @f = split( ' ', $line ); $existing{lc( $f[1] )} = 1 if defined( $f[1] ) && $f[1] ne ''; } foreach my $u ( @users ) { next if ! defined( $u->{name} ) || $u->{name} eq ''; next if defined( $u->{uid} ) && $u->{uid} < 1000; next if lc( $u->{name} ) eq 'nobody'; next if lc( $u->{name} ) eq 'root'; next if $existing{lc( $u->{name} )}; push( @candidates, $u ); } if( scalar( @candidates ) == 0 ) { return qq|\t\n\t\tUnix users detected on host\n\t\n\t\n\t\tNo additional local Unix users were found for import.\n\t\n|; } $html .= qq|\t\n\t\tUnix users detected on host\n\t\n|; foreach my $u ( @candidates ) { my $name = $u->{name}; my $uid = $u->{uid}; my $gecos = defined( $u->{gecos} ) ? $u->{gecos} : ''; $gecos =~ s/,.*$//; my $href = '/settings/users_import/' . url_escape( $name ); $html .= "\t\n"; $html .= "\t\t" . html_escape( $name ) . "
UID: " . html_escape( $uid ) . ""; $html .= "   " . html_escape( $gecos ) if $gecos ne ''; $html .= "\n"; $html .= "\t\tAdd as MARS_NWE user\n"; $html .= "\t\n"; } return $html; } sub unix_user_defaults_from_query() { my %defaults = (); $defaults{name} = ''; $defaults{unix_user} = ''; $defaults{fullname} = ''; my $want = ''; # The router puts imported users here after /settings/users_import/ # was normalized to /settings/users/add_new. if( defined( $p{unix_user} ) && $p{unix_user} ne '' ) { $want = $p{unix_user}; } # Compatibility for direct /settings/users_import/, before normalization. elsif( defined( $c[1] ) && $c[1] eq 'users_import' && defined( $c[2] ) && $c[2] ne '' ) { $want = $c[2]; } # Compatibility for /settings/users/add_new/. elsif( defined( $c[3] ) && $c[3] ne '' ) { $want = $c[3]; } if( $want ne '' ) { $want =~ s/[^-_\.A-Za-z0-9]//g; # Minimal import: use the Unix user parameter that reaches settings.pl. $defaults{unix_user} = $want; $defaults{name} = uc( $want ); $defaults{name} =~ s/[^-_\.A-Za-z0-9]//g; # Step 2: if no GECOS/fullname is available yet, use a friendly # fallback from the Unix account name. "mario" -> "Mario", # "mario_fetka" -> "Mario Fetka". my $full = $want; $full =~ s/[_\.\-]+/ /g; $full =~ s/\s+/ /g; $full =~ s/^\s+//; $full =~ s/\s+$//; $full = join( ' ', map { ucfirst( lc( $_ ) ) } split( / /, $full ) ); $defaults{fullname} = $full; } return %defaults; } sub selected_attr( $$ ) { my( $a, $b ) = @_; $a = '' unless defined( $a ); $b = '' unless defined( $b ); return $a eq $b ? ' SELECTED' : ''; } sub smart_group_checkbox_rows( $ ) { my $server = $_[0]; my $html = ''; my @groups = (); my $cmd = 'nwbols -t 2 -S ' . $server; @groups = sort( split( "\n", `$cmd` ) ); foreach my $g ( @groups ) { my @f = split( ' ', $g ); my $group = $f[0]; next if ! defined( $group ) || $group eq ''; next if $group =~ /[^-_\.A-Za-z0-9]/; $html .= html_escape( $group ) . '
' . "\n"; } if( $html eq '' ) { $html = 'No bindery groups found. Save the user first, then add groups later.
' . "\n"; } return $html; } sub volume_name_from_path( $ ) { my $path = $_[0]; $path = '' unless defined( $path ); $path =~ s#/*$##; $path =~ s#^.*/##; $path = 'ROOT' if $path eq ''; $path = uc( $path ); $path =~ s/[^A-Z0-9_\-]/_/g; $path = substr( $path, 0, 15 ); $path = 'VOLUME' if $path eq ''; return $path; } sub volume_mountpoint_is_useful( $$ ) { my( $mountpoint, $fstype ) = @_; return 0 if ! defined( $mountpoint ) || $mountpoint eq ''; return 0 if $mountpoint eq '/'; # Pseudo and system trees are not useful as NetWare volumes. return 0 if $mountpoint =~ m#^/(proc|sys|dev|run)(/|$)#; return 0 if $mountpoint =~ m#^/(tmp|var/tmp)(/|$)#; return 0 if $mountpoint =~ m#^/boot(/|$)#; return 0 if $mountpoint =~ m#^/(etc|usr|bin|sbin|lib|lib64)(/|$)#; return 0 if $mountpoint =~ m#^/system(/|$)#; # Do not require -d here. The webui service may have /home masked by # systemd hardening, while the real MARS_NWE service can still use it. return 1; } sub local_mountpoints() { my @mounts = (); my %seen = (); my $add_mount = sub { my( $mountpoint, $fstype, $source ) = @_; $mountpoint = '' unless defined( $mountpoint ); $fstype = '' unless defined( $fstype ); $source = '' unless defined( $source ); $mountpoint =~ s#\\040# #g; $mountpoint =~ s#\\011#\t#g; $mountpoint =~ s#\\012#\n#g; $mountpoint =~ s#\\134#\\#g; return if $mountpoint eq ''; return if $mountpoint =~ /[\r\n\t]/; return if $mountpoint =~ /'/; return if $seen{$mountpoint}; return if $fstype =~ /^(proc|sysfs|devtmpfs|devpts|tmpfs|securityfs|cgroup|cgroup2|pstore|bpf|tracefs|debugfs|configfs|fusectl|mqueue|hugetlbfs|autofs|overlay|squashfs|portal|binfmt_misc|efivarfs)$/; return if ! volume_mountpoint_is_useful( $mountpoint, $fstype ); push( @mounts, { path => $mountpoint, fstype => $fstype ne '' ? $fstype : 'mount', source => $source ne '' ? $source : 'mount', name => volume_name_from_path( $mountpoint ), } ); $seen{$mountpoint} = 1; }; foreach my $file ( '/proc/1/mountinfo', '/proc/self/mountinfo' ) { next if ! open( my $fh, '<', $file ); while( my $line = <$fh> ) { chomp( $line ); my @parts = split( / - /, $line, 2 ); next if scalar( @parts ) != 2; my @left = split( /\s+/, $parts[0] ); my @right = split( /\s+/, $parts[1] ); next if scalar( @left ) < 5; next if scalar( @right ) < 3; $add_mount->( $left[4], $right[0], $right[1] ); } close( $fh ); } if( open( my $fh, '<', '/proc/mounts' ) ) { while( my $line = <$fh> ) { chomp( $line ); my( $source, $mountpoint, $fstype ) = split( /\s+/, $line ); $add_mount->( $mountpoint, $fstype, $source ); } close( $fh ); } @mounts = sort { $a->{path} cmp $b->{path} } @mounts; return @mounts; } sub volume_mount_import_rows() { my $html = ''; my @mounts = local_mountpoints(); my %existing = (); foreach my $line ( getconfig( 1 ) ) { my @f = split( ' ', $line ); $existing{lc( $f[1] )} = 1 if defined( $f[1] ) && $f[1] ne ''; $existing{'path:' . $f[2]} = 1 if defined( $f[2] ) && $f[2] ne ''; } if( scalar( @mounts ) == 0 ) { return qq|\t\n\t\tLocal mountpoints detected on host\n\t\n\t\n\t\tNo suitable local mountpoints were found.\n\t\n|; } $html .= qq|\t\n\t\tLocal mountpoints detected on host\n\t\n|; foreach my $m ( @mounts ) { my $name = $m->{name}; my $path = $m->{path}; my $fstype = $m->{fstype}; my $source = $m->{source}; my $exists = $existing{lc( $name )} || $existing{'path:' . $path}; $html .= "\t\n"; $html .= "\t\t" . html_escape( $path ) . "
Volume: " . html_escape( $name ) . "   Type: " . html_escape( $fstype ) . "   Source: " . html_escape( $source ) . "\n"; if( $exists ) { $html .= "\t\talready configured\n"; } else { my $href = '/settings/volumes/add_new?mount_path=' . url_escape( $path ) . '&path=' . url_escape( $path ); $html .= "\t\tAdd as volume\n"; } $html .= "\t\n"; } return $html; } sub volume_mount_defaults_from_query() { my %defaults = (); $defaults{name} = ''; $defaults{path} = ''; my $path = ''; if( defined( $p{mount_path} ) && $p{mount_path} ne '' ) { $path = $p{mount_path}; } elsif( defined( $p{path} ) && $p{path} ne '' ) { $path = $p{path}; } if( $path ne '' ) { $path =~ s/[\r\n\t']//g; $path =~ s#/{2,}#/#g; $path =~ s#/$## if length( $path ) > 1; if( volume_mountpoint_is_useful( $path, 'mount' ) ) { $defaults{path} = $path; $defaults{name} = volume_name_from_path( $path ); } } return %defaults; } sub mars_nwe_service_active() { my $service = defined( $mars_nwe_service ) && $mars_nwe_service ne '' ? $mars_nwe_service : 'mars-nwe-serv.service'; my $systemctl = defined( $smart_systemctl_path ) && $smart_systemctl_path ne '' ? $smart_systemctl_path : '/usr/bin/systemctl'; return 0 if ! -x $systemctl; my $rc = system( $systemctl, 'is-active', '--quiet', $service ); return $rc == 0 ? 1 : 0; } sub mars_nwe_service_guard_rows( $ ) { my $what = $_[0]; $what = 'this section' unless defined( $what ) && $what ne ''; return '' if mars_nwe_service_active(); return qq|\t\n| . qq|\t\tMARS_NWE service is not running.
\n| . qq|\t\tStart mars-nwe-serv.service before managing | . html_escape( $what ) . qq|. | . qq|Open service page\n| . qq|\t\n|; } sub settings_message_html() { return '' if ! defined( $p{msg} ) || $p{msg} eq ''; my $msg = $p{msg}; $msg =~ s/\+/ /g; return qq|
| . html_escape( $msg ) . qq|
\n|; } sub user_group_checkbox_rows( $ ) { my $user = $_[0]; my $html = ''; my %selected = (); $user = '' unless defined( $user ); if( $user ne '' && $user ne 'add_new' ) { my $server = get_server(); my $groups = `nwbpvalues -S $server -t 1 -o $user -p "GROUPS_I'M_IN" 2>/dev/null`; foreach my $line ( split( /\n/, $groups ) ) { if( $line =~ /([A-Za-z0-9_\-]+)/ ) { $selected{uc( $1 )} = 1; } } } my @groups = getconfig( 12 ); my @names = (); foreach my $g ( @groups ) { my @f = split( /\s+/, $g ); next if ! defined( $f[1] ) || $f[1] eq ''; push( @names, uc( $f[1] ) ); } push( @names, 'EVERYONE' ) if ! grep { $_ eq 'EVERYONE' } @names; @names = sort @names; foreach my $g ( @names ) { my $checked = ( $selected{$g} || ( $g eq 'EVERYONE' && $user eq 'add_new' ) ) ? ' CHECKED' : ''; $html .= qq|\n|; } return $html; } sub current_bindery_unix_user( $ ) { # Do not query the live bindery while rendering the edit form. # Some nwbpvalues versions can block or print unexpected data here. # Existing UNIX_USER stays unchanged unless the admin selects a value. return ''; } sub smart_unix_users_for_select() { my @users = (); my %seen = (); my $helper = defined( $smart_userlist_path ) && $smart_userlist_path ne '' ? $smart_userlist_path : '@MARS_NWE_INSTALL_FULL_LIBEXECDIR@/smart_userlist'; my $conf_path = defined( $smart_conf_path ) && $smart_conf_path ne '' ? $smart_conf_path : '@MARS_NWE_INSTALL_FULL_CONFDIR@/smart.conf'; if( -x $helper && open( my $fh, '-|', $helper, '--config', $conf_path ) ) { while( my $line = <$fh> ) { chomp( $line ); my( $name, $uid, $gid, $gecos, $home, $shell ) = split( /\t/, $line ); next if ! defined( $name ) || $name eq ''; next if $seen{$name}; push( @users, { name => $name, uid => defined( $uid ) ? $uid : '', fullname => defined( $gecos ) ? $gecos : '', } ); $seen{$name} = 1; } close( $fh ); } # Fallback: getent passwd. This is only used when smart_userlist is not # available or returned nothing. if( scalar( @users ) == 0 && open( my $fh, '-|', 'getent', 'passwd' ) ) { while( my $line = <$fh> ) { chomp( $line ); my( $name, undef, $uid, $gid, $gecos, $home, $shell ) = split( /:/, $line ); next if ! defined( $name ) || $name eq ''; next if defined( $uid ) && $uid ne '' && $uid < 1000; next if defined( $shell ) && $shell =~ m#/(false|nologin)$#; next if $seen{$name}; push( @users, { name => $name, uid => defined( $uid ) ? $uid : '', fullname => defined( $gecos ) ? $gecos : '', } ); $seen{$name} = 1; } close( $fh ); } @users = sort { $a->{name} cmp $b->{name} } @users; return @users; } sub unix_user_select_options( $ ) { my $selected = $_[0]; my $html = ''; $selected = '' unless defined( $selected ); foreach my $u ( smart_unix_users_for_select() ) { next if ! defined( $u ) || ref( $u ) ne 'HASH'; my $name = $u->{name}; next if ! defined( $name ) || $name eq ''; my $sel = $name eq $selected ? ' SELECTED' : ''; $html .= ' "; } if( $selected ne '' && $html !~ /VALUE="\Q$selected\E"/ ) { $html = '\n" . $html; } return $html; } sub user_unix_mapping_row( $$ ) { my( $user, $selected ) = @_; $user = '' unless defined( $user ); $selected = '' unless defined( $selected ); my $unix_user_options = unix_user_select_options( $selected ); if( $user eq 'add_new' ) { return qq| \n| . qq|\t\tUNIX user:\n| . qq|\t\t\n| . qq|\t\t\t
\n| . qq|\t\t\n| . qq|\t\n|; } my $display = $selected ne '' ? $selected : '(unchanged)'; return qq| \n| . qq|\t\tUNIX user:\n| . qq|\t\t| . html_escape( $display ) . qq|
\n| . qq|\t\t\t\n| . qq|\t\t\t\n| . qq|\t\t\n| . qq|\t\n|; } sub handle_request() { if( $c[1] eq 'general' ) { $server_name = getconfigline( 2 ); $internal_net = getconfigline( 3 ); my( $smart_bind_server_for_general, $smart_bind_user_for_general, $smart_bind_pass_for_general ) = smart_bindery_values(); my $general_sync_server_row = sync_server_hint_row( 'sync_smart_bind_server', $server_name, $smart_bind_server_for_general, 'general_to_smart' ); ( $burst_read, $burst_write ) = split( ' ', getconfigline( 30 ) ); $timing_down = getconfigline( 210 ); $timing_warn = getconfigline( 211 ); eval( '$test_' . getconfigline( 16 ) . ' = " CHECKED";' ); eval( '$version_' . ( split( ' ', getconfigline( 6 ) ) )[0] . ' = " CHECKED";' ); if( ( split( ' ', getconfigline( 6 ) ) )[1] == 1 ) { $burst_enabled_0 = ' CHECKED'; } else { $burst_enabled_0 = ''; } print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
$general_sync_server_row
General settings
Server name:
Internal network:
Tests at startup: None
Some
Check/compress bindery
Server version: 2.15
3.11
3.12
Burst mode
Burst mode: Enabled
MAX_BURST_READ_BUF:
MAX_BURST_WRITE_BUF:
Timing
Wait for x seconds before shutdown:
Warn users every x seconds:

EOF } elsif( $c[1] eq 'dirs' ) { $path_cache = getconfigline( 40 ); $share_lock = getconfigline( 41 ); $spool = getconfigline( 42 ); $bindery = getconfigline( 45 ); $attribute = getconfigline( 46 ); $trustee = getconfigline( 47 ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Directories
Path cache directory:
Share and lock files:
Spool directory:
Bindery files:
Attribute handling files:
Trustee handling files:

EOF } elsif( $c[1] eq 'configh' ) { $net_serial = getconfigline( 70 ); $net_app = getconfigline( 71 ); if( getconfigline( 68 ) eq '1' ) { $mmap_0 = ' CHECKED'; } else { $mmap_0 = ''; } eval( '$sap_' . getconfigline( 69 ) . ' = " CHECKED";' ); $max_conn = getconfigline( 60 ); $max_vol = getconfigline( 61 ); $max_dirbase = getconfigline( 63 ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Precompiled settings
Network serial number:
Network application number:
mmap() calls: Enabled
Handle SAP-types: Only type 4
All
Limits
Maximum connection count:
Maximum volume count:
Maximum directory-base entry count:
Advanced precompiled / path settings

EOF } elsif( $c[1] eq 'security' ) { $creat_dir = ( split( ' ', getconfigline( 9 ) ) )[0]; $creat_file = ( split( ' ', getconfigline( 9 ) ) )[1]; eval( '$encrypt_' . getconfigline( 7 ) . ' = " CHECKED";' ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Security
creat() mode for directories:
creat() mode for files:
Password encryption: Always encrypt
Except when changing password
Disallow zero-passwords
Allow zero-passwords
Disallow encryption
Advanced security settings

EOF } elsif( $c[1] eq 'susers' ) { $guest = getconfigline( 11 ); ( $root_name, $root, $root_password ) = split( ' ', getconfigline( 12 ) ); $guest_user_list = ''; $root_list = ''; foreach $u ( unix_userlist() ) { if( $u->{uid} eq $guest ) { $guest_user_list .= "\t\t\t" . '' . "\n"; } else { $guest_user_list .= "\t\t\t" . '' . "\n"; } if( $u->{name} eq $root ) { $root_list .= "\t\t\t" . '' . "\n"; } else { $root_list .= "\t\t\t" . '' . "\n"; } } $guest = getconfigline( 10 ); $guest_group_list = ''; foreach $u ( unix_grouplist() ) { if( $u->{gid} eq $guest ) { $guest_group_list .= "\t\t\t" . '' . "\n"; } else { $guest_group_list .= "\t\t\t" . '' . "\n"; } } eval( '$map_' . ( split( ' ', getconfigline( 15 ) ) )[0] . ' = " CHECKED";' ); $map_password = ( split( ' ', getconfigline( 15 ) ) )[1]; print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
User configuration
Guest user
User:
Group:
Supervisor user
Username:
Unix user:
Password:
User mapping
User mapping: Disabled
Enabled
Enabled, overwrite all users
Default password:
Advanced user / bindery settings

EOF } elsif( $c[1] eq 'logging' ) { eval( '$ipx_' . getconfigline( 100 ) . ' = " SELECTED";' ); eval( '$nwserv_' . getconfigline( 101 ) . ' = " SELECTED";' ); eval( '$ncpserv_' . getconfigline( 102 ) . ' = " SELECTED";' ); eval( '$nwconn_' . getconfigline( 103 ) . ' = " SELECTED";' ); eval( '$nwclient_' . getconfigline( 104 ) . ' = " SELECTED";' ); eval( '$nwbind_' . getconfigline( 105 ) . ' = " SELECTED";' ); eval( '$nwrouted_' . getconfigline( 106 ) . ' = " SELECTED";' ); eval( '$startup_' . getconfigline( 200 ) . ' = " CHECKED";' ); $general_log = getconfigline( 201 ); $routing_interval = getconfigline( 300 ); $routing_log = getconfigline( 301 ); $x = getconfigline( 202 ); eval( '$g_creat_' . ( $x & 1 ) . ' = " CHECKED";' ); eval( '$error_' . ( ( $x - $g_creat ) >> 1 ) . ' = " CHECKED";' ); $x = getconfigline( 302 ); eval( '$r_creat_' . ( $x & 1 ) . ' = " CHECKED";' ); eval( '$r_file_' . ( ( $x - $r_creat ) >> 1 ) . ' = " CHECKED";' ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Logging
Logfiles
General logfile:
Routing logfile:
Parts to log
IPX-kernel:
NWSERV:
NCPSERV:
NWCONN:
NWCLIENT:
NWBIND:
NWROUTED:
General logging flags
NWSERV behaviour: No logging, run in foreground
Run as daemon, enable logging
Logfile creation: Append messages to logfile
Recreate logfile at startup
Log error messages to: Logfile
syslog
Routing logging flags
Write to file every x minutes:
Logfile creation: Append messages to logfile
Recreate logfile every time
File: Keep using the same file
Write to separate files (.1, .2, etc)
Advanced network watchdog settings

EOF } elsif( $c[1] eq 'volumes' ) { my $volume_mount_import_rows = volume_mount_import_rows(); if( $c[2] eq '' ) { print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]} EOF @c = getconfig( 1 ); foreach $c ( @c ) { my @c = split( ' ', $c ); print < EOF } print <
Volumes
$c[1] ($c[2]) Delete
$volume_mount_import_rows Add new volume
EOF } else { my $volume_action = $c[2]; $c = getconfigline( '1 ' . $volume_action ); @c = split( ' ', $c ); $c = ''; my %volume_mount_defaults = volume_mount_defaults_from_query(); if( $volume_action eq 'add_new' ) { $c[0] = $volume_mount_defaults{name} if defined( $volume_mount_defaults{name} ) && $volume_mount_defaults{name} ne ''; $c[1] = $volume_mount_defaults{path} if defined( $volume_mount_defaults{path} ) && $volume_mount_defaults{path} ne ''; $c[2] = 'k' if ! defined( $c[2] ) || $c[2] eq ''; } if( $volume_action eq 'add_new' ) { my %volume_mount_defaults = volume_mount_defaults_from_query(); if( defined( $volume_mount_defaults{name} ) && $volume_mount_defaults{name} ne '' ) { $c[0] = $volume_mount_defaults{name}; } if( defined( $volume_mount_defaults{path} ) && $volume_mount_defaults{path} ne '' ) { $c[1] = $volume_mount_defaults{path}; } # Default new imported volumes to lower-case filenames. $c[2] = 'k' if ! defined( $c[2] ) || $c[2] eq ''; } $d = $c[2]; $d =~ s/[^ik]//g; eval( '$c' . $d . ' = " CHECKED";' ); $d = $c[2]; $d =~ s/[^Tt]//g; eval( '$t' . $d . ' = " CHECKED";' ); $m = $c[2]; $m =~ s/[^m]//g; if( $m ne '' ) { $m = ' CHECKED'; } $n = $c[2]; $n =~ s/[^n]//g; if( $n ne '' ) { $n = ' CHECKED'; } $o = $c[2]; $o =~ s/[^o]//g; if( $o ne '' ) { $o = ' CHECKED'; } $p = $c[2]; $p =~ s/[^p]//g; if( $p ne '' ) { $p = ' CHECKED'; } $r = $c[2]; $r =~ s/[^r]//g; if( $r ne '' ) { $r = ' CHECKED'; } $O = $c[2]; $O =~ s/[^O]//g; if( $O ne '' ) { $O = ' CHECKED'; } $N = $c[2]; $N =~ s/[^N]//g; if( $N ne '' ) { $N = ' CHECKED'; } print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Volume: $c[0]
Volume name:
Unix path:
Filename case: All upper case
Ignore case
All lower case
Trustees: Disabled
Enabled
Enabled, unix rights disabled
Additional options
Removable: Enabled
No fixed i-nodes: Enabled
Single filesystem: Enabled
Pipe filesystem: Enabled
Read-only: Enabled
Additional namespaces
OS/2 LFN support: Enabled
NFS support: Enabled

EOF } } elsif( $c[1] eq 'devices' ) { if( $c[2] eq '' ) { my $ipx_device_import_rows = ipx_device_import_rows(); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]} EOF @c = getconfig( 4 ); foreach $c ( @c ) { my @c = split( ' ', $c ); print < EOF } print <
Devices
$c[1] ($c[2]/$c[3]) Delete
Add new device manually

Advanced device settings
EOF } else { my $title = $c[2]; my $number = ''; my $interface = ''; my $frametype = '802.2'; my $delay = 1; if( $c[2] eq 'add_new' ) { my %defaults = ipx_device_defaults_from_query(); $number = $defaults{number}; $interface = $defaults{interface}; $frametype = $defaults{frametype}; $delay = $defaults{delay}; } else { my $line = getconfigline( '4 ' . $c[2] ); my @dev = split( ' ', $line ); $number = $dev[0]; $interface = $dev[1]; $frametype = $dev[2]; $delay = $dev[3]; $title = $number; } $number = '' unless defined $number; $interface = '' unless defined $interface; $frametype = '802.2' unless defined $frametype && $frametype ne ''; $delay = 1 unless defined $delay && $delay ne ''; my $frametype_key = $frametype; $frametype_key =~ s/\.//g; eval( '$frametype_' . $frametype_key . ' = " SELECTED";' ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
Device: $title
Network number:
Network interface:
Use the IPX interfaces list on the Devices overview to prefill this value.
Frame type:
Interface delay:

EOF } } elsif( $c[1] eq 'smart' ) { ( $bind_server, $bind_user, $bind_pass ) = smart_bindery_values(); my $smart_general_server_name = getconfigline( 2 ); my $smart_sync_server_row = sync_server_hint_row( 'sync_general_server_name', $bind_server, $smart_general_server_name, 'smart_to_general' ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
$smart_sync_server_row
SMArT settings
nwserv.conf location:
Bindery server
Server name:
Supervisor login name:
Supervisor password:

EOF } elsif( $c[1] eq 'users' || $c[1] eq 'users_import' ) { if( $c[1] eq 'users_import' ) { $p{unix_user} = $c[2]; $c[1] = 'users'; $c[2] = 'add_new'; } my $unix_user_import_rows = unix_user_import_rows(); $server = get_server(); if( $c[2] eq '' ) { print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]} EOF @c = sort( split( "\n", `nwbols -t 1 -S $server` ) ); foreach $c ( @c ) { my @c = split( ' ', $c ); print < EOF } print <
Users
$c[0] Delete
$unix_user_import_rows Add new user
EOF } else { my $group_rows = smart_group_checkbox_rows( $server ); my %unix_defaults = unix_user_defaults_from_query(); my $default_name = $unix_defaults{name}; my $default_unix_user = $unix_defaults{unix_user}; my $default_fullname = $unix_defaults{fullname}; $default_name = '' unless defined( $default_name ); $default_unix_user = '' unless defined( $default_unix_user ); $default_fullname = '' unless defined( $default_fullname ); $unix_user_list = ''; $group_list = ''; @allgroups = sort( split( "\n", `nwbols -S $server -t 2` ) ); if( $c[2] ne 'add_new' ) { $fullname = read_property_string( $c[2], 1, 'IDENTIFICATION' ); $unix_user = read_property_string( $c[2], 1, 'UNIX_USER' ); foreach $u ( unix_userlist() ) { if( $u->{name} eq $unix_user ) { $unix_user_list .= "\t\t\t" . '' . "\n"; } else { $unix_user_list .= "\t\t\t" . '' . "\n"; } } @groups = read_property_list( $c[2], 1, 'GROUPS_I\\\'M_IN' ); foreach $g ( @allgroups ) { $g =~ s/ .*//; if( grep( /^$g$/, @groups ) ) { $group_list .= "\t\t\t" . $g . '
' . "\n"; } else { $group_list .= "\t\t\t" . $g . '
' . "\n"; } } } else { $fullname = $default_fullname; foreach $u ( unix_userlist() ) { if( defined( $default_unix_user ) && $default_unix_user ne '' && $u->{name} eq $default_unix_user ) { $unix_user_list .= "\t\t\t" . '' . "\n"; } else { $unix_user_list .= "\t\t\t" . '' . "\n"; } } if( defined( $default_unix_user ) && $default_unix_user ne '' && $unix_user_list !~ /VALUE="\Q$default_unix_user\E"/ ) { $unix_user_list .= "\t\t\t" . '' . "\n"; } foreach $g ( @allgroups ) { $g =~ s/ .*//; next if $g eq ''; $group_list .= "\t\t\t" . $g . '
' . "\n"; } if( $group_list eq '' ) { $group_list = "\t\t\t" . 'EVERYONE
' . "\n"; } } my $user_group_checkbox_rows = user_group_checkbox_rows( $c[2] ); my $current_unix_user = defined( $p{unix_user} ) ? $p{unix_user} : ''; my $user_unix_mapping_row = user_unix_mapping_row( $c[2], $current_unix_user ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
EOF if( $c[2] eq 'add_new' ) { print < EOF } print < $user_unix_mapping_row
User: $c[2]
Account name:
Full name:
Password:
Groups belonged to: $user_group_checkbox_rows

EOF } } elsif( $c[1] eq 'groups' ) { my $groups_service_guard_rows = mars_nwe_service_guard_rows( 'groups' ); $server = get_server(); if( $c[2] eq '' ) { print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]} EOF @c = sort( split( "\n", `nwbols -t 2 -S $server` ) ); foreach $c ( @c ) { my @c = split( ' ', $c ); print < EOF } print <
Groups
$c[0] Delete
Add new group
EOF } else { @all = sort( split( "\n", `nwbols -S $server` ) ); $man_list = ''; if( $c[2] ne 'add_new' ) { $fullname = read_property_string( $c[2], 2, 'IDENTIFICATION' ); @mans = read_property_list( $c[2], 2, 'OBJ_SUPERVISORS' ); foreach $g ( @all ) { my @c = split( ' ', $g ); if( $c[2] == 1 or $c[2] == 2 ) { if( grep( /^$c[0]$/, @mans ) ) { $man_list .= "\t\t\t" . '(' . ( $c[2] == 1 ? 'user' : 'group' ) . ') ' . $c[0] . '
' . "\n"; } else { $man_list .= "\t\t\t" . '(' . ( $c[2] == 1 ? 'user' : 'group' ) . ') ' . $c[0] . '
' . "\n"; } } } } else { foreach $g ( @all ) { my @c = split( ' ', $g ); if( $c[2] == 1 or $c[2] == 2 ) { $man_list .= "\t\t\t" . '(' . ( $c[2] == 1 ? 'user' : 'group' ) . ') ' . $c[0] . '
' . "\n"; } } } print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
EOF if( $c[2] eq 'add_new' ) { print < EOF } print <
Group: $c[2]
Group name:
Full name:
Group managers: $man_list

EOF } } elsif( $c[1] eq 'queues' ) { my $queues_service_guard_rows = mars_nwe_service_guard_rows( 'print queues' ); $server = get_server(); if( $c[2] eq '' ) { print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]} 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 } print cups_import_rows(); print <
Print queues
$q Test print  |  Delete
Add new print queue
EOF } else { @all = sort( split( "\n", `nwbols -S $server` ) ); $man_list = ''; $queue_name_value = ''; $selected_cups_printer = sanitize_cups_printer_name( $p{cups_printer} ); if( $c[2] ne 'add_new' ) { $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 '' ) { $queue_name_value = cups_queue_name( $selected_cups_printer ); $unix_print = cups_print_command( $selected_cups_printer ); } ( $cups_select, $cups_js ) = cups_select_html( $selected_cups_printer ); print < SMArT Settings $settings_nav_bar @{[ settings_message_html() ]}
EOF if( $c[2] eq 'add_new' ) { print < EOF } print < EOF } print < EOF if( $c[2] ne 'add_new' ) { print < EOF } print <
Print queue: $c[2]
Queue name:
CUPS printer:
Select a host printer to generate the matching lp command.
$cups_select
Unix printing command:
Example for CUPS: /usr/bin/lp -d printer -
Spool directory:
Queue test:
Submit a small test job with nprint.
Test print queue

EOF } } elsif( $c[1] eq 'advanced' ) { my $advanced_category = advanced_category(); my $advanced_title = advanced_title( $advanced_category ); my $advanced_hidden = advanced_hidden_category_input( $advanced_category ); my $device_flags = getconfigline( 5 ); my $security_flags = getconfigline( 8 ); my $bindery_flags = getconfigline( 17 ); my $queue_flags = getconfigline( 18 ); my $max_dir_search_handles = getconfigline( 80 ); my $conversion_tables = getconfigline( 50 ); my $watchdogs = getconfigline( 310 ); my $station_file = getconfigline( 400 ); my $nearest_replies = getconfigline( 401 ); my $connect_replies = getconfigline( 402 ); $device_flags = 0 if ! defined( $device_flags ) || $device_flags eq ''; $security_flags = 0 if ! defined( $security_flags ) || $security_flags eq ''; $bindery_flags = 0 if ! defined( $bindery_flags ) || $bindery_flags eq ''; $queue_flags = 0 if ! defined( $queue_flags ) || $queue_flags eq ''; my $dev_keep = ( $device_flags & 1 ) ? ' CHECKED' : ''; my $dev_auto = ( $device_flags & 2 ) ? ' CHECKED' : ''; my $dev_remove_all = ( $device_flags & 4 ) ? ' CHECKED' : ''; my $sec_supervisor_ignore = ( $security_flags & 0x8 ) ? ' CHECKED' : ''; my $sec_2gb_free = ( $security_flags & 0x40 ) ? ' CHECKED' : ''; my $sec_int17 = ( $security_flags & 0x200 ) ? ' CHECKED' : ''; my $sec_delete_open = ( $security_flags & 0x2 ) ? ' CHECKED' : ''; my $sec_rename_open = ( $security_flags & 0x4 ) ? ' CHECKED' : ''; my $bindery_empty_scripts = ( $bindery_flags & 1 ) ? ' CHECKED' : ''; my $queue_no_banner = ( $queue_flags & 1 ) ? ' CHECKED' : ''; my $nearest_0 = $nearest_replies eq '0' ? ' SELECTED' : ''; my $nearest_1 = $nearest_replies eq '1' ? ' SELECTED' : ''; my $nearest_2 = $nearest_replies eq '2' ? ' SELECTED' : ''; my $connect_0 = $connect_replies eq '0' ? ' SELECTED' : ''; my $connect_1 = $connect_replies eq '1' ? ' SELECTED' : ''; my $connect_2 = $connect_replies eq '2' ? ' SELECTED' : ''; my $print_server_rows = ''; foreach my $ps ( getconfig( 22 ) ) { my $line = $ps; $line =~ s/^22\s+//; $print_server_rows .= html_escape( $line ) . "\n"; } print < SMArT Advanced Settings $settings_nav_bar @{[ settings_message_html() ]}
$advanced_hidden EOF if( advanced_section_visible( $advanced_category, '5' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '8' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '17' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '18' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '22' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '50' ) || advanced_section_visible( $advanced_category, '80' ) ) { print < EOF if( advanced_section_visible( $advanced_category, '50' ) ) { print qq|\t\n|; } if( advanced_section_visible( $advanced_category, '80' ) ) { print qq|\t\n|; } } if( advanced_section_visible( $advanced_category, '310' ) ) { print qq|\t\n|; print qq|\t\n|; } if( advanced_section_visible( $advanced_category, '400' ) || advanced_section_visible( $advanced_category, '401' ) || advanced_section_visible( $advanced_category, '402' ) ) { print < EOF if( advanced_section_visible( $advanced_category, '400' ) ) { print qq|\t\n|; } if( advanced_section_visible( $advanced_category, '401' ) ) { print < EOF } if( advanced_section_visible( $advanced_category, '402' ) ) { print < EOF } } print <
$advanced_title
IPX device flags
Keep IPX devices/routes on stop
Allow automatic kernel IPX interface creation
Remove all IPX routes/devices on stop
Security / compatibility flags
Ignore station/time restrictions for supervisor
Limit volume free space information to 2 GB
Enable direct INT17 printing for NETX clients
Allow deleting open files (advanced)
Allow renaming open files (advanced)
User / bindery flags
Create empty login scripts when missing
Print queue flags
Always disable print banner
Print server entries

One entry per line, without leading section number 22.
Precompiled / path settings
Conversion table file
Maximum directory search handles
Watchdog behavior
Watchdog ticks
0 = always, -1 = never, positive value = only below ticks.
Station access control
Station file
Nearest server replies
Connection replies

EOF } else { error( 404 ); } }