#!/usr/bin/python
"""
	Name		: lpr.py
	Author		: David Boddie
	Created		: Tue 08th August 2000
	Last modified	: Thu 06th September 2001
	Purpose		: Send a file to a printer queue.
	Andy Valencia:
            Tidy up
	    Added option parser
	    Support for # of copies extension
"""
import socket, sys, optparse
from os import getenv

# Usage
def usage():
    print "Usage is: %s -P <printer name> [-s <print host>]" \
	" [-# <copies>]" % (sys.argv[0],)

# Parse command line
parser = optparse.OptionParser()
parser.add_option("-P", default=None, dest="printer")
parser.add_option("-s", default=None, dest="server")
parser.add_option("-#", type=int, default=1, dest="copies")
parser.add_option("-l", action="store_true", default=False, dest="verbose")
options, args = parser.parse_args()
parser.destroy()
del parser

# Get print server host
server = options.server
if not server:
    server = getenv('PRINTER_SERVER')
    if not server:
	print 'No printer server specified: use system variable PRINTER_SERVER'
	sys.exit(1)
server = server.strip()

# Get printer name, command arg or environment
printer = options.printer
if not printer:
    printer = getenv('PRINTER')
if not printer:
    printer = server
printer = printer.strip()

# Our hostname
host = socket.gethostname()

# The user doing the printing
user = getenv('USER')
if not user:
    print 'No user specified: use system variable USER'
    sys.exit(0)
user = user.strip()

# Print the next file
def do_lpr_file(filename, file):
    global server, host, user, printer

    # Determine the length of the file... also
    #  resets file position as needed for multiple
    #  copies.
    file.seek(0, 2)
    length = file.tell()
    file.seek(0, 0)

    # Attach to server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect( (server, 515) )

    # print "Expect to receive a job"
    s.send("\002"+printer+"\012")
    d = s.recv(1024)
    if (d != "\000"):
	    print d.strip()
	    s.send("\001\012")
	    s.close()
	    sys.exit(0)

    # Send the receive control file subcommand
    control = 'H' + host[:31] + "\012" + \
	'N' + filename[:131] + "\012" + \
	'P' + user[:31] + "\012" + \
	'o' + filename[:131] + "\012"

    # print "Send the receive control file subcommand"
    s.send("\002" + str(len(control)) + " cfA000" + host + "\012")
    d = s.recv(1024)
    if (d != "\000"):
	    print d.strip()
	    s.send("\001\012")
	    s.close()
	    sys.exit(0)

    # Send the control file
    # print "Send the control file"
    s.send(control)
    s.send("\000")

    # Wait for reply
    # print "Wait for reply"
    d = s.recv(1024)
    if (d != "\000"):
	    print d.strip()
	    s.send("\001\012")
	    s.close()
	    sys.exit(0)

    # Send the receive data file subcommand
    # print "Send the receive data file subcommand"
    s.send("\003" + str(length) + \
	" dfA000" + host + "\012")

    d = s.recv(1024)
    if (d != "\000"):
	    print d.strip()
	    s.send("\001\012")
	    s.close()
	    sys.exit(0)

    # Send the data file
    # print "Send the data file"
    pos = 0
    opct = -1
    basename = filename.split("/")[-1]
    while True:
	contents = file.readline()
	if not contents:
	    break
	s.send(contents)
	pos += len(contents)
	pct = int((pos*100) / length)
	if pct != opct:
	    sys.stdout.write("\r%s: %d%%" % (basename, pct,))
	    sys.stdout.flush()
	    opct = pct
    s.send("\000")

    # Wait for reply
    # print "Wait for reply"
    d = s.recv(1024)
    if (d != "\000"):
	print d.strip()
	s.send("\001\012")
	s.close()
	sys.exit(0)

    s.close()
    sys.stdout.write("\n")

# Print each file on the command line
def do_lpr(args):
    for filename in args:
	try:
	    file = open(filename, 'r')
	except:
	    print 'Could not find ' + filename
	    sys.exit(0)

	for idx in xrange(options.copies):
	    do_lpr_file(filename, file)
	file.close()

	# All copies of this file sent; close file
	file.close()

# Status of printer
def do_lpq(args):
    global server, printer, user

    if args:
	raise Exception, "No arguments for lpq"
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect( (server, 515) )
    if options.verbose:
	send_string = "\003"+printer+" "+user+"\012"
    else:
	send_string = "\004"+printer+" "+user+"\012"
    s.send(send_string)
    data = s.recv(1024)
    s.close()
    for l in data.split("\12"):
	print l.expandtabs(12)

# Behave as lpr?
cmd = sys.argv[0]
if "lpr" in cmd:
    if not args:
	raise Exception, "No files to print?"
    do_lpr(args)
elif "lpq" in cmd:
    do_lpq(args)
else:
    raise Exception, "Can dispatch via command name: %s" % cmd

sys.exit(0)
