123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059 |
- #!/usr/bin/python
- # $Id$
- # Update CUPS PPDs for Gutenprint queues.
- # Copyright (C) 2002-2003 Roger Leigh (rleigh@debian.org)
- # Copyright (C) 2009, 2011 Red Hat, Inc.
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2, or (at your option)
- # any later version.
- #
- # 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.
- import getopt
- import glob
- import os
- import re
- import stat
- import subprocess
- import sys
- global optargs
- global debug
- global verbose
- global interactive
- global quiet
- global no_action
- global reset_defaults
- global version
- global micro_version
- global use_static_ppd
- global file_version
- global ppd_dir
- global ppd_root_dir
- global ppd_base_dir
- global ppd_out_dir
- global gzext
- global updated_ppd_count
- global skipped_ppd_count
- global failed_ppd_count
- global exit_after_parse_args
- global languages
- global serverdir
- global driver_bin
- global driver_version
- global server_multicat
- global server_multicat_initialized
- global ppd_files
- global languagemappings
- def help():
- print """
- Usage: %s [OPTION]... [PPD_FILE]...
- Update CUPS+Gutenprint PPD files.
- -d flags Enable debugging
- -h Display this help text
- -n No-action. Don't overwrite any PPD files.
- -q Quiet mode. No messages except errors.
- -s ppd_dir Use ppd_dir as the source PPD directory.
- -p ppd_dir Update PPD files in ppd_dir.
- -P driver Use the specified driver binary to generate PPD files.
- -v Verbose messages.
- -N Reset options to defaults.
- -o out_dir Output PPD files to out_dir.
- -r version Use PPD files for Gutenprint major.minor version.
- -f Ignore new PPD file safety checks.
- -i Prompt (interactively) for each PPD file.
- -l language Language choice (Gutenprint 5.1 or below).
- Choices: %s
- Or -loriginal to preserve original language
- with Gutenprint 5.2 or above
- """ % (sys.argv[0],
- reduce (lambda x,y: "%s %s" % (x,y), languages))
- sys.exit (0)
- def die_if_not_directory (dir):
- try:
- st = os.stat (dir)
- if not st.S_ISDIR (st.st_mode):
- os.chdir (dir)
- except OSError, (e, s):
- print "%s: invalid directory: %s" % (dir, s)
- sys.exit (1)
- def get_driver_version():
- global server_multicat
- global driver_version
- def run_with_arg (arg):
- try:
- p = subprocess.Popen ([driver_bin, arg],
- stdin=file("/dev/null"),
- stdout=subprocess.PIPE,
- stderr=file("/dev/null", "w"),
- shell=False)
- (stdout, stderr) = p.communicate ()
- except OSError:
- return None
- return stdout
- stdout = run_with_arg ("org.gutenprint.extensions")
- if stdout == None:
- return
- for line in stdout.split ("\n"):
- if line == "org.gutenprint.multicat":
- server_multicat = 1
- break
- stdout = run_with_arg ("VERSION")
- if stdout == None:
- return
- driver_version = stdout.strip ()
- def parse_options():
- try:
- opts, args = getopt.getopt (sys.argv[1:], "d:hnqs:vNo:p:P:r:ifl:")
- except getopt.GetoptError:
- help ()
- global optargs
- global debug
- global verbose
- global interactive
- global quiet
- global no_action
- global reset_defaults
- global version
- global micro_version
- global use_static_ppd
- global file_version
- global ppd_dir
- global ppd_out_dir
- global ppd_base_dir
- global ppd_root_dir
- global serverdir
- global driver_bin
- global driver_version
- global server_multicat
- global languages
- optargs = dict()
- for opt, optarg in opts:
- optargs[opt[1]] = optarg
- if optargs.has_key ('n'):
- no_action = 1
- if optargs.has_key ('d'):
- try:
- debug = int (optargs['d'])
- except ValueError:
- d = 0
- if optargs.has_key ('v'):
- verbose = 1
- quiet = 0
- if optargs.has_key ('q'):
- verbose = 0
- quiet = 1
- if optargs.has_key ('N'):
- reset_defaults = 1
- if optargs.has_key ('o'):
- opt_o = optargs['o']
- die_if_not_directory (opt_o)
- ppd_out_dir = opt_o
- if optargs.has_key ('r'):
- opt_r = optargs['r']
- if version != opt_r:
- version = opt_r
- if optargs.has_key ('s'):
- opt_s = optargs['s']
- die_if_not_directory (opt_s)
- ppd_base_dir = opt_s
- driver_bin = ""
- server_multicat = 0
- use_static_ppd = "yes"
- else:
- ppd_base_dir = ppd_root_dir + "/gutenprint/" + version
- driver_bin = serverdir + "/driver/gutenprint." + version
- driver_version = ""
- # If user specifies version, we're not going to be able to check
- # for an exact match.
- file_version = '"' + version
- if os.access (driver_bin, os.X_OK):
- get_driver_version ()
- use_static_ppd = "no"
- file_version = "\"%s\"$" % driver_version
- else:
- print "Gutenprint %s does not appear to be installed!" % version
- sys.exit (1)
- if optargs.has_key ('s'):
- opt_s = optargs['s']
- die_if_not_directory (opt_s)
- ppd_base_dir = opt_s
- driver_bin = ""
- server_multicat = 0
- driver_version = ""
- use_static_ppd = "yes"
- if optargs.has_key ('p'):
- opt_p = optargs['p']
- die_if_not_directory (opt_p)
- ppd_dir = opt_p
- if optargs.has_key ('P'):
- opt_P = optargs['P']
- if os.access (opt_P, os.X_OK):
- driver_bin = opt_P
- get_driver_version ()
- use_static_ppd = "no"
- else:
- print "%s: invalid executable" % opt_P
- if optargs.has_key ('h'):
- help ()
- if (optargs.has_key ('l') and
- optargs['l'].lower () != "original" and
- optargs['l'].lower () not in languages):
- print >>sys.stderr, "Unknown language '%s'" % optargs['l']
- if optargs.has_key ('i'):
- interactive = 1
- if exit_after_parse_args:
- sys.exit (0)
- if verbose and driver_version != "":
- print "Updating PPD files from Gutenprint %s" % driver_version
- return args
- def update_ppd (ppd_source_filename):
- global ppd_dest_filename
- global ppd_out_dir
- global optargs
- global languagemappings
- global interactive
- global server_multicat
- global no_action
- global quiet, verbose
- global reset_defaults
- ppd_dest_filename = ppd_source_filename
- if ppd_out_dir:
- ppd_dest_filename = "%s/%s" % (ppd_out_dir,
- os.path.basename (ppd_dest_filename))
- orig = file (ppd_source_filename)
- orig_metadata = os.fstat (orig.fileno ())
- if debug & 1:
- print "Source Filename: %s" % ppd_source_filename
- filename = ""
- driver = ""
- gutenprintdriver = ""
- locale = ""
- lingo = ""
- region = ""
- valid = 0
- orig_locale = ""
- for line in orig.readlines ():
- line.rstrip ()
- if line.find ("*StpLocale:") != -1:
- match = re.search ("\*StpLocale:\s*\"(.*)\"$", line)
- if match:
- groups = match.groups ()
- if len (groups) >= 1:
- locale = groups[0]
- orig_locale = locale
- valid = 1
- elif line.startswith ("*LanguageVersion"):
- match = re.search ("^\*LanguageVersion:\s*(.*)$", line)
- if match:
- groups = match.groups ()
- if len (groups) >= 1:
- lingo = groups[0]
- elif line.startswith ("*StpDriverName:"):
- match = re.search ("^\*StpDriverName:\s*\"(.*)\"$", line)
- if match:
- groups = match.groups ()
- if len (groups) >= 1:
- driver = groups[0]
- valid = 1
- elif line.find ("*%End of ") != -1 and driver == "":
- match = re.search ("^\*%End of\s*(.*).ppd$", line)
- if match:
- groups = match.groups ()
- if len (groups) >= 1:
- driver = groups[0]
- elif line.startswith ("*StpPPDLocation:"):
- match = re.search ("^\*StpPPDLocation:\s*\"(.*)\"$", line)
- if match:
- groups = match.groups ()
- if len (groups) >= 1:
- filename = groups[0]
- valid = 1
- elif line.startswith ("*%Gutenprint Filename:"):
- valid = 1
- if filename and driver and lingo and locale:
- break
- if not valid and line.startswith ("*OpenUI"):
- break
- if not valid:
- #print >>sys.stderr, ("Skipping %s: not a Gutenprint PPD file" %
- # ppd_source_filename)
- return -1
- if (optargs.has_key ('l') and
- optargs['l'] != "" and
- optargs['l'].lower () != "original"):
- locale = optargs['l']
- orig_locale = locale
- if debug & 2:
- print "Gutenprint Filename: %s" % filename
- if optargs.has_key ('l'):
- print "Locale: %s (from -l)" % locale
- else:
- print "Locale: %s" % locale
- print "Language: %s" % lingo
- print "Driver: %s" % driver
- if locale:
- # Split into the language and territory.
- s = locale.split ("_", 1)
- locale = s[0]
- try:
- region = s[1]
- except IndexError:
- region = ""
- else:
- # Split into the language and territory.
- s = lingo.split ("_", 1)
- locale = s[0]
- try:
- region = s[1]
- except IndexError:
- region = ""
- # Convert language into language code.
- locale = languagemappings.get (lingo.lower (), "C")
- if debug & 2:
- print "Base Locale: %s" % locale
- print "Region: %s" % region
- # Read in the new PPD, decompressing it if needed...
- (new_ppd_filename, source_fd) = get_ppd_fh (ppd_source_filename,
- filename,
- driver,
- locale,
- region)
- if source_fd == None:
- print "Unable to retrieve PPD file!"
- return 0
- if interactive:
- inp = raw_input ("Update PPD %s from %s [nyq]? " % ppd_source_filename)
- inp = inp.lower ()
- if inp.startswith ("q"):
- if not server_multicat:
- source_fd.close ()
- print "Skipping all..."
- return -2
- elif not inp.startswith ("y"):
- if not server_multicat:
- source_fd.close ()
- print "Skipping..."
- return -1
- # Extract the default values from the original PPD...
- orig.seek (0)
- (odt, oopt, ores, odef, unused) = get_ppd_data (orig, 1, 0, 1, 1, 0)
- (ndt, nopt, nres, ndef, source_data) = get_ppd_data (source_fd,
- 1, 1, 1, 1, 1)
-
- # Close original and temporary files...
- orig.close ()
- if not server_multicat:
- source_fd.close ()
- orig_default_types = odt
- new_default_types = ndt
- defaults = odef
- new_defaults = ndef
- options = nopt
- resolution_map = nres
- old_resolution_map = dict()
- for key, value in resolution_map.iteritems ():
- old_resolution_map[value] = key
- # Store previous language in the PPD file so that -l original works
- # correctly.
- if orig_locale != "":
- lines = source_data.rstrip ().split ("\n")
- source_data = ""
- for line in lines:
- m = re.search ("(\*StpLocale:\s*\")(.*)(\")", line)
- if m:
- groups = m.groups ()
- line = groups[0] + orig_locale + groups[2]
- source_data += line + "\n"
- if debug & 4:
- print "Options (Old->New Default Type):"
- keys = options.keys ()
- keys.sort ()
- for t in keys:
- old_type = orig_default_types.get (t, "(New)")
- new_type = new_default_types.get (t)
- if old_type != new_type:
- out = " %s (%s -> %s) : " % (t, old_type, new_type)
- else:
- out = " %s (%s) : " % (t, new_type)
- dft = defaults.get ("Default%s" % t)
- for opt in options.get (t, []):
- if dft != None and dft == opt:
- out += "*"
- out += "%s " % opt
- print out
- if len (resolution_map.keys ()) > 0:
- print "Resolution Map:"
- keys = resolution_map.keys ()
- keys.sort ()
- for key in keys:
- print " %s: %s" % (key, resolution_map[key])
- if len (old_resolution_map.keys ()) > 0:
- print "Old Resolution Map:"
- keys = old_resolution_map.keys ()
- keys.sort ()
- for key in keys:
- print " %s: %s" % (key, old_resolution_map[key])
- print "Non-UI Defaults:"
- keys = defaults.keys ()
- keys.sort ()
- for key in keys:
- xkey = key
- if xkey.startswith ("Default"):
- xkey = xkey[7:]
- if not options.has_key (xkey):
- print " %s: %s" % (key, defaults[key])
- print "Default Types of dropped options:"
- keys = orig_default_types.keys ()
- keys.sort ()
- for t in keys:
- if not options.has_key (t):
- print " %s: %s" % (t, orig_default_types[t])
- if no_action:
- if not quiet or verbose:
- if ppd_dest_filename == ppd_source_filename:
- print "Would update %s using %s" % (ppd_source_filename,
- new_ppd_filename)
- else:
- print "Would update %s to %s using %s" % (ppd_source_filename,
- ppd_dest_filename,
- new_ppd_filename)
- return 0
- if not reset_defaults:
- # Update source buffer with old defaults...
- # Loop through each default in turn.
- keys = defaults.keys ()
- keys.sort ()
- for default_option in keys:
- default_option_value = defaults[default_option]
- option = default_option
- if option.startswith ("Default"):
- # Strip off `Default'
- option = option[7:]
- # Check method is valid
- orig_method = orig_default_types.get (option)
- new_method = new_default_types.get (option)
- new_default = new_defaults.get (default_option)
- if (orig_method == None or new_method == None or
- orig_method != new_method):
- continue
- if (new_default != None and
- default_option_value == new_default):
- if verbose:
- print "%s: Preserve *%s (%s)" % (ppd_source_filename,
- default_option,
- default_option_value)
- continue
- if new_method == "PickOne":
- next_default = False
- # Check the old setting is valid
- for opt in options.get (option, []):
- def_option = default_option_value
- odef_option = def_option
- if (option == "Resolution" and
- old_resolution_map.has_key (def_option)):
- if debug & 4:
- print ("Intermapping old resolution %s to %s" %
- def_option, old_resolution_map[def_option])
- def_option = old_resolution_map[def_option]
- dopts = [def_option]
- if def_option != odef_option:
- dopts.append (odef_option)
- for dopt in dopts:
- valid = False
- if dopt == opt:
- valid = True
- elif (option == "Resolution" and
- resolution_map.has_key (dopt)):
- dopt = resolution_map[dopt]
- if dopt == opt:
- valid = True
- if valid:
- # Valid option
- # Set the option in the new PPD
- lines = source_data.rstrip ().split ("\n")
- source_data = ""
- attr = "*%s" % default_option
- for line in lines:
- if line.startswith (attr):
- line = "%s:%s" % (attr, dopt)
- source_data += line + "\n"
- if verbose:
- print "%s: Set *%s to %s" % (ppd_source_filename,
- default_option,
- dopt)
- next_default = True
- break
- if next_default:
- break
- if next_default:
- continue
- print ("Warning: %s: Invalid option: *%s: %s. Using default "
- "setting %s." % (ppd_source_filename, default_option,
- defaults[default_option],
- new_defaults[default_option]))
- continue
- print ("Warning: %s: PPD OpenUI method %s not understood." %
- (ppd_source_filename, new_default_types[default_option]))
- # Write new PPD...
- tmpnew = "%s.new" % ppd_dest_filename
- try:
- newppd = file (tmpnew, "w")
- except IOError, (e, s):
- print "Can't create %s: %s" % (tmpnew, s)
- return 0
- newppd.writelines (source_data)
- try:
- newppd.close ()
- except IOError, (e, s):
- print "Can't write to %s: %s" % (tmpnew, s)
- return 0
- chcon = subprocess.Popen (["chcon", "--reference=%s" % ppd_dest_filename,
- tmpnew], shell=False,
- stdin=file("/dev/null"),
- stdout=file("/dev/null", "w"),
- stderr=subprocess.STDOUT)
- chcon.communicate ()
- try:
- os.rename (tmpnew, ppd_dest_filename)
- except OSError, (e, s):
- print "Can't rename %s to %s: %s" % (tmpnew, ppd_dest_filename, s)
- try:
- os.unlink (tmpnew)
- except OSError:
- pass
- return 0
- try:
- os.chown (ppd_dest_filename,
- orig_metadata.st_uid,
- orig_metadata.st_gid)
- except OSError:
- pass
- try:
- os.chmod (ppd_dest_filename,
- orig_metadata.st_mode & 0777)
- except OSError:
- pass
- if not quiet or verbose:
- if ppd_dest_filename == ppd_source_filename:
- print "Updated %s using %s" % (ppd_source_filename,
- new_ppd_filename)
- else:
- print "Updated %s to %s using %s" % (ppd_source_filename,
- ppd_dest_filename,
- new_ppd_filename)
- # All done!
- return 1
- def get_ppd_data (fh, types, opts, resolutions, defaults, data):
- options_map = dict()
- defaults_map = dict()
- resolution_map = dict()
- default_types = dict()
- cur_opt = ""
- optionlist = []
- source_data = ""
- if reset_defaults:
- types = 0
- opts = 0
- resolutions = 0
- defaults = 0
- if resolutions or types or opts or defaults or data:
- while True:
- line = fh.readline ()
- if line == '':
- break
- if line == "*%*%EOFEOF\n":
- break
- source_data += line
- line = line.strip ()
- if (types or opts) and line.startswith ("*OpenUI"):
- m = re.search ("^\*OpenUI\s\*(\w+).*:\s(\w+)",
- line)
- if m:
- groups = m.groups ()
- key = groups[0]
- value = groups[1]
- default_types[key] = value
- cur_opt = key
- elif opts and line.startswith ("*CloseUI"):
- if cur_opt != "":
- options_map[cur_opt] = optionlist
- cur_opt = ""
- optionlist = []
- elif opts and line.startswith ("*%s" % cur_opt):
- m = re.search ("^\*%s\s*(\w+)[\/:]" % cur_opt, line)
- if m:
- groups = m.groups()
- if len (groups) >= 1:
- value = m.groups ()[0]
- optionlist.append (value)
- elif resolutions and line.startswith ("*StpResolutionMap:"):
- s = line.split (None, 3)
- if len (s) == 3:
- new = s[1]
- old = s[2]
- resolution_map[old] = new
- elif defaults and line.startswith ("*Default"):
- m = re.search ("^\*(\w+):\s*(\w+)", line)
- if m:
- groups = m.groups ()
- key = groups[0]
- value = groups[1]
- defaults_map[key] = value
- return (default_types, options_map, resolution_map,
- defaults_map, source_data)
- def get_ppd_fh (ppd_source_filename, filename, driver, locale, region):
- global use_static_ppd
- global driver_version
- global optargs
- global driver_bin
- global debug
- global server_multicat, server_multicat_initialized
- global gzext
- if use_static_ppd == "no" and driver_version != "":
- if re.search (".*/([^/]*)(.sim)(.ppd)?(.gz)?$", filename):
- simplified = "simple"
- else:
- simplified = "expert"
- opt_r = optargs.get ('r')
- if opt_r:
- try:
- opt_r = float (opt_r)
- except ValueError:
- opt_r = None
- url_list = []
- if (((opt_r != None and opt_r < 5.2) or
- (optargs.has_key ('l') and optargs['l'] != "")) and
- locale != ""):
- if region:
- url_list.append ("gutenprint.%s://%s/%s/%s_%s" %
- version, driver, simplified, locale, region)
- url_list.append ("gutenprint.%s://%s/%s/%s" %
- version, driver, simplified, locale)
- url_list.append ("gutenprint.%s://%s/%s" % (version, driver,
- simplified))
- for url in url_list:
- new_ppd_filename = url
- if debug & 8:
- if server_multicat:
- cat = ""
- else:
- cat = "%s cat " % driver_bin
- print ("Trying %s%s for %s, %s, %s, %s" %
- (cat, url, driver, simplified, locale, region))
- if server_multicat:
- try:
- if not server_multicat_initialized:
- mc_proc = subprocess.Popen ([driver_bin,
- "org.gutenprint.multicat"],
- shell=False,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=file("/dev/null",
- "w"))
- server_multicat_initialized = mc_proc
- print >>server_multicat_initialized.stdin, "%s" % url
- server_multicat_initialized.stdin.flush ()
- return (new_ppd_filename,
- server_multicat_initialized.stdout)
- except OSError:
- pass
- try:
- proc = subprocess.Popen ([driver_bin, "cat", url],
- shell=False,
- stdin=file("/dev/null"),
- stdout=subprocess.PIPE,
- stderr=file("/dev/null", "w"))
- return (new_ppd_filename, proc.stdout)
- except OSError:
- pass
- # Otherwise fall through and try to find a static PPD
- # Search for a PPD matching our criteria...
- new_ppd_filename = find_ppd (filename, driver, locale, region)
- if not new_ppd_filename:
- # There wasn't a valid source PPD file, so give up.
- print >>sys.stderr, ("%s: no valid candidate for replacement. "
- "Skipping" % ppd_source_filename)
- print >>sys.stderr, ("%s: please upgrade this PPD manually" %
- ppd_source_filename)
- return ("", None)
- if debug & 1:
- print "Candidate PPD: %s" % new_ppd_filename
- suffix = "\\" + gzext # Add '\' so the regexp matches the '.'
- if new_ppd_filename.endswith (".gz"):
- # Decompress input buffer
- try:
- proc = subprocess.Popen (['gunzip', '-c', new_ppd_filename],
- shell=False,
- stdin=file("/dev/null"),
- stdout=subprocess.PIPE,
- stderr=file("/dev/null", "w"))
- except OSError, (e, s):
- print "can't open for decompression: %s" % s
- sys.exit (1)
- return (new_ppd_filename, proc.stdout)
- else:
- return (new_ppd_filename, file (new_ppd_filename))
- def find_ppd (gutenprintfilename, drivername, lang, region):
- global file_version
- global optargs
- global ppd_base_dir
- global ppd_root_dir
- global debug
- key = '^\\*FileVersion:[ ]*' + file_version
- match = re.search (".*/([^/]+\.[0-9]+\.[0-9]+)(\.sim)?(\.ppd)?(\.gz)?$",
- gutenprintfilename)
- if not match:
- return None
- stored_name = match.groups ()[0]
- if re.search (".*/([^/]*)(\.sim)(\.ppd)?(\.gz)?$", gutenprintfilename):
- simplified = ".sim"
- else:
- simplified = ""
- stored_dir = os.path.dirname (gutenprintfilename)
- current_best_file = ""
- current_best_time = 0
- if optargs.has_key ('s'):
- basedirs = [optargs['s']]
- else:
- basedirs = [ppd_base_dir, stored_dir, ppd_root_dir]
- lingos = []
- if region != "":
- lingos.append ("%s_%s/" % (lang, region))
- lingos.append ("%s/" % lang)
- if lang != "C":
- lingos.append ("C/")
- lingos.append ("en/")
- lingos.append ("")
- lingos.append ("Global/")
- bases = ["stp-%s.%s%s" % (drivername, version, simplified),
- "%s.%s%s" % (drivername, version, simplified)]
- if stored_name not in bases:
- bases.append (stored_name)
- bases.append (drivername)
- # All possible candidates, in order of usefulness and gzippedness
- for lingo in lingos:
- for suffix in (".ppd%s" % gzext,
- ".ppd"):
- for base in bases:
- for basedir in basedirs:
- if basedir == "" or base == "":
- continue
- fn = "%s/%s%s%s" % (basedir, lingo, base, suffix)
- if debug & 8:
- print ("Trying %s for %s, %s, %s" %
- (fn, gutenprintfilename, lang, region))
- try:
- st = os.stat (fn)
- except OSError:
- continue
- if (optargs.has_key ('f') or
- (stat.S_ISREG (st.st_mode) and
- st.st_uid == 0)):
- # Check that the file is a valid Gutenprint PPD file
- # of the correct version.
- if fn.endswith (".gz"):
- cmdline = "gunzip -c '%s' | grep '%s'" % (fn, key)
- else:
- cmdline = "cat '%s' | grep '%s'" % (fn, key)
- try:
- p = subprocess.Popen (cmdline,
- stdin=file("/dev/null"),
- stdout=subprocess.PIPE,
- stderr=file("/dev/null", "w"))
- except OSError:
- new_file_version = ""
- else:
- (stdin, stderr) = p.communicate ()
- new_file_version = stdin.rstrip ()
- if new_file_version != "":
- if debug & 8:
- print (" Format valid: time %s best %s "
- "prev %s cur %s!" %
- (st.st_mtime, current_best_time,
- current_best_file, fn))
- if st.st_mtime > current_best_time:
- current_best_time = st.st_mtime
- current_best_file = fn
- if debug & 8:
- print >>sys.stderr, ("***current_best_file "
- " is %s" % fn)
- elif debug & 8:
- print " Format invalid"
- else:
- if (not stat.S_ISDIR (st.st_mode) and
- not fn.endswith ("/")):
- print >>sys.stderr, ("%s: not a regular file, "
- "or insecure ownership and "
- "permissions. Skipped" % fn)
- if current_best_file:
- return current_best_file
- # Yikes! Cannot find a valid PPD file!
- return None
- debug=0
- verbose=0
- interactive=0
- quiet=0
- no_action=0
- reset_defaults=0
- version="@GUTENPRINT_MAJOR_VERSION@.@GUTENPRINT_MINOR_VERSION@"
- micro_version="@GUTENPRINT_VERSION@"
- use_static_ppd="@BUILD_CUPS_PPDS@"
- file_version='"@VERSION@"$'
- ppd_dir = "@cups_conf_serverroot@/ppd"
- ppd_root_dir = "@cups_conf_datadir@/model";
- ppd_base_dir = ppd_root_dir + "/gutenprint/" + version
- ppd_out_dir = ""
- gzext = ".gz"
- updated_ppd_count = 0
- skipped_ppd_count = 0
- failed_ppd_count = 0
- exit_after_parse_args = 0
- languages=["Global", "C"] + "@ALL_LINGUAS@".split (' ')
- serverdir = "@cups_conf_serverbin@"
- driver_bin = serverdir + "/driver/gutenprint." + version
- driver_version = ""
- server_multicat = 0
- server_multicat_initialized = 0
- if os.access (driver_bin, os.X_OK):
- get_driver_version ()
- ppd_files = []
- languagemappings = { "chinese": "cn",
- "danish": "da",
- "dutch": "nl",
- "english": "en",
- "finnish": "fi",
- "french": "fr",
- "german": "de",
- "greek": "el",
- "hungarian": "hu",
- "italian": "it",
- "japanese": "jp",
- "norwegian": "no",
- "polish": "pl",
- "portuguese": "pt",
- "russian": "ru",
- "slovak": "sk",
- "spanish": "es",
- "swedish": "sv",
- "turkish": "tr" }
- # Check command-line options...
- args = parse_options()
- # Set a secure umask...
- os.umask (0177)
- # Find all in-use Gutenprint PPD files...
- # For case-insensitive filesystems, use only one of .ppd and .PPD
- # (bug 1929738)
- for f in args:
- if (os.access (f, os.F_OK) and
- (f.lower ().endswith (".ppd") or
- f.find ("/") != -1)):
- ppd_files.append (f)
- elif os.access ("%s/%s" % (ppd_dir, f), os.F_OK):
- ppd_files.append ("%s/%s" % (ppd_dir, f))
- elif os.access ("%s/%s.ppd" % (ppd_dir, f), os.F_OK):
- ppd_files.append ("%s/%s.ppd" % (ppd_dir, f))
- elif os.access ("%s/%s.PPD" % (ppd_dir, f), os.F_OK):
- ppd_files.append ("%s/%s.PPD" % (ppd_dir, f))
- else:
- print >>sys.stderr, ("Cannot find file %s/%s, %s/%s.ppd, or %s/%s.PPD" %
- ppd_dir, f, ppd_dir, f, ppd_dir, f)
- if len (args) == 0:
- ppdtmp = glob.glob ("%s/*.ppd" % ppd_dir)
- ppdtmp += glob.glob ("%s/*.PPD" % ppd_dir)
- ppd_map = dict()
- for each in ppdtmp:
- ppd_map[each] = 1
- for f in ppdtmp:
- if f.endswith (".PPD"):
- g = f[:-4] + ".ppd"
- if not ppd_map.has_key (g):
- ppd_files.append (f)
- else:
- ppd_files.append (f)
- # Update each of the Gutenprint PPDs, where possible...
- for ppd_file in ppd_files:
- status = update_ppd (ppd_file)
- if status == -2:
- break
- elif status == 0:
- failed_ppd_count += 1
- elif status == 1:
- updated_ppd_count += 1
- elif status == -1:
- skipped_ppd_count += 1
- if (not quiet) or verbose:
- if len (ppd_files) == 0:
- print "No Gutenprint PPD files to update."
- elif updated_ppd_count > 0:
- plural = ""
- if updated_ppd_count != 1:
- plural = "s"
- print "Updated %d PPD file%s" % (updated_ppd_count, plural)
- if ((not optargs.has_key ('o')) or
- optargs['o'] != ""):
- print "Restart cupsd for the changes to take effect."
- else:
- if failed_ppd_count > 0:
- print "Failed to update any PPD files"
- else:
- print "Did not update any PPD files"
- sys.exit (failed_ppd_count > 0)
|