]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
backend/usb-unix.c:
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Tue, 23 Aug 2005 19:30:08 +0000 (19:30 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Tue, 23 Aug 2005 19:30:08 +0000 (19:30 +0000)
- Add some more checking to ensure we don't get "HP hp
  designjet..." model strings, and remove some unused
  code.

cgi-bin/admin.c:
- Set PRINTER_INFO (printer-description) value to make
  and model so that MacOS X clients see a reasonable
  printer name.

doc/images/accept-jobs.gif:
doc/images/reject-jobs.gif:
- Change colors to green and red, respectively.

scheduler/client.c:
- Support IPP requests that use subprocesses (cups-deviced for now)

scheduler/conf.c:
scheduler/cupsd.h:
scheduler/devices.c:
- Remove static device initialization data.

scheduler/cups-deviced.c:
- Add new external (CGI-style) program to list devices
  dynamically.

scheduler/ipp.c:
- get_devices(): use new external cups-deviced command.
- Remove extra looping variables.
- ProcessIPPRequest(): add code to handle subprocess responses.

scheduler/job.c:
- Add CUPS_SERVERBIN environment variable.

scheduler/Makefile:
- Add cups-deviced targets, remove devices.o.

scheduler/util.c:
scheduler/util.h:
- Added new utility functions for cups-deviced and others.

test/run-stp-tests.sh:
- Add symlink for daemon directory (now required for testing)

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@4583 7a7537e8-13f0-0310-91df-b6672ffda945

15 files changed:
backend/usb-unix.c
cgi-bin/admin.c
doc/images/accept-jobs.gif
doc/images/reject-jobs.gif
scheduler/Makefile
scheduler/client.c
scheduler/conf.c
scheduler/cups-deviced.c [new file with mode: 0644]
scheduler/cupsd.h
scheduler/devices.c [deleted file]
scheduler/ipp.c
scheduler/job.c
scheduler/util.c [new file with mode: 0644]
scheduler/util.h [new file with mode: 0644]
test/run-stp-tests.sh

index d91610f623d18c417b9e335f983e225778a349d5..2eaa50603c0aefe683cec618ae45081514a48d50 100644 (file)
@@ -283,7 +283,20 @@ decode_device_id(int        port,          /* I - Port number */
 
   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);
@@ -292,9 +305,6 @@ decode_device_id(int        port,           /* I - Port number */
     {
       strlcpy(make_model, attr, mmsize);
     }
-
-    if ((delim = strchr(make_model, ';')) != NULL)
-      *delim = '\0';
   }
   else if (mfg && mdl)
   {
@@ -302,16 +312,31 @@ decode_device_id(int        port,         /* I - Port number */
     * 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
   {
@@ -322,6 +347,9 @@ decode_device_id(int        port,           /* I - Port number */
     strlcpy(make_model, "Unknown", mmsize);
   }
 
+  if ((delim = strchr(make_model, ';')) != NULL)
+    *delim = '\0';
+
  /*
   * Look for the serial number field...
   */
@@ -333,26 +361,6 @@ decode_device_id(int        port,          /* I - Port number */
   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));
index 0e483866ff1e455f3de85df795fe9ed070959003..8f6c338c9547125d64005416eadd2421b5368647 100644 (file)
@@ -2691,12 +2691,25 @@ do_menu(http_t      *http,              /* I - HTTP connection */
                *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);
 
index 9da7a0dce11b175dafc1f23c698367a584570a0a..e0f46d9214247e494941df7defaff2b2887794e9 100644 (file)
Binary files a/doc/images/accept-jobs.gif and b/doc/images/accept-jobs.gif differ
index 6d938e308475bdc9862421d2d21653ff105b4b3a..23dfa99c061285df99eee84f12b7f01bfab38ff5 100644 (file)
Binary files a/doc/images/reject-jobs.gif and b/doc/images/reject-jobs.gif differ
index d3f659f31c10c1c9e5f3c5a235112291ab5defa5..cd23dbd1edd4823b4ac5d2fbcf29b81465715da6 100644 (file)
 
 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...
@@ -65,6 +71,7 @@ install:      all
        $(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
@@ -86,6 +93,15 @@ cupsd:       $(CUPSDOBJS) libmime.a ../cups/$(LIBCUPS)
                $(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".
 #
index 4f913da1a952430062558d829af88f2ea1a33f17..7afd0d19cde6f742a69e41387f561e756a60d11c 100644 (file)
@@ -1967,12 +1967,12 @@ ReadClient(client_t *con)               /* I - Client to read from */
  * '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)
@@ -2940,6 +2940,7 @@ pipe_command(client_t *con,               /* I - Client connection */
   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 */
@@ -3141,6 +3142,7 @@ pipe_command(client_t *con,               /* I - Client connection */
   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);
 
@@ -3168,6 +3170,7 @@ pipe_command(client_t *con,               /* I - Client connection */
   envp[envc ++] = TZ;
   envp[envc ++] = tmpdir;
   envp[envc ++] = cups_datadir;
+  envp[envc ++] = cups_serverbin;
   envp[envc ++] = cups_serverroot;
   envp[envc ++] = cups_statedir;
 
index 325043accb66288c1d4d1574e77cf6a71bc504ee..b04f9072c4872fb64fdd4a9b9414be1236d378a5 100644 (file)
@@ -786,12 +786,6 @@ ReadConfiguration(void)
 
     DefaultPrinter = NULL;
 
-    if (Devices)
-    {
-      ippDelete(Devices);
-      Devices = NULL;
-    }
-
     if (PPDs)
     {
       ippDelete(PPDs);
@@ -862,9 +856,6 @@ ReadConfiguration(void)
     * Load devices and PPDs...
     */
 
-    snprintf(temp, sizeof(temp), "%s/backend", ServerBin);
-    LoadDevices(temp);
-
     snprintf(temp, sizeof(temp), "%s/model", DataDir);
     LoadPPDs(temp);
 
diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c
new file mode 100644 (file)
index 0000000..c5c6fee
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * "$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$".
+ */
index 5408a6634915163474c5b9500fb146b0df390a91..5be06f89bfa3c3ba6391a2a2bfe4958e06c1b2b8 100644 (file)
@@ -188,9 +188,7 @@ VAR int                     NeedReload      VALUE(RELOAD_ALL),
 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 */
 
 
@@ -202,7 +200,6 @@ extern void CatchChildSignals(void);
 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);
diff --git a/scheduler/devices.c b/scheduler/devices.c
deleted file mode 100644 (file)
index 93fb7d4..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * "$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$".
- */
index c7aae01a383983b4988345c69efc8bdb9d403510..d3f0e6a12cb86959af68e157f75b55235af017ea 100644 (file)
@@ -554,45 +554,61 @@ ProcessIPPRequest(client_t *con)  /* I - Client connection */
     }
   }
 
-  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);
   }
 }
 
@@ -1517,6 +1533,7 @@ add_printer(client_t        *con, /* I - Client connection */
       * 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))
@@ -1536,6 +1553,7 @@ add_printer(client_t        *con, /* I - Client connection */
        send_ipp_error(con, IPP_NOT_POSSIBLE);
        return;
       }
+#endif /* 0 */
     }
 
     LogMessage(L_INFO, "Setting %s device-uri to \"%s\" (was \"%s\".)",
@@ -3352,8 +3370,6 @@ create_job(client_t        *con,  /* I - Client connection */
       * 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 :
@@ -3841,6 +3857,11 @@ get_default(client_t *con)               /* I - Client connection */
 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);
 
  /*
@@ -3855,15 +3876,34 @@ get_devices(client_t *con)              /* I - Client connection */
   }
 
  /*
-  * 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);
+  }
 }
 
 
@@ -5369,8 +5409,6 @@ print_job(client_t        *con,           /* I - Client connection */
       * 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 :
index d905c0681ad8413d4d4f328936ad583470b41fbd..2887a63982b5e13a66d4c0c84bd0f1afff675e5d 100644 (file)
@@ -1363,6 +1363,7 @@ StartJob(int       id,                    /* I - Job ID */
                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 */
@@ -1879,6 +1880,7 @@ StartJob(int       id,                    /* I - Job ID */
   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);
@@ -1895,6 +1897,7 @@ StartJob(int       id,                    /* I - Job ID */
   if (TZ && TZ[0])
     envp[envc ++] = TZ;
   envp[envc ++] = ppd;
+  envp[envc ++] = cups_serverbin;
   envp[envc ++] = root;
   envp[envc ++] = cups_statedir;
   envp[envc ++] = cache;
diff --git a/scheduler/util.c b/scheduler/util.c
new file mode 100644 (file)
index 0000000..bdb16db
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * "$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$".
+ */
diff --git a/scheduler/util.h b/scheduler/util.h
new file mode 100644 (file)
index 0000000..f9d8cc8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * "$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$".
+ */
index d20d16bf41fa91fc245b8195ddd4ab8a438812ca..d83b165f5d23eb53d44672c8c84ab9785f119d25 100755 (executable)
@@ -200,6 +200,7 @@ ln -s $root/backend/serial /tmp/$user/bin/backend
 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