if (attr)
{
- if (strncasecmp(attr, "Hewlett-Packard ", 16) == 0)
+ /*
+ * Use description...
+ */
+
+ if (!strncasecmp(attr, "Hewlett-Packard hp ", 19))
+ {
+ /*
+ * Check for a common HP bug...
+ */
+
+ strlcpy(make_model, "HP ", mmsize);
+ strlcpy(make_model + 3, attr + 19, mmsize - 3);
+ }
+ else if (!strncasecmp(attr, "Hewlett-Packard ", 16))
{
strlcpy(make_model, "HP ", mmsize);
strlcpy(make_model + 3, attr + 16, mmsize - 3);
{
strlcpy(make_model, attr, mmsize);
}
-
- if ((delim = strchr(make_model, ';')) != NULL)
- *delim = '\0';
}
else if (mfg && mdl)
{
* Build a make-model string from the manufacturer and model attributes...
*/
- strlcpy(make_model, mfg, mmsize);
+ if (!strncasecmp(mfg, "Hewlett-Packard", 15))
+ strlcpy(make_model, "HP", mmsize);
+ else
+ strlcpy(make_model, mfg, mmsize);
if ((delim = strchr(make_model, ';')) != NULL)
*delim = '\0';
- strlcat(make_model, " ", mmsize);
- strlcat(make_model, mdl, mmsize);
+ if (!strncasecmp(make_model, mdl, strlen(make_model)))
+ {
+ /*
+ * Just copy model string, since it has the manufacturer...
+ */
- if ((delim = strchr(make_model, ';')) != NULL)
- *delim = '\0';
+ strlcpy(make_model, mdl, mmsize);
+ }
+ else
+ {
+ /*
+ * Concatenate the make and model...
+ */
+
+ strlcat(make_model, " ", mmsize);
+ strlcat(make_model, mdl, mmsize);
+ }
}
else
{
strlcpy(make_model, "Unknown", mmsize);
}
+ if ((delim = strchr(make_model, ';')) != NULL)
+ *delim = '\0';
+
/*
* Look for the serial number field...
*/
else if ((attr = strstr(device_id, ";SN:")) != NULL)
attr += 4;
- if (mfg)
- {
- /*
- * Make sure manufacturer is truncated at delimiter...
- */
-
- if ((delim = strchr(mfg, ';')) != NULL)
- *delim = '\0';
- }
-
- if (mdl)
- {
- /*
- * Make sure model is truncated at delimiter...
- */
-
- if ((delim = strchr(mdl, ';')) != NULL)
- *delim = '\0';
- }
-
if (attr)
{
strlcpy(serial_number, attr, sizeof(serial_number));
*options_ptr++ = *ptr;
else if (*ptr == ' ')
*options_ptr++ = '_';
-
+
+ /*
+ * Then add the make and model in the printer info, so
+ * that MacOS clients see something reasonable...
+ */
+
+ strlcpy(options_ptr, "&PRINTER_LOCATION=&PRINTER_INFO=",
+ sizeof(options) - (options_ptr - options));
+ options_ptr += strlen(options_ptr);
+
+ form_encode(options_ptr, device_make_and_model,
+ sizeof(options) - (options_ptr - options));
+ options_ptr += strlen(options_ptr);
+
/*
* Then copy the device URI...
*/
- strlcpy(options_ptr, "&PRINTER_LOCATION=&PRINTER_INFO=&DEVICE_URI=",
+ strlcpy(options_ptr, "&DEVICE_URI=",
sizeof(options) - (options_ptr - options));
options_ptr += strlen(options_ptr);
include ../Makedefs
-CUPSDOBJS = auth.o banners.o cert.o classes.o client.o conf.o devices.o \
+CUPSDOBJS = auth.o banners.o cert.o classes.o client.o conf.o \
dirsvc.o main.o ipp.o listen.o job.o log.o network.o \
policy.o ppds.o printers.o process.o quotas.o server.o \
statbuf.o subscriptions.o
MIMEOBJS = filter.o mime.o type.o
-OBJS = $(CUPSDOBJS) $(MIMEOBJS) cups-lpd.o cups-polld.o testmime.o \
+OBJS = $(CUPSDOBJS) $(MIMEOBJS) \
+ cups-deviced.o util.o \
+ cups-lpd.o \
+ cups-polld.o \
+ testmime.o \
testspeed.o
-TARGETS = cupsd cups-lpd cups-polld libmime.a testmime testspeed
+TARGETS = cupsd cups-deviced cups-lpd cups-polld libmime.a \
+ testmime testspeed
+
#
# Make everything...
$(INSTALL_DIR) $(SBINDIR)
$(INSTALL_BIN) cupsd $(SBINDIR)
$(INSTALL_DIR) $(SERVERBIN)/daemon
+ $(INSTALL_BIN) cups-deviced $(SERVERBIN)/daemon
$(INSTALL_BIN) cups-lpd $(SERVERBIN)/daemon
$(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
$(INSTALL_DIR) -m 711 -o $(CUPS_USER) -g $(CUPS_GROUP) $(SERVERROOT)/certs
$(LIBPAPER) $(LIBMALLOC)
+#
+# Make the device daemon, "cups-deviced".
+#
+
+cups-deviced: cups-deviced.o util.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cups-deviced cups-deviced.o util.o $(LIBS)
+
+
#
# Make the line printer daemon, "cups-lpd".
#
* 'SendCommand()' - Send output from a command via HTTP.
*/
-int
-SendCommand(client_t *con,
- char *command,
- char *options)
+int /* O - 1 on success, 0 on failure */
+SendCommand(client_t *con, /* I - Client connection */
+ char *command, /* I - Command to run */
+ char *options) /* I - Command-line options */
{
- int fd;
+ int fd; /* Standard input file descriptor */
if (con->filename)
char content_length[1024], /* CONTENT_LENGTH environment variable */
content_type[1024], /* CONTENT_TYPE environment variable */
cups_datadir[1024], /* CUPS_DATADIR environment variable */
+ cups_serverbin[1024], /* CUPS_SERVERBIN environment variable */
cups_serverroot[1024], /* CUPS_SERVERROOT environment variable */
cups_statedir[1024], /* CUPS_STATEDIR environment variable */
http_cookie[1024], /* HTTP_COOKIE environment variable */
snprintf(remote_user, sizeof(remote_user), "REMOTE_USER=%s", con->username);
snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
+ snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s", ServerBin);
snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s", ServerRoot);
snprintf(cups_statedir, sizeof(cups_statedir), "CUPS_STATEDIR=%s", StateDir);
envp[envc ++] = TZ;
envp[envc ++] = tmpdir;
envp[envc ++] = cups_datadir;
+ envp[envc ++] = cups_serverbin;
envp[envc ++] = cups_serverroot;
envp[envc ++] = cups_statedir;
DefaultPrinter = NULL;
- if (Devices)
- {
- ippDelete(Devices);
- Devices = NULL;
- }
-
if (PPDs)
{
ippDelete(PPDs);
* Load devices and PPDs...
*/
- snprintf(temp, sizeof(temp), "%s/backend", ServerBin);
- LoadDevices(temp);
-
snprintf(temp, sizeof(temp), "%s/model", DataDir);
LoadPPDs(temp);
--- /dev/null
+/*
+ * "$Id$"
+ *
+ * Device scanning mini-daemon for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "util.h"
+
+
+/*
+ * Device information structure...
+ */
+
+typedef struct
+{
+ char device_class[128], /* Device class */
+ device_make_and_model[128], /* Make and model, if known */
+ device_info[128], /* Device info/description */
+ device_uri[1024]; /* Device URI */
+} dev_info_t;
+
+
+/*
+ * Local globals...
+ */
+
+static int alarm_tripped; /* Non-zero if alarm was tripped */
+static int num_devs, /* Number of devices */
+ alloc_devs; /* Number of allocated entries */
+static dev_info_t *devs; /* Device info */
+
+
+/*
+ * Local functions...
+ */
+
+static dev_info_t *add_dev(const char *device_class,
+ const char *device_make_and_model,
+ const char *device_info,
+ const char *device_uri);
+static int compare_devs(const dev_info_t *p0,
+ const dev_info_t *p1);
+static void sigalrm_handler(int sig);
+
+
+/*
+ * 'main()' - Scan for devices and return an IPP response.
+ *
+ * Usage:
+ *
+ * cups-deviced request_id limit
+ */
+
+int /* O - Exit code */
+main(int argc, /* I - Number of command-line args */
+ char *argv[]) /* I - Command-line arguments */
+{
+ const char *server_bin; /* CUPS_SERVERBIN environment variable */
+ char backends[1024]; /* Location of backends */
+ int count; /* Number of devices from backend */
+ int compat; /* Compatibility device? */
+ FILE *fp; /* Pipe to device backend */
+ DIR *dir; /* Directory pointer */
+ DIRENT *dent; /* Directory entry */
+ char filename[1024], /* Name of backend */
+ line[2048], /* Line from backend */
+ dclass[64], /* Device class */
+ uri[1024], /* Device URI */
+ info[128], /* Device info */
+ make_model[256]; /* Make and model */
+ dev_info_t *dev; /* Current device */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Check the command-line...
+ */
+
+ if (argc != 3)
+ {
+ fputs("Usage: cups-deviced request_id limit\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Try opening the backend directory...
+ */
+
+ if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL)
+ server_bin = CUPS_SERVERBIN;
+
+ snprintf(backends, sizeof(backends), "%s/backend", server_bin);
+
+ if ((dir = opendir(backends)) == NULL)
+ {
+ fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory \"%s\": %s",
+ backends, strerror(errno));
+ return (1);
+ }
+
+ /*
+ * Setup the devices array...
+ */
+
+ alloc_devs = 0;
+ num_devs = 0;
+ devs = (dev_info_t *)0;
+
+ /*
+ * Loop through all of the device backends...
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ /*
+ * Skip "." and ".."...
+ */
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ /*
+ * Run the backend with no arguments and collect the output...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", backends, dent->d_name);
+ if ((fp = popen(filename, "r")) != NULL)
+ {
+ /*
+ * Set an alarm for the first read from the backend; this avoids
+ * problems when a backend is hung getting device information.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGALRM, sigalrm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGALRM);
+ action.sa_handler = sigalrm_handler;
+ sigaction(SIGALRM, &action, NULL);
+#else
+ signal(SIGALRM, sigalrm_handler);
+#endif /* HAVE_SIGSET */
+
+ alarm_tripped = 0;
+ count = 0;
+ compat = !strcmp(dent->d_name, "smb");
+
+ alarm(30);
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Reset the alarm clock...
+ */
+
+ alarm(30);
+
+ /*
+ * Each line is of the form:
+ *
+ * class URI "make model" "name"
+ */
+
+ if (!strncasecmp(line, "Usage", 5))
+ compat = 1;
+ else if (sscanf(line, "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]",
+ dclass, uri, make_model, info) != 4)
+ {
+ /*
+ * Bad format; strip trailing newline and write an error message.
+ */
+
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
+ dent->d_name, line);
+ compat = 1;
+ break;
+ }
+ else
+ {
+ /*
+ * Add the device to the array of available devices...
+ */
+
+ dev = add_dev(dclass, make_model, info, uri);
+ if (!dev)
+ {
+ closedir(dir);
+ return (1);
+ }
+
+ fprintf(stderr, "DEBUG: [cups-deviced] Added device \"%s\"...\n", uri);
+ count ++;
+ }
+ }
+
+ /*
+ * Turn the alarm clock off and close the pipe to the command...
+ */
+
+ alarm(0);
+
+ if (alarm_tripped)
+ fprintf(stderr, "WARNING: [cups-deviced] Backend \"%s\" did not respond within 30 seconds!\n",
+ dent->d_name);
+
+ pclose(fp);
+
+ /*
+ * Hack for backends that don't support the CUPS 1.1 calling convention:
+ * add a network device with the method == backend name.
+ */
+
+ if (count == 0 && compat)
+ {
+ snprintf(line, sizeof(line), "Unknown Network Device (%s)",
+ dent->d_name);
+
+ dev = add_dev("network", line, "Unknown", dent->d_name);
+ if (!dev)
+ {
+ closedir(dir);
+ return (1);
+ }
+
+ fprintf(stderr, "DEBUG: [cups-deviced] Compatibility device \"%s\"...\n",
+ dent->d_name);
+ }
+ }
+ else
+ fprintf(stderr, "WARNING: [cups-deviced] Unable to execute \"%s\" backend: %s\n",
+ dent->d_name, strerror(errno));
+ }
+
+ closedir(dir);
+
+ /*
+ * Sort the available devices...
+ */
+
+ if (num_devs > 1)
+ qsort(devs, num_devs, sizeof(dev_info_t),
+ (int (*)(const void *, const void *))compare_devs);
+
+ /*
+ * Output the list of devices...
+ */
+
+ puts("Content-Type: application/ipp\n");
+
+ cupsdSendIPPHeader(IPP_OK, atoi(argv[1]));
+ cupsdSendIPPGroup(IPP_TAG_OPERATION);
+ cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+ cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
+
+ if ((count = atoi(argv[2])) <= 0)
+ count = num_devs;
+
+ if (count > num_devs)
+ count = num_devs;
+
+ for (dev = devs; count > 0; count --, dev ++)
+ {
+ /*
+ * Add strings to attributes...
+ */
+
+ cupsdSendIPPGroup(IPP_TAG_PRINTER);
+ cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class", dev->device_class);
+ cupsdSendIPPString(IPP_TAG_TEXT, "device-info", dev->device_info);
+ cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model",
+ dev->device_make_and_model);
+ cupsdSendIPPString(IPP_TAG_URI, "device-uri", dev->device_uri);
+ }
+
+ cupsdSendIPPTrailer();
+
+ /*
+ * Free the devices array and return...
+ */
+
+ if (alloc_devs)
+ free(devs);
+
+ return (0);
+}
+
+
+/*
+ * 'add_dev()' - Add a new device to the list.
+ */
+
+static dev_info_t * /* O - New device or NULL on error */
+add_dev(
+ const char *device_class, /* I - Device class */
+ const char *device_make_and_model, /* I - Device make and model */
+ const char *device_info, /* I - Device information */
+ const char *device_uri) /* I - Device URI */
+{
+ dev_info_t *dev; /* New device */
+
+
+ if (num_devs >= alloc_devs)
+ {
+ /*
+ * Allocate (more) memory for the devices...
+ */
+
+ if (alloc_devs == 0)
+ dev = malloc(sizeof(dev_info_t) * 16);
+ else
+ dev = realloc(devs, sizeof(dev_info_t) * (alloc_devs + 16));
+
+ if (dev == NULL)
+ {
+ fprintf(stderr, "ERROR: [cups-deviced] Ran out of memory for %d devices!\n",
+ alloc_devs + 16);
+ return (NULL);
+ }
+
+ devs = dev;
+ alloc_devs += 16;
+ }
+
+ /*
+ * Add a new device at the end of the array...
+ */
+
+ dev = devs + num_devs;
+ num_devs ++;
+
+ memset(dev, 0, sizeof(dev_info_t));
+
+ /*
+ * Copy the strings and return...
+ */
+
+ strlcpy(dev->device_class, device_class, sizeof(dev->device_class));
+ strlcpy(dev->device_make_and_model, device_make_and_model,
+ sizeof(dev->device_make_and_model));
+ strlcpy(dev->device_info, device_info, sizeof(dev->device_info));
+ strlcpy(dev->device_uri, device_uri, sizeof(dev->device_uri));
+
+ return (dev);
+}
+
+
+/*
+ * 'compare_devs()' - Compare device names for sorting.
+ */
+
+static int /* O - Result of comparison */
+compare_devs(const dev_info_t *d0, /* I - First device */
+ const dev_info_t *d1) /* I - Second device */
+{
+ int diff; /* Difference between strings */
+
+
+ /*
+ * Sort devices by device-info, device-class, and device-uri...
+ */
+
+ if ((diff = cupsdCompareNames(d0->device_info, d1->device_info)) != 0)
+ return (diff);
+ else if ((diff = strcasecmp(d0->device_class, d1->device_class)) != 0)
+ return (diff);
+ else
+ return (strcasecmp(d0->device_uri, d1->device_uri));
+}
+
+
+/*
+ * 'sigalrm_handler()' - Handle alarm signals for backends that get hung
+ * trying to list the available devices...
+ */
+
+static void
+sigalrm_handler(int sig) /* I - Signal number */
+{
+ (void)sig; /* remove compiler warnings... */
+
+ alarm_tripped = 1;
+}
+
+
+/*
+ * End of "$Id$".
+ */
VAR char *TZ VALUE(NULL);
/* Timezone configuration */
-VAR ipp_t *Devices VALUE(NULL),
- /* Available devices */
- *PPDs VALUE(NULL);
+VAR ipp_t *PPDs VALUE(NULL);
/* Available PPDs */
extern void ClearString(char **s);
extern void HoldSignals(void);
extern void IgnoreChildSignals(void);
-extern void LoadDevices(const char *d);
extern void LoadPPDs(const char *d);
extern void ReleaseSignals(void);
extern void SetString(char **s, const char *v);
+++ /dev/null
-/*
- * "$Id$"
- *
- * Device scanning routines for the Common UNIX Printing System (CUPS).
- *
- * Copyright 1997-2005 by Easy Software Products.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
- *
- * Contents:
- *
- * LoadDevices() - Load all available devices.
- * compare_devs() - Compare PPD file make and model names for sorting.
- * sigalrm_handler() - Handle alarm signals for backends that get hung
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "cupsd.h"
-
-
-/*
- * Device information structure...
- */
-
-typedef struct
-{
- char device_class[128], /* Device class */
- device_make_and_model[128], /* Make and model, if known */
- device_info[128], /* Device info/description */
- device_uri[1024]; /* Device URI */
-} dev_info_t;
-
-
-/*
- * Local globals...
- */
-
-static int num_devs, /* Number of devices */
- alloc_devs; /* Number of allocated entries */
-static dev_info_t *devs; /* Device info */
-
-
-/*
- * Local functions...
- */
-
-static int compare_devs(const dev_info_t *p0, const dev_info_t *p1);
-static void sigalrm_handler(int sig);
-
-
-/*
- * 'LoadDevices()' - Load all available devices.
- */
-
-void
-LoadDevices(const char *d) /* I - Directory to scan */
-{
- int i; /* Looping var */
- int count; /* Number of devices from backend */
- int compat; /* Compatibility device? */
- FILE *fp; /* Pipe to device backend */
- DIR *dir; /* Directory pointer */
- DIRENT *dent; /* Directory entry */
- char filename[1024], /* Name of backend */
- line[2048], /* Line from backend */
- dclass[64], /* Device class */
- uri[1024], /* Device URI */
- info[128], /* Device info */
- make_model[256];/* Make and model */
- dev_info_t *dev; /* Current device */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- struct sigaction action; /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
- * Initialize the device list.
- */
-
- Devices = ippNew();
-
- /*
- * Try opening the backend directory...
- */
-
- if ((dir = opendir(d)) == NULL)
- {
- LogMessage(L_ERROR, "LoadDevices: Unable to open backend directory \"%s\": %s",
- d, strerror(errno));
- return;
- }
-
- /*
- * Setup the devices array...
- */
-
- alloc_devs = 0;
- num_devs = 0;
- devs = (dev_info_t *)0;
-
- /*
- * Ignore child signals...
- */
-
- IgnoreChildSignals();
-
- /*
- * Loop through all of the device backends...
- */
-
- while ((dent = readdir(dir)) != NULL)
- {
- /*
- * Skip "." and ".."...
- */
-
- if (dent->d_name[0] == '.')
- continue;
-
- /*
- * Run the backend with no arguments and collect the output...
- */
-
- snprintf(filename, sizeof(filename), "%s/%s", d, dent->d_name);
- if ((fp = popen(filename, "r")) != NULL)
- {
- /*
- * Set an alarm for the first read from the backend; this avoids
- * problems when a backend is hung getting device information.
- */
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
- sigset(SIGALRM, sigalrm_handler);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
-
- sigemptyset(&action.sa_mask);
- sigaddset(&action.sa_mask, SIGALRM);
- action.sa_handler = sigalrm_handler;
- sigaction(SIGALRM, &action, NULL);
-#else
- signal(SIGALRM, sigalrm_handler);
-#endif /* HAVE_SIGSET */
-
- alarm(30);
- count = 0;
- compat = strcmp(dent->d_name, "smb") == 0;
-
- while (fgets(line, sizeof(line), fp) != NULL)
- {
- /*
- * Reset the alarm clock...
- */
-
- alarm(30);
-
- /*
- * Each line is of the form:
- *
- * class URI "make model" "name"
- */
-
- if (strncasecmp(line, "Usage", 5) == 0)
- compat = 1;
- else if (sscanf(line, "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]",
- dclass, uri, make_model, info) != 4)
- {
- /*
- * Bad format; strip trailing newline and write an error message.
- */
-
- if (line[strlen(line) - 1] == '\n')
- line[strlen(line) - 1] = '\0';
-
- LogMessage(L_ERROR, "LoadDevices: Bad line from \"%s\": %s",
- dent->d_name, line);
- compat = 1;
- break;
- }
- else
- {
- /*
- * Add the device to the array of available devices...
- */
-
- if (num_devs >= alloc_devs)
- {
- /*
- * Allocate (more) memory for the devices...
- */
-
- if (alloc_devs == 0)
- dev = malloc(sizeof(dev_info_t) * 16);
- else
- dev = realloc(devs, sizeof(dev_info_t) * (alloc_devs + 16));
-
- if (dev == NULL)
- {
- LogMessage(L_ERROR, "LoadDevices: Ran out of memory for %d devices!",
- alloc_devs + 16);
- closedir(dir);
- return;
- }
-
- devs = dev;
- alloc_devs += 16;
- }
-
- dev = devs + num_devs;
- num_devs ++;
-
- memset(dev, 0, sizeof(dev_info_t));
- strlcpy(dev->device_class, dclass, sizeof(dev->device_class));
- strlcpy(dev->device_info, info, sizeof(dev->device_info));
- strlcpy(dev->device_make_and_model, make_model,
- sizeof(dev->device_make_and_model));
- strlcpy(dev->device_uri, uri, sizeof(dev->device_uri));
-
- LogMessage(L_DEBUG, "LoadDevices: Added device \"%s\"...", uri);
- count ++;
- }
- }
-
- /*
- * Turn the alarm clock off and close the pipe to the command...
- */
-
- alarm(0);
-
- pclose(fp);
-
- /*
- * Hack for backends that don't support the CUPS 1.1 calling convention:
- * add a network device with the method == backend name.
- */
-
- if (count == 0 && compat)
- {
- if (num_devs >= alloc_devs)
- {
- /*
- * Allocate (more) memory for the devices...
- */
-
- if (alloc_devs == 0)
- dev = malloc(sizeof(dev_info_t) * 16);
- else
- dev = realloc(devs, sizeof(dev_info_t) * (alloc_devs + 16));
-
- if (dev == NULL)
- {
- LogMessage(L_ERROR, "LoadDevices: Ran out of memory for %d devices!",
- alloc_devs + 16);
- closedir(dir);
- return;
- }
-
- devs = dev;
- alloc_devs += 16;
- }
-
- dev = devs + num_devs;
- num_devs ++;
-
- memset(dev, 0, sizeof(dev_info_t));
- strcpy(dev->device_class, "network");
- snprintf(dev->device_info, sizeof(dev->device_info),
- "Unknown Network Device (%s)", dent->d_name);
- strcpy(dev->device_make_and_model, "Unknown");
- strlcpy(dev->device_uri, dent->d_name, sizeof(dev->device_uri));
-
- LogMessage(L_DEBUG, "LoadDevices: Compatibility device \"%s\"...",
- dent->d_name);
- }
- }
- else
- LogMessage(L_WARN, "LoadDevices: Unable to execute \"%s\" backend: %s",
- dent->d_name, strerror(errno));
- }
-
- closedir(dir);
-
- /*
- * Catch child signals...
- */
-
- CatchChildSignals();
-
- /*
- * Sort the available devices...
- */
-
- if (num_devs > 1)
- qsort(devs, num_devs, sizeof(dev_info_t),
- (int (*)(const void *, const void *))compare_devs);
-
- /*
- * Create the list of devices...
- */
-
- for (i = num_devs, dev = devs; i > 0; i --, dev ++)
- {
- /*
- * Add strings to attributes...
- */
-
- if (i < num_devs)
- ippAddSeparator(Devices);
-
- ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
- "device-class", NULL, dev->device_class);
- ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "device-info", NULL, dev->device_info);
- ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_TEXT,
- "device-make-and-model", NULL, dev->device_make_and_model);
- ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_URI,
- "device-uri", NULL, dev->device_uri);
- }
-
- /*
- * Free the devices array...
- */
-
- if (alloc_devs)
- free(devs);
-}
-
-
-/*
- * 'compare_devs()' - Compare device names for sorting.
- */
-
-static int /* O - Result of comparison */
-compare_devs(const dev_info_t *d0, /* I - First device */
- const dev_info_t *d1) /* I - Second device */
-{
- const char *s, /* First name */
- *t; /* Second name */
- int diff, /* Difference between digits */
- digits; /* Number of digits */
-
-
- /*
- * First compare names...
- */
-
- s = d0->device_info;
- t = d1->device_info;
-
- /*
- * Loop through both nicknames, returning only when a difference is
- * seen. Also, compare whole numbers rather than just characters, too!
- */
-
- while (*s && *t)
- {
- if (isdigit(*s & 255) && isdigit(*t & 255))
- {
- /*
- * Got a number; start by skipping leading 0's...
- */
-
- while (*s == '0')
- s ++;
- while (*t == '0')
- t ++;
-
- /*
- * Skip equal digits...
- */
-
- while (isdigit(*s & 255) && *s == *t)
- {
- s ++;
- t ++;
- }
-
- /*
- * Bounce out if *s and *t aren't both digits...
- */
-
- if (isdigit(*s & 255) && !isdigit(*t & 255))
- return (1);
- else if (!isdigit(*s & 255) && isdigit(*t & 255))
- return (-1);
- else if (!isdigit(*s & 255) || !isdigit(*t & 255))
- continue;
-
- if (*s < *t)
- diff = -1;
- else
- diff = 1;
-
- /*
- * Figure out how many more digits there are...
- */
-
- digits = 0;
- s ++;
- t ++;
-
- while (isdigit(*s & 255))
- {
- digits ++;
- s ++;
- }
-
- while (isdigit(*t & 255))
- {
- digits --;
- t ++;
- }
-
- /*
- * Return if the number or value of the digits is different...
- */
-
- if (digits < 0)
- return (-1);
- else if (digits > 0)
- return (1);
- else if (diff)
- return (diff);
- }
- else if (tolower(*s) < tolower(*t))
- return (-1);
- else if (tolower(*s) > tolower(*t))
- return (1);
- else
- {
- s ++;
- t ++;
- }
- }
-
- /*
- * Return the results of the final comparison...
- */
-
- if (*s)
- return (1);
- else if (*t)
- return (-1);
- else if ((diff = strcasecmp(d0->device_class, d1->device_class)) != 0)
- return (diff);
- else
- return (strcasecmp(d0->device_uri, d1->device_uri));
-}
-
-
-/*
- * 'sigalrm_handler()' - Handle alarm signals for backends that get hung
- * trying to list the available devices...
- */
-
-static void
-sigalrm_handler(int sig) /* I - Signal number */
-{
- (void)sig; /* remove compiler warnings... */
-
- LogMessage(L_WARN, "LoadDevices: Backend did not respond within 30 seconds!");
-}
-
-
-/*
- * End of "$Id$".
- */
}
}
- LogMessage(L_DEBUG, "ProcessIPPRequest: %d status_code=%x (%s)",
- con->http.fd, con->response->request.status.status_code,
- ippErrorString(con->response->request.status.status_code));
-
- if (SendHeader(con, HTTP_OK, "application/ipp"))
+ if (con->response)
{
- if (con->http.version == HTTP_1_1)
- {
- con->http.data_encoding = HTTP_ENCODE_CHUNKED;
+ /*
+ * Sending data from the scheduler...
+ */
- httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n");
- }
- else
+ LogMessage(L_DEBUG, "ProcessIPPRequest: %d status_code=%x (%s)",
+ con->http.fd, con->response->request.status.status_code,
+ ippErrorString(con->response->request.status.status_code));
+
+ if (SendHeader(con, HTTP_OK, "application/ipp"))
{
- con->http.data_encoding = HTTP_ENCODE_LENGTH;
- con->http.data_remaining = ippLength(con->response);
+ if (con->http.version == HTTP_1_1)
+ {
+ con->http.data_encoding = HTTP_ENCODE_CHUNKED;
- httpPrintf(HTTP(con), "Content-Length: %d\r\n\r\n",
- con->http.data_remaining);
- }
+ httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n");
+ }
+ else
+ {
+ con->http.data_encoding = HTTP_ENCODE_LENGTH;
+ con->http.data_remaining = ippLength(con->response);
- LogMessage(L_DEBUG2, "ProcessIPPRequest: Adding fd %d to OutputSet...",
- con->http.fd);
+ httpPrintf(HTTP(con), "Content-Length: %d\r\n\r\n",
+ con->http.data_remaining);
+ }
- FD_SET(con->http.fd, OutputSet);
+ LogMessage(L_DEBUG2, "ProcessIPPRequest: Adding fd %d to OutputSet...",
+ con->http.fd);
- /*
- * Tell the caller the response header was sent successfully...
- */
+ FD_SET(con->http.fd, OutputSet);
- return (1);
+ /*
+ * Tell the caller the response header was sent successfully...
+ */
+
+ return (1);
+ }
+ else
+ {
+ /*
+ * Tell the caller the response header could not be sent...
+ */
+
+ return (0);
+ }
}
else
{
/*
- * Tell the caller the response header could not be sent...
+ * Sending data from a subprocess like cups-deviced; tell the caller
+ * everything is A-OK so far...
*/
- return (0);
+ return (1);
}
}
* See if the backend is listed as a device...
*/
+#if 0 /* ADD THIS BACK IN SOMEHOW */
for (device = ippFindAttribute(Devices, "device-uri", IPP_TAG_URI);
device != NULL;
device = ippFindNextAttribute(Devices, "device-uri", IPP_TAG_URI))
send_ipp_error(con, IPP_NOT_POSSIBLE);
return;
}
+#endif /* 0 */
}
LogMessage(L_INFO, "Setting %s device-uri to \"%s\" (was \"%s\".)",
* Also, we can only have 1 value and it must be a name value.
*/
- int i; /* Looping var */
-
switch (attr->value_tag)
{
case IPP_TAG_STRING :
static void
get_devices(client_t *con) /* I - Client connection */
{
+ ipp_attribute_t *limit; /* Limit attribute */
+ char command[1024], /* cups-deviced command */
+ options[1024]; /* Options to pass to command */
+
+
LogMessage(L_DEBUG2, "get_devices(%p[%d])\n", con, con->http.fd);
/*
}
/*
- * Copy the device attributes to the response using the requested-attributes
- * attribute that may be provided by the client.
+ * Run cups-deviced command with the given options...
*/
- copy_attrs(con->response, Devices,
- ippFindAttribute(con->request, "requested-attributes",
- IPP_TAG_KEYWORD), IPP_TAG_ZERO, IPP_TAG_COPY);
+ limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
- con->response->request.status.status_code = IPP_OK;
+ snprintf(command, sizeof(command), "%s/daemon/cups-deviced", ServerBin);
+ snprintf(options, sizeof(options), "cups-deviced %d+%d",
+ con->request->request.op.request_id,
+ limit ? limit->values[0].integer : 0);
+
+ if (SendCommand(con, command, options))
+ {
+ /*
+ * Command started successfully, don't send an IPP response here...
+ */
+
+ ippDelete(con->response);
+ con->response = NULL;
+ }
+ else
+ {
+ /*
+ * Command failed, return "internal error" so the user knows something
+ * went wrong...
+ */
+
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ }
}
* Also, we can only have 1 value and it must be a name value.
*/
- int i; /* Looping var */
-
switch (attr->value_tag)
{
case IPP_TAG_STRING :
class_name[255], /* CLASS environment variable */
printer_name[255], /* PRINTER environment variable */
root[1024], /* CUPS_SERVERROOT environment variable */
+ cups_serverbin[1024], /* CUPS_SERVERBIN environment variable */
cups_statedir[1024], /* CUPS_STATEDIR environment variable */
cache[255], /* RIP_MAX_CACHE environment variable */
tmpdir[1024], /* TMPDIR environment variable */
snprintf(printer_name, sizeof(printer_name), "PRINTER=%s", printer->name);
snprintf(cache, sizeof(cache), "RIP_MAX_CACHE=%s", RIPCache);
snprintf(root, sizeof(root), "CUPS_SERVERROOT=%s", ServerRoot);
+ snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s", ServerBin);
snprintf(cups_statedir, sizeof(cups_statedir), "CUPS_STATEDIR=%s", StateDir);
snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
if (TZ && TZ[0])
envp[envc ++] = TZ;
envp[envc ++] = ppd;
+ envp[envc ++] = cups_serverbin;
envp[envc ++] = root;
envp[envc ++] = cups_statedir;
envp[envc ++] = cache;
--- /dev/null
+/*
+ * "$Id$"
+ *
+ * Mini-daemon utility functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * cupsdSendIPPGroup() - Send a group tag.
+ * cupsdSendIPPHeader() - Send the IPP response header.
+ * cupsdSendIPPInteger() - Send an integer attribute.
+ * cupsdSendIPPString() - Send a string attribute.
+ * cupsdSendIPPTrailer() - Send the end-of-message tag.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "util.h"
+
+
+/*
+ * 'cupsdCompareNames()' - Compare two names.
+ *
+ * This function basically does a strcasecmp() of the two strings,
+ * but is also aware of numbers so that "a2" < "a100".
+ */
+
+int /* O - Result of comparison */
+cupsdCompareNames(const char *s, /* I - First string */
+ const char *t) /* I - Second string */
+{
+ int diff, /* Difference between digits */
+ digits; /* Number of digits */
+
+
+ /*
+ * Loop through both names, returning only when a difference is
+ * seen. Also, compare whole numbers rather than just characters, too!
+ */
+
+ while (*s && *t)
+ {
+ if (isdigit(*s & 255) && isdigit(*t & 255))
+ {
+ /*
+ * Got a number; start by skipping leading 0's...
+ */
+
+ while (*s == '0')
+ s ++;
+ while (*t == '0')
+ t ++;
+
+ /*
+ * Skip equal digits...
+ */
+
+ while (isdigit(*s & 255) && *s == *t)
+ {
+ s ++;
+ t ++;
+ }
+
+ /*
+ * Bounce out if *s and *t aren't both digits...
+ */
+
+ if (isdigit(*s & 255) && !isdigit(*t & 255))
+ return (1);
+ else if (!isdigit(*s & 255) && isdigit(*t & 255))
+ return (-1);
+ else if (!isdigit(*s & 255) || !isdigit(*t & 255))
+ continue;
+
+ if (*s < *t)
+ diff = -1;
+ else
+ diff = 1;
+
+ /*
+ * Figure out how many more digits there are...
+ */
+
+ digits = 0;
+ s ++;
+ t ++;
+
+ while (isdigit(*s & 255))
+ {
+ digits ++;
+ s ++;
+ }
+
+ while (isdigit(*t & 255))
+ {
+ digits --;
+ t ++;
+ }
+
+ /*
+ * Return if the number or value of the digits is different...
+ */
+
+ if (digits < 0)
+ return (-1);
+ else if (digits > 0)
+ return (1);
+ else if (diff)
+ return (diff);
+ }
+ else if (tolower(*s) < tolower(*t))
+ return (-1);
+ else if (tolower(*s) > tolower(*t))
+ return (1);
+ else
+ {
+ s ++;
+ t ++;
+ }
+ }
+
+ /*
+ * Return the results of the final comparison...
+ */
+
+ if (*s)
+ return (1);
+ else if (*t)
+ return (-1);
+ else
+ return (0);
+}
+
+
+/*
+ * 'cupsdSendIPPGroup()' - Send a group tag.
+ */
+
+void
+cupsdSendIPPGroup(ipp_tag_t group_tag) /* I - Group tag */
+{
+ /*
+ * Send IPP group tag (1 byte)...
+ */
+
+ putchar(group_tag);
+}
+
+
+/*
+ * 'cupsdSendIPPHeader()' - Send the IPP response header.
+ */
+
+void
+cupsdSendIPPHeader(
+ ipp_status_t status_code, /* I - Status code */
+ int request_id) /* I - Request ID */
+{
+ /*
+ * Send IPP/1.1 response header: version number (2 bytes), status code
+ * (4 bytes), and request ID (4 bytes)...
+ */
+
+ putchar(1);
+ putchar(1);
+
+ putchar(status_code >> 24);
+ putchar(status_code >> 16);
+ putchar(status_code >> 8);
+ putchar(status_code);
+
+ putchar(request_id >> 24);
+ putchar(request_id >> 16);
+ putchar(request_id >> 8);
+ putchar(request_id);
+}
+
+
+/*
+ * 'cupsdSendIPPInteger()' - Send an integer attribute.
+ */
+
+void
+cupsdSendIPPInteger(
+ ipp_tag_t value_tag, /* I - Value tag */
+ const char *name, /* I - Attribute name */
+ int value) /* I - Attribute value */
+{
+ size_t len; /* Length of attribute name */
+
+
+ /*
+ * Send IPP integer value: value tag (1 byte), name length (2 bytes),
+ * name string (without nul), and value (4 bytes)...
+ */
+
+ putchar(value_tag);
+
+ len = strlen(name);
+ putchar(len >> 8);
+ putchar(len);
+
+ fputs(name, stdout);
+
+ putchar(value >> 24);
+ putchar(value >> 16);
+ putchar(value >> 8);
+ putchar(value);
+}
+
+
+/*
+ * 'cupsdSendIPPString()' - Send a string attribute.
+ */
+
+void
+cupsdSendIPPString(
+ ipp_tag_t value_tag, /* I - Value tag */
+ const char *name, /* I - Attribute name */
+ const char *value) /* I - Attribute value */
+{
+ size_t len; /* Length of attribute name */
+
+
+ /*
+ * Send IPP string value: value tag (1 byte), name length (2 bytes),
+ * name string (without nul), value length (2 bytes), and value string
+ * (without nul)...
+ */
+
+ putchar(value_tag);
+
+ len = strlen(name);
+ putchar(len >> 8);
+ putchar(len);
+
+ fputs(name, stdout);
+
+ len = strlen(value);
+ putchar(len >> 8);
+ putchar(len);
+
+ fputs(value, stdout);
+}
+
+
+/*
+ * 'cupsdSendIPPTrailer()' - Send the end-of-message tag.
+ */
+
+void
+cupsdSendIPPTrailer(void)
+{
+ putchar(IPP_TAG_END);
+ fflush(stdout);
+}
+
+
+/*
+ * End of "$Id$".
+ */
--- /dev/null
+/*
+ * "$Id$"
+ *
+ * Mini-daemon utility definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2005 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifndef _CUPSD_UTIL_H_
+# define _CUPSD_UTIL_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <cups/cups.h>
+# include <cups/file.h>
+# include <cups/string.h>
+# include <stdlib.h>
+# include <errno.h>
+# include <signal.h>
+
+# if HAVE_DIRENT_H
+# include <dirent.h>
+typedef struct dirent DIRENT;
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+# else
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+typedef struct direct DIRENT;
+# define NAMLEN(dirent) (dirent)->d_namlen
+# endif /* HAVE_DIRENT_H */
+
+
+/*
+ * Prototypes...
+ */
+
+extern int cupsdCompareNames(const char *s, const char *t);
+extern void cupsdSendIPPGroup(ipp_tag_t group_tag);
+extern void cupsdSendIPPHeader(ipp_status_t status_code, int request_id);
+extern void cupsdSendIPPInteger(ipp_tag_t value_tag, const char *name,
+ int value);
+extern void cupsdSendIPPString(ipp_tag_t value_tag, const char *name,
+ const char *value);
+extern void cupsdSendIPPTrailer(void);
+
+
+#endif /* !_CUPSD_UTIL_H_ */
+
+/*
+ * End of "$Id$".
+ */
ln -s $root/backend/socket /tmp/$user/bin/backend
ln -s $root/backend/usb /tmp/$user/bin/backend
ln -s $root/cgi-bin /tmp/$user/bin
+ln -s $root/scheduler /tmp/$user/bin/daemon
ln -s $root/filter/hpgltops /tmp/$user/bin/filter
ln -s $root/filter/imagetops /tmp/$user/bin/filter
ln -s $root/filter/imagetoraster /tmp/$user/bin/filter