323 lines
10 KiB
Diff
323 lines
10 KiB
Diff
|
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)
|
||
|
{
|