From e291b2dcb1ff3e8b37364e020afac3c76c251721 Mon Sep 17 00:00:00 2001 From: Till Kamppeter Date: Wed, 12 Feb 2003 18:42:36 +0000 Subject: Scannerdrake vastly improved - Use auto-detection methods of SANE - Do not ask the user to configure scanners which are already configured - Handle systems with more than one scanner correctly - Added ports of newer scanners (libusb, parallel, ...) to the port selector in manual setup - Main dialog showing all configured scanners - Full support for scanner sharing via SANE (server/client) - Support for USB scanner access via libusb --- perl-install/scanner.pm | 153 +++++++-- perl-install/services.pm | 9 +- perl-install/standalone/scannerdrake | 621 +++++++++++++++++++++++++++++++++-- 3 files changed, 736 insertions(+), 47 deletions(-) (limited to 'perl-install') diff --git a/perl-install/scanner.pm b/perl-install/scanner.pm index 3fe56b01f..6a5dbdacb 100755 --- a/perl-install/scanner.pm +++ b/perl-install/scanner.pm @@ -32,7 +32,7 @@ use handle_configs; my $_sanedir = "$::prefix/etc/sane.d"; my $_scannerDBdir = "$::prefix$ENV{SHARE_PATH}/ldetect-lst"; -my $scannerDB = readScannerDB("$_scannerDBdir/ScannerDB"); +$scannerDB = readScannerDB("$_scannerDBdir/ScannerDB"); sub confScanner { my ($model, $port) = @_; @@ -54,34 +54,139 @@ sub add2dll { output("$_sanedir/dll.conf", @dllconf); } +sub configured { + my @res = (); + # Run "scanimage -L", to find the scanners which are already working + open LIST, "LC_ALL=C scanimage -L |"; + while (my $line = ) { + if ($line =~ /^\s*device\s*\`([^\`\']+)\'\s+is\s+a\s+(\S.*)$/) { + # Extract port and description + my $port = $1; + my $description = $2; + # Remove duplicate scanners appearing through saned and the + # "net" backend + next if $port =~ /^net:(localhost|127.0.0.1):/; + # Store collected data + push @res, { + port => $port, + val => { + DESCRIPTION => $description, + } + }; + } + } + close LIST; + return @res; +} + sub detect { - my ($i, @res) = 0; - foreach (grep { $_->{driver} =~ /scanner/ } detect_devices::usb_probe()) { - use Data::Dumper; - print Dumper($_); - #my ($manufacturer, $model) = split '\|', $_->{description}; - #$_->{description} =~ s/Hewlett[-\s_]Packard/HP/; - $_->{description} =~ s/Seiko\s+Epson/Epson/i; - push @res, { port => "/dev/usb/scanner$i", val => { CLASS => 'SCANNER', - MODEL => $model, - MANUFACTURER => $manufacturer, - DESCRIPTION => $_->{description}, - id => $_->{id}, - vendor => $_->{vendor}, - } }; - ++$i; + my @configured = @_; + my @res = (); + # Run "sane-find-scanner", this also detects USB scanners which only + # work with libusb. + open DETECT, "LC_ALL=C sane-find-scanner -q |"; + while (my $line = ) { + my $vendorid = undef; + my $productid = undef; + my $make = undef; + my $model = undef; + my $description = undef; + my $port = undef; + if ($line =~ /^\s*found\s+USB\s+scanner/i) { + # Found an USB scanner + if ($line =~ /vendor=(0x[0-9a-f]+)[^0-9a-f\[]+[^\[]*\[([^\[\]]+)\].*prod(|uct)=(0x[0-9a-f]+)[^0-9a-f\[]+[^\[]*\[([^\[\]]+)\]/) { + # Scanner connected via libusb + $vendorid = $1; + $make = $2; + $productid = $4; + $model = $5; + $description = "$make|$model"; + } elsif ($line =~ /vendor=(0x[0-9a-f]+)[^0-9a-f]+.*prod(|uct)=(0x[0-9a-f]+)[^0-9a-f]+/) { + # Scanner connected via scanner.o kernel module + $vendorid = $1; + $productid = $3; + } + if ($vendorid and $productid) { + # We have vendor and product ID, look up the scanner in + # the usbtable + foreach $entry (cat_("$_scannerDBdir/usbtable")) { + if ($entry =~ + /^\s*$vendorid\s+$productid\s+.*\"([^\"]+)\"\s*$/) { + $description = $1; + $description =~ s/Seiko\s+Epson/Epson/i; + if ($description =~ /^([^\|]+)\|(.*)$/) { + $make = $1; + $model = $2; + } + last; + } + } + } + } elsif ($line =~ /^\s*found\s+SCSI/i) { + # SCSI scanner + if ($line =~ /\"([^\"\s]+)\s+([^\"]+?)\s+([^\"\s]+)\"/) { + $make = $1; + $model = $2; + $description = "$make|$model"; + } + } else { + # Comment line in output of "sane-find-scanner" + next; + } + # Extract port + $line =~ /\s+(\S+)\s*$/; + $port = $1; + # Check for duplicate (scanner.o/libusb) + if ($port =~ /^libusb/) { + my $duplicate = 0; + foreach (@res) { + if (($_->{val}{vendor} eq $vendorid) && + ($_->{val}{id} eq $productid) && + ($_->{port} =~ /dev.*usb.*scanner/) && + (!defined($_->{port2}))) { + # Duplicate entry found, merge the entries + $_->{port2} = $port; + $_->{val}{MANUFACTURER} ||= $make; + $_->{val}{MODEL} ||= $model; + $_->{val}{DESCRIPTION} ||= $description; + $duplicate = 1; + last; + } + } + next if $duplicate; + } + # Store collected data + push @res, { + port => $port, + val => { + CLASS => 'SCANNER', + MODEL => $model, + MANUFACTURER => $make, + DESCRIPTION => $description, + id => $productid, + vendor => $vendorid, + } + }; } - foreach (grep { $_->{media_type} =~ /scanner/ } detect_devices::getSCSI()) { - $_->{info} =~ s/Seiko\s+Epson/Epson/i; - push @res, { port => "/dev/sg", - val => { DESCRIPTION => $_->{info} }, - }; - ++$i; + close DETECT; + if (@configured) { + # Remove scanners which are already working + foreach my $d (@res) { + my $searchport1 = handle_configs::searchstr($d->{port}); + my $searchport2 = handle_configs::searchstr($d->{port2}); + foreach my $c (@configured) { + if (($c->{port} =~ /$searchport1$/) || + ($c->{port} =~ /$searchport2$/)) { + $d->{configured} = 1; + last; + } + } + } + @res = map { $_->{configured} ? () : $_; } @res; } - @res; + return @res; } - sub readScannerDB { my ($file) = @_; my ($card, %cards); diff --git a/perl-install/services.pm b/perl-install/services.pm index f8c6a4aaa..f3aa02e49 100644 --- a/perl-install/services.pm +++ b/perl-install/services.pm @@ -337,7 +337,8 @@ sub starts_on_boot ($) { return 0; while (my $line = ) { chomp $line; - if ($line =~ /:on/) { + if (($line =~ /:on/) || # service with init script + ($line =~ /^\s*$service\s+on\s*$/)) { # xinetd service close F; return 1; } @@ -353,5 +354,11 @@ sub start_service_on_boot ($) { return 1; } +sub do_not_start_service_on_boot ($) { + my ($service) = @_; + run_program::rooted($::prefix, "/sbin/chkconfig", "--del", $service) + or return 0; + return 1; +} 1; diff --git a/perl-install/standalone/scannerdrake b/perl-install/standalone/scannerdrake index bf7717257..f625f4568 100755 --- a/perl-install/standalone/scannerdrake +++ b/perl-install/standalone/scannerdrake @@ -25,6 +25,8 @@ use standalone; #- warning, standalone must be loaded very first, for 'expla use interactive; use common; use scanner; +use handle_configs; +use services; foreach (@ARGV) { /^--update-usbtable$/ and do { scanner::updateScannerDBfromUsbtable(); exit }; @@ -34,52 +36,180 @@ foreach (@ARGV) { } $in = 'interactive'->vnew('su', 'default'); -$in->do_pkgs->install('sane-backends', 'xsane', if_($in->do_pkgs->is_installed('gimp'),'xsane-gimp')); +if (!files_exist('/usr/bin/scanimage', + '/usr/bin/xsane', + if_(files_exist("/usr/bin/gimp"), + "/usr/lib/gimp/*/plug-ins/xsane"))) { + $in->do_pkgs->install('sane-backends', 'xsane', + if_($in->do_pkgs->is_installed('gimp'), + 'xsane-gimp')); +} if ($::Manual) { manual(); quit() } -my $wait = $in->wait_message(N("Test ports"), N("Detecting devices ...")); -@f = scanner::detect(); +my $wait = $in->wait_message(N("Scannerdrake"), + N("Searching for configured scanners ...")); +@c = scanner::configured(); +$wait = $in->wait_message(N("Scannerdrake"), + N("Searching for new scanners ...")); +@f = scanner::detect(@c); $wait = undef; -(@f) ? auto() : manual(); +my $changed = 0; +(@f) and $changed = auto(); +if ($changed) { + my $wait = + $in->wait_message(N("Scannerdrake"), + N("Re-generating list of configured scanners ...")); + @c = scanner::configured(); +} +mainwindow(@c); quit(); sub removeverticalbar { my ($s) = @_; $s =~ s/\|/ /g; + $s =~ /^\s*(\S+)\s+/; + my $make = $1; + my $searchmake = handle_configs::searchstr($make); + $s =~ s/($searchmake)\s*$searchmake/$1/; return $s; } sub auto { #use Data::Dumper; #print Dumper (@f); + my $changed = 0; foreach (@f) { if (member($_->{val}{DESCRIPTION}, keys %$scanner::scannerDB)) { my $name = $_->{val}{DESCRIPTION}; - $name =~ s/\s$//; #some HP entry have a trailing space, i will correct usbtable asap + $name =~ s/\s$//; # some HP entries have a trailing space, i will correct usbtable asap if ($scanner::scannerDB->{$name}{flags}{unsupported}) { - $in->ask_warn('scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($name))); + $in->ask_warn('Scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($name))); next; } - if ($in->ask_yesorno('scannerdrake',N("%s found on %s, configure it automatically?",removeverticalbar($name),$_->{port}),1)) { - tryConfScanner($name, $_->{port}) or manual(); + if ($in->ask_yesorno('Scannerdrake',N("%s found on %s, configure it automatically?",removeverticalbar($name),$_->{port}),1)) { + $changed ||= (tryConfScanner($name, $_->{port}) or + manual()); } else { - manual(); + $changed ||= manual(); } } else { - $in->ask_yesorno('scannerdrake',N("%s is not in the scanner database, configure it manually?", removeverticalbar($_->{val}{DESCRIPTION})),1) and manual(); + $in->ask_yesorno('Scannerdrake',N("%s is not in the scanner database, configure it manually?", removeverticalbar($_->{val}{DESCRIPTION})),1) and manual(); } } + return changed; } sub manual { - my $s = $in->ask_from_treelist('scannerdrake', N("Select a scanner"), '|', [' None', keys %$scanner::scannerDB], '') or return; - return 1 if $s eq ' None'; + my $s = $in->ask_from_treelist('Scannerdrake', N("Select a scanner"), '|', [' None', keys %$scanner::scannerDB], '') or return 0; + return 0 if $s eq ' None'; if ($scanner::scannerDB->{$s}{flags}{unsupported}) { - $in->ask_warn('scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($s))); - return 1; + $in->ask_warn('Scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($s))); + return 0; } return tryConfScanner($s); } +sub mainwindow { + my @configured = @_; + # main loop + my $maindone; + while (!$maindone) { + # Generate list of configured scanners + my $msg = do { + if (@configured) { + my @scannerlist = + map { + my $entry = $_->{val}{DESCRIPTION}; + if_($entry, " - $entry\n"); + } @configured; + if (@scannerlist) { + my $main_msg = + @scannerlist > 1 ? + N_("The following scanners\n\n%s\nare available on your system.\n") : + N_("The following scanner\n\n%s\nis available on your system.\n"); + sprintf($main_msg, join('', @scannerlist)); + } else { + N("There are no scanners found which are available on your system.\n"); + } + } else { + N("There are no scanners found which are available on your system.\n"); + } + }; + my $buttonclicked; + #- Show dialog + if ($in->ask_from_ + ( + { + title => N("Scannerdrake"), + messages => $msg, + ok => "", + cancel => "", + }, + [ + { val => N("Search for new scanners"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "autoadd"; + 1; + } }, + { val => N("Add a scanner manually"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "manualadd"; + 1; + } }, + { val => N("Scanner sharing"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "sharing"; + 1; + } }, + { val => N("Quit"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "quit"; + 1; + } }, + ] + ) + ) { + my $changed = 0; + if ($buttonclicked eq "autoadd") { + # Do scanner auto-detection + my $wait = + $in->wait_message(N("Scannerdrake"), + N("Searching for configured scanners ...")); + @configured = scanner::configured(); + $wait = + $in->wait_message(N("Scannerdrake"), + N("Searching for new scanners ...")); + my @f = scanner::detect(@configured); + $wait = undef; + if (@f) { + $changed = auto(); + } + } elsif ($buttonclicked eq "manualadd") { + # Show dialogs to manually add a scanner + $changed = manual(); + } elsif ($buttonclicked eq "sharing") { + # Show dialog to set up scanner sharing + $changed = sharewindow(@configured); + } elsif ($buttonclicked eq "quit") { + # We have clicked "Quit" + $maindone = 1; + } + if ($changed) { + my $wait = + $in->wait_message(N("Scannerdrake"), + N("Re-generating list of configured scanners ...")); + @configured = scanner::configured(); + } + } else { + # Cancel clicked + $maindone = 1; + } + } +} + sub dynamic { @f = scanner::detect(); foreach (@f) { @@ -87,12 +217,12 @@ sub dynamic { my $name = $_->{val}{DESCRIPTION}; $name =~ s/\s$//; #some HP entry have a trailing space, i will correct usbtable asap if ($scanner::scannerDB->{$name}{flags}{unsupported}) { - $in->ask_warn('scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($name))); + $in->ask_warn('Scannerdrake', N("The %s is not supported by this version of Mandrake Linux.", removeverticalbar($name))); next; } scanner::confScanner($name, $_->{port}); } else { - $in->ask_warn('scannerdrake', N("The %s is not known by this version of scannerdrake.", removeverticalbar($name))); + $in->ask_warn('Scannerdrake', N("The %s is not known by this version of Scannerdrake.", removeverticalbar($name))); } } } @@ -101,13 +231,13 @@ sub tryConfScanner { # take care if interactive output is needed (unsupported, parallel..) my ($model, $port) = @_; if ($scanner::scannerDB->{$model}{flags}{unsupported}) { - $in->ask_warn('scannerdrake', N("The %s is unsupported", + $in->ask_warn('Scannerdrake', N("The %s is unsupported", removeverticalbar($model))); return 0; } - if ($scanner::scannerDB->{$model}{ask} =~ /DEVICE/) { + if (($scanner::scannerDB->{$model}{ask} =~ /DEVICE/) || (!$port)){ $port = '/dev/usb/scanner0'; - $in->ask_from('scannerdrake', + $in->ask_from('Scannerdrake', N("Scannerdrake was not able to detect your %s.\nPlease select the device where your scanner is attached", removeverticalbar($model)), [ { label => N("choose device"), @@ -137,10 +267,10 @@ sub tryConfScanner { '/dev/pt_drv'], not_edit => 0, sort => 1 }, ], - ) or manual(); + ) or return 0; } - if ($scanner::scannerDB->{$model}{server} =~ /(printerdrake|hpoj)/) { - $in->ask_warn('scannerdrake', N("The %s must be configured by printerdrake.\nYou can launch printerdrake from the Mandrake Control Center in Hardware section.", removeverticalbar($model))); + if ($scanner::scannerDB->{$model}{server} =~ /(printerdrake|hpoj)/i) { + $in->ask_warn('Scannerdrake', N("The %s must be configured by printerdrake.\nYou can launch printerdrake from the Mandrake Control Center in Hardware section.", removeverticalbar($model))); return 0; } scanner::confScanner($model,$port); @@ -152,3 +282,450 @@ sub tryConfScanner { sub quit { $::isEmbedded ? kill('USR1', $::CCPID) : $in->exit(0); } + +sub makeexportmenues { + my @exports = @_; + my %menuexports = map { + ($_ eq '+' ? N("All remote machines") : $_) => $_; + } map { + # Remove comments and blank lines + ($_ =~ /^\s*($|\#)/ ? () : chomp_($_)); + } @exports; + my %menuexports_inv = reverse %menuexports; + return (\%menuexports, \%menuexports_inv); +} + +sub makeimportmenues { + my @imports = @_; + my %menuimports = map { + ($_ eq 'localhost' ? N("This machine") : $_) => $_; + } map { + # Remove comments and blank lines + ($_ =~ /^\s*($|\#)/ ? () : chomp_($_)); + } @imports; + my %menuimports_inv = reverse %menuimports; + return (\%menuimports, \%menuimports_inv); +} + +sub sharewindow { + my @configured = @_; + # Read list of hosts to where to export the local scanners + my @exports = cat_("/etc/sane.d/saned.conf"); + my ($menuexports, $menuexports_inv) = + makeexportmenues(@exports); + # Read list of hosts from where to import scanners + my @imports = cat_("/etc/sane.d/net.conf"); + my ($menuimports, $menuimports_inv) = + makeimportmenues(@imports); + # Is saned running? + my $sanedrunning = services::starts_on_boot("saned"); + my $oldsanedrunning = $sanedrunning; + # Is the "net" SANE backend active + my $netbackendactive = grep(/^\s*net\s*$/, + cat_("/etc/sane.d/dll.conf")); + my $oldnetbackendactive = $netbackendactive; + # Set this to 1 to tell the caller that the list of locally available + # scanners has changed (Here if the SANE client configuration has + # changed) + my $changed = 0; + my $importschanged = 0; + # main loop + my $maindone; + while (!$maindone) { + my $buttonclicked; + #- Show dialog + if ($in->ask_from_ + ( + { + title => N("Scannerdrake"), + messages => N("Here you can choose whether the scanners connected to this machine should be accessable by remote machines and by which remote machines.") . + N("You can also decide here whether scanners on remote machines should be made available on this machine."), + }, + [ + { text => N("The scanners on this machine are available to other computers"), type => 'bool', + val => \$sanedrunning }, + { val => N("Scanner sharing to hosts: ") . + (keys %{$menuexports} > 0 ? + (keys %{$menuexports} > 2 ? + join(", ", (keys %{$menuexports})[0,1]) . " ..." : + join(", ", keys %{$menuexports})) : + N("No remote machines")), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "exports"; + 1; + }, + disabled => sub { + !$sanedrunning; + } }, + { text => N("Use scanners on remote computers"), + type => 'bool', + val => \$netbackendactive }, + { val => N("Use the scanners on hosts: ") . + (keys %{$menuimports} > 0 ? + (keys %{$menuimports} > 2 ? + join(", ", (keys %{$menuimports})[0,1]) . " ..." : + join(", ", keys %{$menuimports})) : + N("No remote machines")), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "imports"; + 1; + }, + disabled => sub { + !$netbackendactive; + } }, + ] + ) + ) { + if ($buttonclicked eq "exports") { + # Show dialog to add hosts to share scanners to + my $subdone = 0; + my $choice; + while (!$subdone) { + my @list = keys %{$menuexports}; + # Entry should be edited when double-clicked + $buttonclicked = "edit"; + $in->ask_from_ + ( + { title => N("Sharing of local scanners"), + messages => N("These are the machines on which the locally connected scanner(s) should be available:"), + ok => "", + cancel => "", + }, + # List the hosts + [ { val => \$choice, format => \&translate, + sort => 0, separator => "####", + tree_expanded => 1, + quit_if_double_click => 1, + allow_empty_list => 1, + list => \@list }, + { val => N("Add host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "add"; + 1; + } }, + { val => N("Edit selected host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "edit"; + 1; + }, + disabled => sub { + return ($#list < 0); + } }, + { val => N("Remove selected host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "remove"; + 1; + }, + disabled => sub { + return ($#list < 0); + } }, + { val => N("Done"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = ""; + $subdone = 1; + 1; + } }, + ] + ); + if ($buttonclicked eq "add" || + $buttonclicked eq "edit") { + my ($hostchoice, $ip); + if ($buttonclicked eq "add") { + # Use first entry as default for a new entry + $hostchoice = + N("Name/IP address of host:"); + } else { + if ($menuexports->{$choice} eq '+') { + # Entry is "All hosts" + $hostchoice = $choice; + } else { + # Entry is a name/an IP address + $hostchoice = + N("Name/IP address of host:"); + $ip = $choice; + } + } + my @menu = (N("All remote machines"), + N("Name/IP address of host:")); + # Show the dialog + my $address; + my $oldaddress = + ($buttonclicked eq "edit" ? + $menuexports->{$choice} : ""); + if ($in->ask_from_ + ( + { title => N("Sharing of local scanners"), + messages => N("Choose the host on which the local scanners should be made available:"), + callbacks => { + complete => sub { + if ($hostchoice eq $menu[0]) { + $address = "+"; + } elsif ($hostchoice eq $menu[1]) { + $address = $ip; + } + # Do not allow an empty address + if ($address !~ /\S/) { + $in->ask_warn(N("Scannerdrake"), + N("You must enter a host name or an IP address.\n")); + return (1,0); + } + # Strip off leading and trailing + # spaces + $address =~ s/^\s*(.*?)\s*$/$1/; + # Check whether item is duplicate + if (($address ne $oldaddress) && + (member("$address\n", + @exports))) { + $in->ask_warn(N("Scannerdrake"), + N("This host is already in the list, it cannot be added again.\n")); + return (1,1); + } + return 0; + }, + }, + }, + # List the host types + [ { val => \$hostchoice, format => \&translate, + type => 'list', + sort => 0, + list => \@menu }, + { val => \$ip, + disabled => sub { + $hostchoice ne + N("Name/IP address of host:"); + }}, + ], + )) { + # OK was clicked, insert new item into the list + if ($buttonclicked eq "add") { + handle_configs::set_directive(\@exports, + $address); + } else { + handle_configs::replace_directive(\@exports, + $oldaddress, + $address); + } + # Refresh list of hosts + ($menuexports, $menuexports_inv) = + makeexportmenues(@exports); + # Position the list cursor on the new/modified + # item + $choice = $menuexports_inv->{$address}; + } + } elsif ($buttonclicked eq "remove") { + my $address = $menuexports->{$choice}; + handle_configs::remove_directive(\@exports, + $address); + # Refresh list of hosts + ($menuexports, $menuexports_inv) = + makeexportmenues(@exports); + } + } + } elsif ($buttonclicked eq "imports") { + # Show dialog to add hosts on which the scanners should be + # used + my $subdone = 0; + my $choice; + while (!$subdone) { + my @list = keys %{$menuimports}; + # Entry should be edited when double-clicked + $buttonclicked = "edit"; + $in->ask_from_ + ( + { title => N("Usage of remote scanners"), + messages => N("These are the machines from which the scanners should be used:"), + ok => "", + cancel => "", + }, + # List the hosts + [ { val => \$choice, format => \&translate, + sort => 0, separator => "####", + tree_expanded => 1, + quit_if_double_click => 1, + allow_empty_list => 1, + list => \@list }, + { val => N("Add host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "add"; + 1; + } }, + { val => N("Edit selected host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "edit"; + 1; + }, + disabled => sub { + return ($#list < 0); + } }, + { val => N("Remove selected host"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = "remove"; + 1; + }, + disabled => sub { + return ($#list < 0); + } }, + { val => N("Done"), + type => 'button', + clicked_may_quit => sub { + $buttonclicked = ""; + $subdone = 1; + 1; + } }, + ] + ); + if ($buttonclicked eq "add" || + $buttonclicked eq "edit") { + my ($hostchoice, $ip); + if ($buttonclicked eq "add") { + # Use first entry as default for a new entry + $hostchoice = + N("Name/IP address of host:"); + } else { + if ($menuimports->{$choice} eq 'localhost') { + # Entry is "This machine" + $hostchoice = $choice; + } else { + # Entry is a name/an IP address + $hostchoice = + N("Name/IP address of host:"); + $ip = $choice; + } + } + my @menu = (N("This machine"), + N("Name/IP address of host:")); + # Show the dialog + my $address; + my $oldaddress = + ($buttonclicked eq "edit" ? + $menuimports->{$choice} : ""); + if ($in->ask_from_ + ( + { title => N("Sharing of local scanners"), + messages => N("Choose the host on which the local scanners should be made available:"), + callbacks => { + complete => sub { + if ($hostchoice eq $menu[0]) { + $address = 'localhost'; + } elsif ($hostchoice eq $menu[1]) { + $address = $ip; + } + # Do not allow an empty address + if ($address !~ /\S/) { + $in->ask_warn(N("Scannerdrake"), + N("You must enter a host name or an IP address.\n")); + return (1,0); + } + # Strip off leading and trailing + # spaces + $address =~ s/^\s*(.*?)\s*$/$1/; + # Check whether item is duplicate + if (($address ne $oldaddress) && + (member("$address\n", + @imports))) { + $in->ask_warn(N("Scannerdrake"), + N("This host is already in the list, it cannot be added again.\n")); + return (1,1); + } + return 0; + }, + }, + }, + # List the host types + [ { val => \$hostchoice, format => \&translate, + type => 'list', + sort => 0, + list => \@menu }, + { val => \$ip, + disabled => sub { + $hostchoice ne + N("Name/IP address of host:"); + }}, + ], + )) { + # OK was clicked, insert new item into the list + if ($buttonclicked eq "add") { + handle_configs::set_directive(\@imports, + $address); + } else { + handle_configs::replace_directive(\@imports, + $oldaddress, + $address); + } + $importschanged = 1; + # Refresh list of hosts + ($menuimports, $menuimports_inv) = + makeimportmenues(@imports); + # Position the list cursor on the new/modified + # item + $choice = $menuimports_inv->{$address}; + } + } elsif ($buttonclicked eq "remove") { + my $address = $menuimports->{$choice}; + handle_configs::remove_directive(\@imports, + $address); + # Refresh list of hosts + ($menuimports, $menuimports_inv) = + makeimportmenues(@imports); + $importschanged = 1; + } + } + } else { + # We have clicked "OK" + $maindone = 1; + if ($importschanged) { + $changed = 1; + } + # Write /etc/sane.d/saned.conf + output("/etc/sane.d/saned.conf", @exports); + # Write /etc/sane.d/net.conf + output("/etc/sane.d/net.conf", @imports); + # Turn on/off saned + if ($sanedrunning != $oldsanedrunning) { + if ($sanedrunning) { + # Make sure saned and xinetd is installed and + # running + if (!files_exist('/usr/sbin/xinetd', + '/usr/sbin/saned')) { + $in->do_pkgs->install('xinetd', 'saned'); + } + # Start saned and make sure that it gets started on + # every boot + services::start_service_on_boot("saned"); + services::start_service_on_boot("xinetd"); + services::restart("xinetd"); + } else { + # Stop saned and make sure that it does not get + # started when booting + services::do_not_start_service_on_boot("saned"); + services::restart("xinetd"); + } + } + # Turn on/off "net" SANE backend + if ($netbackendactive != $oldnetbackendactive) { + my @dllconf = cat_("/etc/sane.d/dll.conf"); + if ($netbackendactive) { + handle_configs::set_directive(\@dllconf, "net"); + } else { + handle_configs::comment_directive(\@dllconf, "net"); + } + output("/etc/sane.d/dll.conf", @dllconf); + $changed = 1; + } + } + } else { + # Cancel clicked + $maindone = 1; + } + } + return $changed; +} -- cgit v1.2.1