]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/dest.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / dest.c
index 0d8ffd95db5305ae631cdaa70c38d8185e2abd57..289456370b0c2587ce42a82d7106ddf2cdff2c21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: dest.c 5138 2006-02-21 10:49:06Z mike $"
+ * "$Id: dest.c 6044 2006-10-17 20:32:59Z mike $"
  *
  *   User-defined destination (and option) support for the Common UNIX
  *   Printing System (CUPS).
@@ -44,6 +44,7 @@
 #include "globals.h"
 #include <stdlib.h>
 #include <ctype.h>
+#include <sys/stat.h>
 
 #ifdef HAVE_NOTIFY_H
 #  include <notify.h>
@@ -63,21 +64,31 @@ static int  cups_get_sdests(http_t *http, ipp_op_t op, int num_dests,
 /*
  * 'cupsAddDest()' - Add a destination to the list of destinations.
  *
- * Use the cupsSaveDests() function to save the updated list of destinations
- * to the user's lpoptions file.
+ * This function cannot be used to add a new class or printer queue,
+ * it only adds a new container of saved options for the named
+ * destination or instance.
+ *
+ * If the named destination already exists, the destination list is
+ * returned unchanged.  Adding a new instance of a destination creates
+ * a copy of that destination's options.
+ *
+ * Use the cupsSaveDests() function to save the updated list of
+ * destinations to the user's lpoptions file.
  */
 
 int                                    /* O  - New number of destinations */
-cupsAddDest(const char  *name,         /* I  - Name of destination */
-            const char *instance,      /* I  - Instance of destination or NULL for none/primary */
+cupsAddDest(const char  *name,         /* I  - Destination name */
+            const char *instance,      /* I  - Instance name or NULL for none/primary */
             int         num_dests,     /* I  - Number of destinations */
             cups_dest_t **dests)       /* IO - Destinations */
 {
   int          i;                      /* Looping var */
   cups_dest_t  *dest;                  /* Destination pointer */
+  cups_dest_t  *parent;                /* Parent destination */
+  cups_option_t        *option;                /* Current option */
 
 
-  if (name == NULL || dests == NULL)
+  if (!name || !dests)
     return (0);
 
   if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
@@ -97,27 +108,53 @@ cupsAddDest(const char  *name,             /* I  - Name of destination */
 
   *dests = dest;
 
+ /*
+  * Find where to insert the destination...
+  */
+
   for (i = num_dests; i > 0; i --, dest ++)
     if (strcasecmp(name, dest->name) < 0)
       break;
-    else if (strcasecmp(name, dest->name) == 0 &&
-             instance != NULL && dest->instance != NULL &&
+    else if (!instance && dest->instance)
+      break;
+    else if (!strcasecmp(name, dest->name) &&
+             instance  && dest->instance &&
              strcasecmp(instance, dest->instance) < 0)
       break;
 
   if (i > 0)
     memmove(dest + 1, dest, i * sizeof(cups_dest_t));
 
+ /*
+  * Initialize the destination...
+  */
+
   dest->name        = strdup(name);
   dest->is_default  = 0;
   dest->num_options = 0;
   dest->options     = (cups_option_t *)0;
 
-  if (instance == NULL)
+  if (!instance)
     dest->instance = NULL;
   else
+  {
+   /*
+    * Copy options from the primary instance...
+    */
+
     dest->instance = strdup(instance);
 
+    if ((parent = cupsGetDest(name, NULL, num_dests + 1, *dests)) != NULL)
+    {
+      for (i = parent->num_options, option = parent->options;
+           i > 0;
+          i --, option ++)
+       dest->num_options = cupsAddOption(option->name, option->value,
+                                         dest->num_options,
+                                         &(dest->options));
+    }
+  }
+
   return (num_dests + 1);
 }
 
@@ -159,18 +196,18 @@ cupsFreeDests(int         num_dests,      /* I - Number of destinations */
  */
 
 cups_dest_t *                          /* O - Destination pointer or NULL */
-cupsGetDest(const char  *name,         /* I - Name of destination */
-            const char *instance,      /* I - Instance of destination */
+cupsGetDest(const char  *name,         /* I - Destination name or NULL for the default destination */
+            const char *instance,      /* I - Instance name or NULL */
             int         num_dests,     /* I - Number of destinations */
             cups_dest_t *dests)                /* I - Destinations */
 {
   int  comp;                           /* Result of comparison */
 
 
-  if (num_dests == 0 || dests == NULL)
+  if (num_dests <= 0 || !dests)
     return (NULL);
 
-  if (name == NULL)
+  if (!name)
   {
    /*
     * NULL name for default printer.
@@ -197,9 +234,9 @@ cupsGetDest(const char  *name,              /* I - Name of destination */
        return (NULL);
       else if (comp == 0)
       {
-       if ((instance == NULL && dests->instance == NULL) ||
+       if ((!instance && !dests->instance) ||
             (instance != NULL && dests->instance != NULL &&
-            strcasecmp(instance, dests->instance) == 0))
+            !strcasecmp(instance, dests->instance)))
          return (dests);
       }
 
@@ -219,6 +256,9 @@ cupsGetDest(const char  *name,              /* I - Name of destination */
  * printer-info, printer-is-accepting-jobs, printer-is-shared,
  * printer-make-and-model, printer-state, printer-state-change-time,
  * printer-state-reasons, and printer-type attributes as options.
+ *
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
  */
 
 int                                    /* O - Number of destinations */
@@ -251,6 +291,9 @@ cupsGetDests(cups_dest_t **dests)   /* O - Destinations */
  * printer-make-and-model, printer-state, printer-state-change-time,
  * printer-state-reasons, and printer-type attributes as options.
  *
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
+ *
  * @since CUPS 1.1.21@
  */
 
@@ -262,7 +305,7 @@ cupsGetDests2(http_t      *http,    /* I - HTTP connection */
   int          num_dests;              /* Number of destinations */
   cups_dest_t  *dest;                  /* Destination pointer */
   const char   *home;                  /* HOME environment variable */
-  char         filename[1024];         /* Local ~/.lpoptions file */
+  char         filename[1024];         /* Local ~/.cups/lpoptions file */
   const char   *defprinter;            /* Default printer */
   char         name[1024],             /* Copy of printer name */
                *instance;              /* Pointer to instance name */
@@ -345,7 +388,7 @@ cupsGetDests2(http_t      *http,    /* I - HTTP connection */
   }
 
  /*
-  * Load the /etc/cups/lpoptions and ~/.lpoptions files...
+  * Load the /etc/cups/lpoptions and ~/.cups/lpoptions files...
   */
 
   snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
@@ -353,13 +396,16 @@ cupsGetDests2(http_t      *http,  /* I - HTTP connection */
 
   if ((home = getenv("HOME")) != NULL)
   {
-    snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
+    snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
+    if (access(filename, 0))
+      snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
+
     num_dests = cups_get_dests(filename, num_dests, dests);
   }
 
  /*
   * Validate the current default destination - this prevents old
-  * Default lines in /etc/cups/lpoptions and ~/.lpoptions from
+  * Default lines in /etc/cups/lpoptions and ~/.cups/lpoptions from
   * pointing to a non-existent printer or class...
   */
 
@@ -411,7 +457,7 @@ cupsGetDests2(http_t      *http,    /* I - HTTP connection */
  * 'cupsSetDests()' - Save the list of destinations for the default server.
  *
  * This function saves the destinations to /etc/cups/lpoptions when run
- * as root and ~/.lpoptions when run as a normal user.
+ * as root and ~/.cups/lpoptions when run as a normal user.
  */
 
 void
@@ -438,7 +484,7 @@ cupsSetDests(int         num_dests, /* I - Number of destinations */
  * 'cupsSetDests2()' - Save the list of destinations for the specified server.
  *
  * This function saves the destinations to /etc/cups/lpoptions when run
- * as root and ~/.lpoptions when run as a normal user.
+ * as root and ~/.cups/lpoptions when run as a normal user.
  *
  * @since CUPS 1.1.21@
  */
@@ -452,6 +498,7 @@ cupsSetDests2(http_t      *http,    /* I - HTTP connection */
   int          wrote;                  /* Wrote definition? */
   cups_dest_t  *dest;                  /* Current destination */
   cups_option_t        *option;                /* Current option */
+  _ipp_option_t        *match;                 /* Matching attribute for option */
   FILE         *fp;                    /* File pointer */
   const char   *home;                  /* HOME environment variable */
   char         filename[1024];         /* lpoptions file */
@@ -496,7 +543,24 @@ cupsSetDests2(http_t      *http,   /* I - HTTP connection */
     */
 
     if ((home = getenv("HOME")) != NULL)
+    {
+     /*
+      * Remove the old ~/.lpoptions file...
+      */
+
       snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
+      unlink(filename);
+
+     /*
+      * Create ~/.cups subdirectory...
+      */
+
+      snprintf(filename, sizeof(filename), "%s/.cups", home);
+      if (access(filename, 0))
+        mkdir(filename, 0700);
+
+      snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
+    }
   }
 #endif /* !WIN32 */
 
@@ -510,6 +574,16 @@ cupsSetDests2(http_t      *http,   /* I - HTTP connection */
     return (-1);
   }
 
+#ifndef WIN32
+ /*
+  * Set the permissions to 0644 when saving to the /etc/cups/lpoptions
+  * file...
+  */
+
+  if (!getuid())
+    fchmod(fileno(fp), 0644);
+#endif /* !WIN32 */
+
  /*
   * Write each printer; each line looks like:
   *
@@ -536,17 +610,24 @@ cupsSetDests2(http_t      *http,  /* I - HTTP connection */
 
       for (j = dest->num_options, option = dest->options; j > 0; j --, option ++)
       {
+       /*
+        * See if this option is a printer attribute; if so, skip it...
+       */
+
+        if ((match = _ippFindOption(option->name)) != NULL &&
+           match->group_tag == IPP_TAG_PRINTER)
+         continue;
+
        /*
        * See if the server/global options match these; if so, don't
        * write 'em.
        */
 
-        if (temp && (val = cupsGetOption(option->name, temp->num_options,
-                                        temp->options)) != NULL)
-       {
-         if (strcasecmp(val, option->value) == 0)
-           continue;
-       }
+        if (temp &&
+           (val = cupsGetOption(option->name, temp->num_options,
+                                temp->options)) != NULL &&
+            !strcasecmp(val, option->value))
+         continue;
 
        /*
         * Options don't match, write to the file...
@@ -562,10 +643,35 @@ cupsSetDests2(http_t      *http,  /* I - HTTP connection */
         
         if (option->value[0])
        {
-         if (strchr(option->value, ' ') != NULL)
-           fprintf(fp, " %s=\"%s\"", option->name, option->value);
-          else
+         if (strchr(option->value, ' ') ||
+             strchr(option->value, '\\') ||
+             strchr(option->value, '\"') ||
+             strchr(option->value, '\''))
+         {
+          /*
+           * Quote the value...
+           */
+
+           fprintf(fp, " %s=\"", option->name);
+
+           for (val = option->value; *val; val ++)
+           {
+             if (strchr("\"\'\\", *val))
+               putc('\\', fp);
+
+              putc(*val, fp);
+           }
+
+           putc('\"', fp);
+          }
+         else
+         {
+          /*
+           * Store the literal value...
+           */
+
            fprintf(fp, " %s=%s", option->name, option->value);
+          }
        }
        else
          fprintf(fp, " %s", option->name);
@@ -977,5 +1083,5 @@ cups_get_sdests(http_t      *http, /* I - HTTP connection */
 
 
 /*
- * End of "$Id: dest.c 5138 2006-02-21 10:49:06Z mike $".
+ * End of "$Id: dest.c 6044 2006-10-17 20:32:59Z mike $".
  */