- Applied some udev-configure-printer fixes from upstrema.

This commit is contained in:
Tim Waugh 2009-07-23 13:47:54 +00:00
parent 7a4b5a7e63
commit 7f628c6513
2 changed files with 328 additions and 1 deletions

View File

@ -0,0 +1,322 @@
diff --git a/udev/udev-add-printer b/udev/udev-add-printer
index 03d301e..2e4d933 100755
--- a/udev/udev-add-printer
+++ b/udev/udev-add-printer
@@ -27,13 +27,11 @@ import sys
import traceback
from syslog import *
-def create_queue (c, name, device_uri, ppdname, info):
+def create_queue (c, printernames, name, device_uri, ppdname, info):
# Make sure the name is unique.
- printers = cupshelpers.getPrinters (c)
- names = printers.keys ()
- if name in names:
+ if name in printernames:
suffix = 2
- while (name + "-" + str (suffix)) in names:
+ while (name + "-" + str (suffix)) in printernames:
suffix += 1
if suffix == 100:
break
@@ -83,7 +81,10 @@ def add_queue (device_id, device_uris, is_fax=False):
name = name.replace ("/", "-")
name = name.replace ("#", "-")
- create_queue (c, name, device_uris[0], ppdname,
+ printers = cupshelpers.getPrinters (c)
+ printernames = printers.keys ()
+
+ create_queue (c, printernames, name, device_uris[0], ppdname,
"%s %s" % (id_dict["MFG"], id_dict["MDL"]))
if not is_fax:
@@ -93,24 +94,8 @@ def add_queue (device_id, device_uris, is_fax=False):
# find one whose scheme ends in "fax", use that as a fax
# queue. Note that the HPLIP backends do follow this
# pattern (hp and hpfax).
- not_fax_schemes=["beh",
- "bluetooth",
- "http",
- "https",
- "ipp",
- "lpd",
- "parallel",
- "serial",
- "smb",
- "snmp",
- "socket",
- "scsi",
- "usb"]
- devices = c.getDevices (exclude_schemes=not_fax_schemes)
- for uri, device_dict in devices.iteritems ():
- if uri in device_uris:
- continue
-
+ used_uris = map (lambda x: x.device_uri, printers.values ())
+ for uri in device_uris[1:]:
if uri.find (":") == -1:
continue
@@ -119,8 +104,20 @@ def add_queue (device_id, device_uris, is_fax=False):
# Now see if the non-scheme parts of the URI match
# any of the URIs we were given.
for each_uri in device_uris:
+ if each_uri == uri:
+ continue
(s, device_uri_rest) = each_uri.split (":", 1)
if rest == device_uri_rest:
+ # This one matches. Check there is not
+ # already a queue using this URI.
+ if uri in used_uris:
+ break
+
+ devices = c.getDevices (include_schemes=[scheme])
+ device_dict = devices.get (uri)
+ if device_dict == None:
+ break
+
add_queue (device_dict.get ("device-id", ""),
[uri], is_fax=True)
else:
diff --git a/udev/udev-configure-printer.c b/udev/udev-configure-printer.c
index a3c87dc..37a8682 100644
--- a/udev/udev-configure-printer.c
+++ b/udev/udev-configure-printer.c
@@ -708,7 +708,7 @@ cupsDoRequestOrDie (http_t *http,
static int
find_matching_device_uris (struct device_id *id,
- const char *serial,
+ const char *usbserial,
struct device_uris *uris,
const char *devpath)
{
@@ -716,21 +716,34 @@ find_matching_device_uris (struct device_id *id,
ipp_t *request, *answer;
ipp_attribute_t *attr;
struct device_uris uris_noserial;
+ struct device_uris all_uris;
+ size_t i, n;
+ const char *exclude_schemes[] = {
+ "beh",
+ "bluetooth",
+ "http",
+ "https",
+ "ipp",
+ "lpd",
+ "ncp",
+ "parallel",
+ "scsi",
+ "smb",
+ "snmp",
+ "socket",
+ };
- uris->n_uris = 0;
- uris->uri = NULL;
-
- uris_noserial.n_uris = 0;
- uris_noserial.uri = NULL;
+ uris->n_uris = uris_noserial.n_uris = all_uris.n_uris = 0;
+ uris->uri = uris_noserial.uri = all_uris.uri = NULL;
/* Leave the bus to settle. */
sleep (1);
cups = cups_connection ();
request = ippNewRequest (CUPS_GET_DEVICES);
- ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "include-schemes",
- sizeof (device_uri_types) / sizeof(device_uri_types[0]),
- NULL, device_uri_types);
+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_NAME, "exclude-schemes",
+ sizeof (exclude_schemes) / sizeof(exclude_schemes[0]),
+ NULL, exclude_schemes);
answer = cupsDoRequestOrDie (cups, request, "/");
httpClose (cups);
@@ -757,6 +770,28 @@ find_matching_device_uris (struct device_id *id,
parse_device_id (attr->values[0].string.text, &this_id);
}
+ /* Only use device schemes in our preference order for matching
+ * against the IEEE 1284 Device ID. */
+
+ for (i = 0;
+ device_uri &&
+ i < sizeof (device_uri_types) / sizeof (device_uri_types[0]);
+ i++)
+ {
+ size_t len = strlen (device_uri_types[i]);
+ if (!strncmp (device_uri_types[i], device_uri, len) &&
+ device_uri[len] == ':')
+ break;
+ }
+
+ if (device_uri)
+ add_device_uri (&all_uris, device_uri);
+
+ if (i == sizeof (device_uri_types) / sizeof (device_uri_types[0]))
+ /* Not what we want to match against. Ignore this one. */
+ device_uri = NULL;
+
+ /* Now check the manufacturer and model names. */
if (device_uri && this_id.mfg && this_id.mdl &&
!strcmp (this_id.mfg, id->mfg) &&
!strcmp (this_id.mdl, id->mdl))
@@ -803,11 +838,11 @@ find_matching_device_uris (struct device_id *id,
match = 1;
}
- if (!match && strlen (serial) >= 12)
+ if (!match && usbserial[0] != '\0')
{
if (!id->sern)
{
- if (this_id.sern && !strcmp (serial, this_id.sern))
+ if (this_id.sern && !strcmp (usbserial, this_id.sern))
{
syslog (LOG_DEBUG,
"SERN field matches USB serial number");
@@ -819,10 +854,11 @@ find_matching_device_uris (struct device_id *id,
{
char *saveptr, *uri = strdup (device_uri);
const char *token;
- for (token = strtok_r (uri, "?=&", &saveptr);
+ const char *sep = "?=&/";
+ for (token = strtok_r (uri, sep, &saveptr);
token;
- token = strtok_r (NULL, "?=&", &saveptr))
- if (!strcmp (token, serial))
+ token = strtok_r (NULL, sep, &saveptr))
+ if (!strcmp (token, usbserial))
{
syslog (LOG_DEBUG, "URI contains USB serial number");
match = 1;
@@ -886,14 +922,56 @@ find_matching_device_uris (struct device_id *id,
uris->uri = old;
else
{
- size_t i;
for (i = 0; i < uris_noserial.n_uris; i++)
uris->uri[uris->n_uris + i] = uris_noserial.uri[i];
uris->n_uris += uris_noserial.n_uris;
}
+
+ uris_noserial.n_uris = 0;
+ uris_noserial.uri = NULL;
}
free_device_uris (&uris_noserial);
+
+ /* Having decided which device URIs match based on IEEE 1284 Device
+ * ID, we now need to look for "paired" URIs for other functions of
+ * a multi-function device. This are the same except for the
+ * scheme. */
+
+ n = uris->n_uris;
+ for (i = 0; i < n; i++)
+ {
+ size_t j;
+ char *me = uris->uri[i];
+ char *my_rest = strchr (me, ':');
+ size_t my_schemelen;
+ if (!my_rest)
+ continue;
+
+ my_schemelen = my_rest - me;
+ for (j = 0; j < all_uris.n_uris; j++)
+ {
+ char *twin = all_uris.uri[j];
+ char *twin_rest = strchr (twin, ':');
+ size_t twin_schemelen;
+ if (!twin_rest)
+ continue;
+
+ twin_schemelen = twin_rest - twin;
+ if (my_schemelen == twin_schemelen &&
+ !strncmp (me, twin, my_schemelen))
+ /* This is the one we are looking for the twin of. */
+ continue;
+
+ if (!strcmp (my_rest, twin_rest))
+ {
+ syslog (LOG_DEBUG, "%s twinned with %s", me, twin);
+ add_device_uri (uris, twin);
+ }
+ }
+ }
+
+ free_device_uris (&all_uris);
if (uris->n_uris > 0)
{
struct usb_uri_map *map = read_usb_uri_map ();
@@ -1048,12 +1126,12 @@ do_add (const char *cmd, const char *devpath)
struct device_id id;
struct device_uris device_uris;
char *usb_device_devpath;
- char serial[256];
+ char usbserial[256];
syslog (LOG_DEBUG, "add %s", devpath);
usb_device_devpath = device_id_from_devpath (devpath, &id,
- serial, sizeof (serial));
+ usbserial, sizeof (usbserial));
if (!id.mfg || !id.mdl)
{
syslog (LOG_ERR, "invalid or missing IEEE 1284 Device ID%s%s",
@@ -1063,28 +1141,31 @@ do_add (const char *cmd, const char *devpath)
}
syslog (LOG_DEBUG, "MFG:%s MDL:%s SERN:%s serial:%s", id.mfg, id.mdl,
- id.sern ? id.sern : "-", serial);
-
- if ((pid = fork ()) == -1)
- syslog (LOG_ERR, "Failed to fork process");
- else if (pid != 0)
- /* Parent. */
- exit (0);
-
- close (STDIN_FILENO);
- close (STDOUT_FILENO);
- close (STDERR_FILENO);
- f = open ("/dev/null", O_RDWR);
- if (f != STDIN_FILENO)
- dup2 (f, STDIN_FILENO);
- if (f != STDOUT_FILENO)
- dup2 (f, STDOUT_FILENO);
- if (f != STDERR_FILENO)
- dup2 (f, STDERR_FILENO);
-
- setsid ();
-
- find_matching_device_uris (&id, serial, &device_uris, usb_device_devpath);
+ id.sern ? id.sern : "-", usbserial);
+
+ if (getenv ("DEBUG") == NULL)
+ {
+ if ((pid = fork ()) == -1)
+ syslog (LOG_ERR, "Failed to fork process");
+ else if (pid != 0)
+ /* Parent. */
+ exit (0);
+
+ close (STDIN_FILENO);
+ close (STDOUT_FILENO);
+ close (STDERR_FILENO);
+ f = open ("/dev/null", O_RDWR);
+ if (f != STDIN_FILENO)
+ dup2 (f, STDIN_FILENO);
+ if (f != STDOUT_FILENO)
+ dup2 (f, STDOUT_FILENO);
+ if (f != STDERR_FILENO)
+ dup2 (f, STDERR_FILENO);
+
+ setsid ();
+ }
+
+ find_matching_device_uris (&id, usbserial, &device_uris, usb_device_devpath);
free (usb_device_devpath);
if (device_uris.n_uris == 0)
{

View File

@ -7,13 +7,14 @@
Summary: A printer administration tool
Name: system-config-printer
Version: 1.1.10
Release: 1%{?dist}
Release: 2%{?dist}
License: GPLv2+
URL: http://cyberelk.net/tim/software/system-config-printer/
Group: System Environment/Base
Source0: http://cyberelk.net/tim/data/system-config-printer/1.1/system-config-printer-%{version}.tar.bz2
Source1: http://cyberelk.net/tim/data/pycups/pycups-%{pycups_version}.tar.bz2
Source2: http://cyberelk.net/tim/data/pysmbc/pysmbc-%{pysmbc_version}.tar.bz2
Patch1: system-config-printer-a05bd9c.patch
BuildRequires: cups-devel >= 1.2
BuildRequires: python-devel >= 2.4
@ -76,6 +77,7 @@ printers.
%prep
%setup -q -a 1 -a 2
%patch1 -p1 -b .a05bd9c
%build
%configure --with-udev-rules
@ -183,6 +185,9 @@ rm -rf %buildroot
exit 0
%changelog
* Thu Jul 23 2009 Tim Waugh <twaugh@redhat.com> 1.1.10-2
- Applied some udev-configure-printer fixes from upstrema.
* Wed Jul 22 2009 Tim Waugh <twaugh@redhat.com> 1.1.10-1
- 1.1.10:
- New udev rules for adding/enabling/disabling USB printers