source: trunk/debathena/config/printing-config/files/usr/bin/lpr.debathena @ 24519

Revision 24519, 7.3 KB checked in by broder, 14 years ago (diff)
In printing-config, don't blindly fall back on LPRng if we're not using CUPS.
  • Property svn:executable set to *
RevLine 
[23055]1#!/usr/bin/python
2
3# lpr.debathena
4#
5# also lp.debathena, lpq.debathena, and lprm.debathena
6#
7# Wrapper script that intelligently determines whether a command was
8# intended for should go to CUPS or LPRng and sends it off in the
9# right direction
10
[24201]11import cups
[23157]12import hesiod
[23055]13import getopt
14import os
[23950]15import shlex
[24201]16import socket
[23055]17import sys
18from subprocess import call, PIPE
19
[24515]20from debathena import printing
21
[24201]22try:
23    cupsd = cups.Connection()
24except RuntimeError: # Is this actually safer than "except:"?
25    cupsd = None
26
27def hesiod_lookup(hes_name, hes_type):
[24209]28    """A wrapper with somewhat graceful error handling."""
[24201]29    try:
30        h = hesiod.Lookup(hes_name, hes_type)
31        if len(h.results) > 0:
32            return h.results
[24265]33    except IOError:
34        return []
[24201]35
[23950]36def lpropt_transform(args):
37    if 'LPROPT' in os.environ:
[24001]38        return shlex.split(os.environ['LPROPT']) + args
[23950]39    return args
40
[23945]41def zephyr_transform(options):
[23954]42    zephyr = True
43    return_options = []
44    for o, a in options:
[24216]45        if o == '-N':
46            zephyr = False
[23954]47        else:
48            return_options.append((o, a))
[23945]49
[23954]50    if zephyr and os.environ.get('ATHENA_USER'):
51        return_options.append(('-m', 'zephyr%' + os.environ['ATHENA_USER']))
[23945]52
[23954]53    return return_options
54
[23055]55opts = {
[23847]56    'cups': {
[24201]57        'lp': ('EU:cd:h:mn:o:q:st:H:P:i:', None, '-d'),
58        'lpq': ('EU:h:P:al', None, '-P'),
[24374]59        'lpr': ('EH:U:P:#:hlmo:pqrC:J:T:',
60            (lpropt_transform, zephyr_transform), '-P'),
[24201]61        'lprm': ('EU:h:P:', None, '-P'),
[23847]62    },
63    'lprng': {
[24201]64        'lp': ('ckmprswBGYd:D:f:n:q:t:', None, '-d'),
65        'lpq': ('aAlLVcvP:st:D:', None, '-P'),
[24216]66        'lpr': ('ABblC:D:F:Ghi:kJ:K:#:m:NP:rR:sT:U:Vw:X:YZ:z1:2:3:4:',
[24201]67            (lpropt_transform, zephyr_transform), '-P'),
68        'lprm': ('aAD:P:VU:', None, '-P'),
[23847]69    }
[23055]70}
71
72def error(code, message):
73    """Exit out with an error
74    """
75    sys.stderr.write(message)
76    sys.exit(code)
77
[24201]78def execCups(command, queue, args):
79    """Pass the command and arguments on to the CUPS versions of the command
[23055]80    """
[24201]81    new_command = '/usr/bin/cups-%s' % command
82    os.execv(new_command, [command] + args)
[23055]83
[24201]84def execLprng(command, queue, args):
85    """Pass the command and arguments on to the LPRng versions of the command
[23055]86    """
[24201]87    new_command = '/usr/bin/mit-%s' % command
88    os.execv(new_command, [command] + args)
[23055]89
[24201]90def getPrintQueue(command, args):
[23055]91    """Given argv, extract the printer name, using knowledge of the possible
92    command line options for both the CUPS and LPRng versions of the command
[23847]93    that this script was called as. Also, return whether the command line
94    options imply a particular version of the command.
[23055]95    """
[24201]96
97    preference = 'cups'
98    for version in ['cups', 'lprng']:
[23847]99        try:
100            # Get the set of options that correspond to the command that this
101            # script was invoked as
[24201]102            (cmd_opts, transformers, destopt) = opts[version][command]
[23950]103            if transformers:
104                (transform_args, transform_opts) = transformers
105            else:
[24001]106                transform_args = transform_opts = lambda x: x
[23847]107        except KeyError:
108            error(1, """
109Error: this script was called as %s, when it must be called as
[24202]110one of lpr, lpq, lprm, or lp
[23847]111
112""" % command)
113
114        # Attempt to parse it with the current version of this command
[24001]115        targs = transform_args(args)
[23847]116        try:
[24001]117            options, realargs = getopt.gnu_getopt(targs, cmd_opts)
[23847]118        except getopt.GetoptError:
119            # That's the wrong version, so try the next one.
120            continue
121
[24001]122        options = transform_opts(options)
123        ttargs = [o + a for o, a in options] + realargs
[24201]124        if destopt:
125            for o, a in options:
126                if o == destopt:
127                    return (version, a, ttargs)
128        else:
129            if len(realargs) > 0:
130                return (version, realargs[0], ttargs)
[23847]131        # Since we've successfully getopt'd, don't try any other versions,
132        # but do note that we like this version.
133        preference = version
134        break
135
[24201]136    # Either we failed to getopt, or nobody told us what printer to use,
137    # so let's use the default printer
[23157]138    default = os.getenv('PRINTER')
[24201]139    if not default:
140        if cupsd:
141            default = cupsd.getDefault()
142    if not default:
143        h = hesiod_lookup(os.uname()[1], 'cluster')
144        for result in h:
[24227]145            (key, value) = result.split(None, 1)
[24201]146            if key == 'lpr':
147                default = value
148
[23157]149    if default:
[23945]150        return (preference, default, args)
[24201]151    else:
152        error(2, """
153No default printer configured. Specify a -P option, or configure a
154default printer via e.g. System | Administration | Printing.
155
156""")
157
158def translate_lprng_args_to_cups(command, args):
159    # TODO yell at user if/when we decide that these args are deprecated
160
161    # If getopt fails, something went very wrong -- _we_ generated this
162    options, realargs = getopt.gnu_getopt(args, opts['lprng'][command][0])
163    cupsargs = []
164    for (o, a) in options:
165        if o in ('-a') and command == 'lpq':
166            cupsargs += [('-a', a)]
167        elif o in ('-b', '-l') and command == 'lpr':
168            cupsargs += [('-l', a)]
169        elif o in ('-h') and command == 'lpr':
170            cupsargs += [('-h', a)]
171        elif o in ('-J') and command == 'lpr':
172            cupsargs += [('-J', a)]
173        elif o in ('-K', '-#') and command == 'lpr':
174            cupsargs += [('-#', a)]
175        elif o in ('-P'):
176            cupsargs += [('-P', a)]
177        elif o in ('-T') and command == 'lpr':
178            cupsargs += [('-T', a)]
179        elif o in ('-U') and command == 'lpr':
180            cupsargs += [('-U', a)]
181        elif o in ('-v') and command == 'lpq':
182            cupsargs += [('-l', a)]
183        elif o in ('-Z') and command == 'lpr':
184            if a == 'simplex':
185                cupsargs += [('-o', 'sides=one-sided')]
186            elif a == 'duplex':
187                cupsargs += [('-o', 'sides=two-sided-long-edge')]
188            elif a == 'duplexshort':
189                cupsargs += [('-o', 'sides=two-sided-short-edge')]
190            # TODO attempt to deal banner=staff
191        elif o in ('-m') and command == 'lpr':
192            # TODO figure out if CUPS can do mail/zephyr
193            pass # Don't warn about this, we probably generated it
[23157]194        else:
[24201]195            sys.stderr.write("Warning: option %s%s not converted to CUPS\n"
196                             % (o, a))
197    joincupsargs = [o + a for o, a in cupsargs] + realargs
198    sys.stderr.write("Using cups-%s %s\n" % (command, ' '.join(joincupsargs)))
199    return joincupsargs
[23055]200
201if __name__ == '__main__':
202    # Remove the command name from the arguments when we extract it
203    command = os.path.basename(sys.argv.pop(0))
[23847]204
205    # Determine if the arguments prefer one version of this command,
[24201]206    # For instance, "lpr -Zduplex" wants mit-lpr.
[24515]207    preference, queue, args = getPrintQueue(command, sys.argv)
[23847]208
[24515]209    system, server, queue = printing.find_queue(queue)
[24209]210
[24515]211    if system == printing.SYSTEM_CUPS:
212        if preference == 'lprng':
213            args = translate_lprng_args_to_cups(command, args)
214        if server:
215            os.environ['CUPS_SERVER'] = server
[24201]216        execCups(command, queue, args)
[24519]217    elif system == printing.SYSTEM_LPRNG:
218        execLprng(command, queue, args)
[24515]219    else:
[24519]220        error(1, """
221Error: the print queue %s uses an unknown printing infrastructure
222
223""" % queue)
Note: See TracBrowser for help on using the repository browser.