summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xperl-install/scanner.pm153
-rw-r--r--perl-install/services.pm9
-rwxr-xr-xperl-install/standalone/scannerdrake621
3 files changed, 736 insertions, 47 deletions
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 = <LIST>) {
+ 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 = <DETECT>) {
+ 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 = <F>) {
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;
+}