#!/usr/bin/perl -w

use strict;

use Expect;

# sshlpd - LPD over SSH for CUPS
# http://twofoos.org/content/labprinting/
#
# Copyright (C) 2006 Christopher Povirk <beigetangerine@gmail.com>
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of version 2 of the GNU General Public License as
#  published by the Free Software Foundation.
#
#  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.
#
#  (Or visit http://www.gnu.org/copyleft/gpl.html for the HTML version.)

# Large portions taken from beh (Backend Error Handler) by Till Kamppeter,
# also available under the GPL.
#
# http://www.linuxprinting.org/beh.html

my $SSH_PASSWORD_DIRECTORY = '/etc/sshpassword';
my $TIMEOUT = 10;
# TODO would be nice if we didn't have to specify the location of lpr
my $REMOTE_LPR = '/usr/ucb/lpr';

my $tempFile;

sub cleanUp();
sub dieCleanly(@);

sub cleanUp()
{
  unlink $tempFile if $tempFile;
}

sub dieCleanly(@)
{
  cleanUp();
  die @_;
}

$0 =~ m!^(.*)/([^/]+)\s*$!;
my $progname = ($2 || $0);

if(!$ARGV[0])
{
  print qq#network $progname "Unknown" "LPD over SSH Login"\n#;
  exit 0;
}

if(scalar(@ARGV) < 5 || scalar(@ARGV) > 6)
{
  print STDERR "ERROR: Usage: $progname job-id user title copies options [file]\n";
  exit 1;
}

my ($jobID, $userName, $jobTitle, $copies, $printOptions, $printFile) = @ARGV;

$jobTitle =~ s#\\#\\\\#g;
$jobTitle =~ s#"#\\"#g;
$jobTitle =~ s#\$#\\\$#g;

if(!$printFile)
{ 
  my $jid = $jobID;
  my $uid = $userName;
  $jid =~ s/\W//g; #sanity check
  $uid =~ s/\W//g; #sanity check
  $tempFile = "$ENV{TMPDIR}/$jid-$uid-cupsjob";

  open(OUT, ">$tempFile") or die "ERROR: Cannot write $tempFile: $!\n";

  while(<STDIN>)
  {
    print OUT "$_";
  }

  close OUT;

  $printFile = $tempFile;

  # Backends should only produce multiple copies if a file name is 
  # supplied (see CUPS Software Programmers Manual)
  $copies = 1;
}

my $uri = $ENV{DEVICE_URI};
$uri =~ m#$progname://([^/:]+)\@([^/:]+)/([^/]+)# or dieCleanly(qq#URI must be "$progname://user\@host/destination"\n#);
my ( $user, $host, $destination ) = ( $1, $2, $3 );
my $connectToString = "$user\@$host";

my $whoami = `whoami`; chomp $whoami;

my $passwordFile = "$SSH_PASSWORD_DIRECTORY/$connectToString";
open(PASSWORD_FILE, '<', $passwordFile) or dieCleanly(qq#No password info for "$connectToString"; create "$passwordFile" and make sure it is readable by user $whoami (but not by other users, or they will be able to see your password!).\n#);
my $password = <PASSWORD_FILE>; chomp $password;
close(PASSWORD_FILE);

for(my $i = 0; $i < $copies; $i++)
{
  my $command = qq#ssh '$connectToString' '$REMOTE_LPR -P "$destination" -T "$jobTitle"' < '$printFile'#;
  my $expect = Expect->spawn($command) or dieCleanly("Cannot spawn ssh process: $!\n");

  $expect->expect($TIMEOUT,
                  [ qr/.*password: / => sub { my $exp = shift; $exp->send("$password\n"); exp_continue; } ]
                 );

  $expect->soft_close();

  dieCleanly(qq#ssh returned $? ($i of $copies copies printed): $!\nTry running "ssh $connectToString" as user $whoami (try running "sudo -u $whoami ssh $connectToString" as root) and see if it works.\nThere are at least two potential problems, both relating to host keys.\nFirst, you may simply need to accept the host key.\nIf so, once you have accepted the key, you should be able to print.\nIf that doesn't work, then it may be the case that $whoami has no home directory and thus nowhere to save the keys.\nIf so, you'll have to create a home directory for $whoami.\nTry "grep $whoami /etc/passwd"; the sixth field in ${whoami}'s column is the home directory.\nAs root, create it and change the owner to $whoami with "chown ${whoami}:${whoami} <directory>".\nThen run the ssh command listed above again, accepting the host key, and try printing again.\n#) if $expect->exitstatus();
}

cleanUp();
