"Fossies" - the Fresh Open Source Software Archive

Member "cups-2.3rc1/cups/adminutil.c" (21 May 2019, 40652 Bytes) of package /linux/misc/cups-2.3rc1-source.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "adminutil.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.2.11_vs_2.3b8.

    1 /*
    2  * Administration utility API definitions for CUPS.
    3  *
    4  * Copyright © 2007-2018 by Apple Inc.
    5  * Copyright © 2001-2007 by Easy Software Products.
    6  *
    7  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
    8  * information.
    9  */
   10 
   11 /*
   12  * Include necessary headers...
   13  */
   14 
   15 #include "cups-private.h"
   16 #include "debug-internal.h"
   17 #include "ppd.h"
   18 #include "adminutil.h"
   19 #include <fcntl.h>
   20 #include <sys/stat.h>
   21 #ifndef _WIN32
   22 #  include <unistd.h>
   23 #  include <sys/wait.h>
   24 #endif /* !_WIN32 */
   25 
   26 
   27 /*
   28  * Local functions...
   29  */
   30 
   31 static http_status_t    get_cupsd_conf(http_t *http, _cups_globals_t *cg,
   32                            time_t last_update, char *name,
   33                        size_t namelen, int *remote);
   34 static void     invalidate_cupsd_cache(_cups_globals_t *cg);
   35 
   36 
   37 /*
   38  * 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer.
   39  *
   40  * @deprecated@
   41  */
   42 
   43 char *                  /* O - PPD file or NULL */
   44 cupsAdminCreateWindowsPPD(
   45     http_t     *http,           /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
   46     const char *dest,           /* I - Printer or class */
   47     char       *buffer,         /* I - Filename buffer */
   48     int        bufsize)         /* I - Size of filename buffer */
   49 {
   50   (void)http;
   51   (void)dest;
   52   (void)bufsize;
   53 
   54   if (buffer)
   55     *buffer = '\0';
   56 
   57   return (NULL);
   58 }
   59 
   60 
   61 /*
   62  * 'cupsAdminExportSamba()' - Export a printer to Samba.
   63  *
   64  * @deprecated@
   65  */
   66 
   67 int                 /* O - 1 on success, 0 on failure */
   68 cupsAdminExportSamba(
   69     const char *dest,           /* I - Destination to export */
   70     const char *ppd,            /* I - PPD file */
   71     const char *samba_server,       /* I - Samba server */
   72     const char *samba_user,     /* I - Samba username */
   73     const char *samba_password,     /* I - Samba password */
   74     FILE       *logfile)        /* I - Log file, if any */
   75 {
   76   (void)dest;
   77   (void)ppd;
   78   (void)samba_server;
   79   (void)samba_user;
   80   (void)samba_password;
   81   (void)logfile;
   82 
   83   return (0);
   84 }
   85 
   86 
   87 /*
   88  * 'cupsAdminGetServerSettings()' - Get settings from the server.
   89  *
   90  * The returned settings should be freed with cupsFreeOptions() when
   91  * you are done with them.
   92  *
   93  * @since CUPS 1.3/macOS 10.5@
   94  */
   95 
   96 int                 /* O - 1 on success, 0 on failure */
   97 cupsAdminGetServerSettings(
   98     http_t        *http,        /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
   99     int           *num_settings,    /* O - Number of settings */
  100     cups_option_t **settings)       /* O - Settings */
  101 {
  102   int       i;          /* Looping var */
  103   cups_file_t   *cupsd;         /* cupsd.conf file */
  104   char      cupsdconf[1024];    /* cupsd.conf filename */
  105   int       remote;         /* Remote cupsd.conf file? */
  106   http_status_t status;         /* Status of getting cupsd.conf */
  107   char      line[1024],     /* Line from cupsd.conf file */
  108         *value;         /* Value on line */
  109   cups_option_t *setting;       /* Current setting */
  110   _cups_globals_t *cg = _cupsGlobals(); /* Global data */
  111 
  112 
  113  /*
  114   * Range check input...
  115   */
  116 
  117   if (!http)
  118   {
  119    /*
  120     * See if we are connected to the same server...
  121     */
  122 
  123     if (cg->http)
  124     {
  125      /*
  126       * Compare the connection hostname, port, and encryption settings to
  127       * the cached defaults; these were initialized the first time we
  128       * connected...
  129       */
  130 
  131       if (strcmp(cg->http->hostname, cg->server) ||
  132           cg->ipp_port != httpAddrPort(cg->http->hostaddr) ||
  133       (cg->http->encryption != cg->encryption &&
  134        cg->http->encryption == HTTP_ENCRYPTION_NEVER))
  135       {
  136        /*
  137     * Need to close the current connection because something has changed...
  138     */
  139 
  140     httpClose(cg->http);
  141     cg->http = NULL;
  142       }
  143     }
  144 
  145    /*
  146     * (Re)connect as needed...
  147     */
  148 
  149     if (!cg->http)
  150     {
  151       if ((cg->http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
  152                                    cupsEncryption(), 1, 0, NULL)) == NULL)
  153       {
  154     if (errno)
  155       _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, NULL, 0);
  156     else
  157       _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE,
  158             _("Unable to connect to host."), 1);
  159 
  160     if (num_settings)
  161       *num_settings = 0;
  162 
  163     if (settings)
  164       *settings = NULL;
  165 
  166     return (0);
  167       }
  168     }
  169 
  170     http = cg->http;
  171   }
  172 
  173   if (!http || !num_settings || !settings)
  174   {
  175     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
  176 
  177     if (num_settings)
  178       *num_settings = 0;
  179 
  180     if (settings)
  181       *settings = NULL;
  182 
  183     return (0);
  184   }
  185 
  186   *num_settings = 0;
  187   *settings     = NULL;
  188 
  189  /*
  190   * Get the cupsd.conf file...
  191   */
  192 
  193   if ((status = get_cupsd_conf(http, cg, cg->cupsd_update, cupsdconf,
  194                                sizeof(cupsdconf), &remote)) == HTTP_STATUS_OK)
  195   {
  196     if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
  197     {
  198       char  message[1024];      /* Message string */
  199 
  200 
  201       snprintf(message, sizeof(message),
  202                _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
  203                cupsdconf, strerror(errno));
  204       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0);
  205     }
  206   }
  207   else
  208     cupsd = NULL;
  209 
  210   if (cupsd)
  211   {
  212    /*
  213     * Read the file, keeping track of what settings are enabled...
  214     */
  215 
  216     int     remote_access = 0,  /* Remote access allowed? */
  217         remote_admin = 0,   /* Remote administration allowed? */
  218         remote_any = 0,     /* Remote access from anywhere allowed? */
  219         browsing = 1,       /* Browsing enabled? */
  220         cancel_policy = 1,  /* Cancel-job policy set? */
  221         debug_logging = 0;  /* LogLevel debug set? */
  222     int     linenum = 0,        /* Line number in file */
  223         in_location = 0,    /* In a location section? */
  224         in_policy = 0,      /* In a policy section? */
  225         in_cancel_job = 0,  /* In a cancel-job section? */
  226         in_admin_location = 0;  /* In the /admin location? */
  227 
  228 
  229     invalidate_cupsd_cache(cg);
  230 
  231     cg->cupsd_update = time(NULL);
  232     httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname));
  233 
  234     while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
  235     {
  236       if (!value && strncmp(line, "</", 2))
  237         value = line + strlen(line);
  238 
  239       if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && value)
  240       {
  241     char    *port;          /* Pointer to port number, if any */
  242 
  243 
  244     if ((port = strrchr(value, ':')) != NULL)
  245       *port = '\0';
  246     else if (isdigit(*value & 255))
  247     {
  248      /*
  249       * Listen on a port number implies remote access...
  250       */
  251 
  252       remote_access = 1;
  253       continue;
  254     }
  255 
  256     if (_cups_strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1")
  257 #ifdef AF_LOCAL
  258             && *value != '/'
  259 #endif /* AF_LOCAL */
  260 #ifdef AF_INET6
  261             && strcmp(value, "[::1]")
  262 #endif /* AF_INET6 */
  263         )
  264       remote_access = 1;
  265       }
  266       else if (!_cups_strcasecmp(line, "Browsing"))
  267       {
  268     browsing = !_cups_strcasecmp(value, "yes") ||
  269                !_cups_strcasecmp(value, "on") ||
  270                !_cups_strcasecmp(value, "true");
  271       }
  272       else if (!_cups_strcasecmp(line, "LogLevel"))
  273       {
  274     debug_logging = !_cups_strncasecmp(value, "debug", 5);
  275       }
  276       else if (!_cups_strcasecmp(line, "<Policy") &&
  277                !_cups_strcasecmp(value, "default"))
  278       {
  279     in_policy = 1;
  280       }
  281       else if (!_cups_strcasecmp(line, "</Policy>"))
  282       {
  283     in_policy = 0;
  284       }
  285       else if (!_cups_strcasecmp(line, "<Limit") && in_policy && value)
  286       {
  287        /*
  288     * See if the policy limit is for the Cancel-Job operation...
  289     */
  290 
  291     char    *valptr;        /* Pointer into value */
  292 
  293 
  294     while (*value)
  295     {
  296       for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);
  297 
  298       if (*valptr)
  299         *valptr++ = '\0';
  300 
  301           if (!_cups_strcasecmp(value, "cancel-job") ||
  302               !_cups_strcasecmp(value, "all"))
  303       {
  304         in_cancel_job = 1;
  305         break;
  306       }
  307 
  308           for (value = valptr; _cups_isspace(*value); value ++);
  309     }
  310       }
  311       else if (!_cups_strcasecmp(line, "</Limit>"))
  312       {
  313     in_cancel_job = 0;
  314       }
  315       else if (!_cups_strcasecmp(line, "Require") && in_cancel_job)
  316       {
  317     cancel_policy = 0;
  318       }
  319       else if (!_cups_strcasecmp(line, "<Location") && value)
  320       {
  321         in_admin_location = !_cups_strcasecmp(value, "/admin");
  322     in_location       = 1;
  323       }
  324       else if (!_cups_strcasecmp(line, "</Location>"))
  325       {
  326     in_admin_location = 0;
  327     in_location       = 0;
  328       }
  329       else if (!_cups_strcasecmp(line, "Allow") && value &&
  330                _cups_strcasecmp(value, "localhost") &&
  331                _cups_strcasecmp(value, "127.0.0.1")
  332 #ifdef AF_LOCAL
  333            && *value != '/'
  334 #endif /* AF_LOCAL */
  335 #ifdef AF_INET6
  336            && strcmp(value, "::1")
  337 #endif /* AF_INET6 */
  338            )
  339       {
  340         if (in_admin_location)
  341       remote_admin = 1;
  342         else if (!_cups_strcasecmp(value, "all"))
  343       remote_any = 1;
  344       }
  345       else if (line[0] != '<' && !in_location && !in_policy &&
  346            _cups_strcasecmp(line, "Allow") &&
  347                _cups_strcasecmp(line, "AuthType") &&
  348            _cups_strcasecmp(line, "Deny") &&
  349            _cups_strcasecmp(line, "Order") &&
  350            _cups_strcasecmp(line, "Require") &&
  351            _cups_strcasecmp(line, "Satisfy"))
  352         cg->cupsd_num_settings = cupsAddOption(line, value,
  353                                            cg->cupsd_num_settings,
  354                            &(cg->cupsd_settings));
  355     }
  356 
  357     cupsFileClose(cupsd);
  358 
  359     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
  360                                            debug_logging ? "1" : "0",
  361                        cg->cupsd_num_settings,
  362                        &(cg->cupsd_settings));
  363 
  364     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
  365                                            (remote_access && remote_admin) ?
  366                            "1" : "0",
  367                        cg->cupsd_num_settings,
  368                        &(cg->cupsd_settings));
  369 
  370     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
  371                                            remote_any ? "1" : "0",
  372                        cg->cupsd_num_settings,
  373                        &(cg->cupsd_settings));
  374 
  375     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
  376                                            (remote_access && browsing) ? "1" :
  377                                                                          "0",
  378                        cg->cupsd_num_settings,
  379                        &(cg->cupsd_settings));
  380 
  381     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
  382                                            cancel_policy ? "1" : "0",
  383                        cg->cupsd_num_settings,
  384                        &(cg->cupsd_settings));
  385   }
  386   else if (status != HTTP_STATUS_NOT_MODIFIED)
  387     invalidate_cupsd_cache(cg);
  388 
  389  /*
  390   * Remove any temporary files and copy the settings array...
  391   */
  392 
  393   if (remote)
  394     unlink(cupsdconf);
  395 
  396   for (i = cg->cupsd_num_settings, setting = cg->cupsd_settings;
  397        i > 0;
  398        i --, setting ++)
  399     *num_settings = cupsAddOption(setting->name, setting->value,
  400                                   *num_settings, settings);
  401 
  402   return (cg->cupsd_num_settings > 0);
  403 }
  404 
  405 
  406 /*
  407  * 'cupsAdminSetServerSettings()' - Set settings on the server.
  408  *
  409  * @since CUPS 1.3/macOS 10.5@
  410  */
  411 
  412 int                 /* O - 1 on success, 0 on failure */
  413 cupsAdminSetServerSettings(
  414     http_t        *http,        /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
  415     int           num_settings,     /* I - Number of settings */
  416     cups_option_t *settings)        /* I - Settings */
  417 {
  418   int       i;          /* Looping var */
  419   http_status_t status;         /* GET/PUT status */
  420   const char    *server_port_env;   /* SERVER_PORT env var */
  421   int       server_port;        /* IPP port for server */
  422   cups_file_t   *cupsd;         /* cupsd.conf file */
  423   char      cupsdconf[1024];    /* cupsd.conf filename */
  424   int       remote;         /* Remote cupsd.conf file? */
  425   char      tempfile[1024];     /* Temporary new cupsd.conf */
  426   cups_file_t   *temp;          /* Temporary file */
  427   char      line[1024],     /* Line from cupsd.conf file */
  428         *value;         /* Value on line */
  429   int       linenum,        /* Line number in file */
  430         in_location,        /* In a location section? */
  431         in_policy,      /* In a policy section? */
  432         in_default_policy,  /* In the default policy section? */
  433         in_cancel_job,      /* In a cancel-job section? */
  434         in_admin_location,  /* In the /admin location? */
  435         in_conf_location,   /* In the /admin/conf location? */
  436         in_log_location,    /* In the /admin/log location? */
  437         in_root_location;   /* In the / location? */
  438   const char    *val;           /* Setting value */
  439   int       share_printers,     /* Share local printers */
  440         remote_admin,       /* Remote administration allowed? */
  441         remote_any,     /* Remote access from anywhere? */
  442         user_cancel_any,    /* Cancel-job policy set? */
  443         debug_logging;      /* LogLevel debug set? */
  444   int       wrote_port_listen,  /* Wrote the port/listen lines? */
  445         wrote_browsing,     /* Wrote the browsing lines? */
  446         wrote_policy,       /* Wrote the policy? */
  447         wrote_loglevel,     /* Wrote the LogLevel line? */
  448         wrote_admin_location,   /* Wrote the /admin location? */
  449         wrote_conf_location,    /* Wrote the /admin/conf location? */
  450         wrote_log_location, /* Wrote the /admin/log location? */
  451         wrote_root_location;    /* Wrote the / location? */
  452   int       indent;         /* Indentation */
  453   int       cupsd_num_settings; /* New number of settings */
  454   int       old_share_printers, /* Share local printers */
  455         old_remote_admin,   /* Remote administration allowed? */
  456         old_remote_any,     /* Remote access from anywhere? */
  457         old_user_cancel_any,    /* Cancel-job policy set? */
  458         old_debug_logging;  /* LogLevel debug set? */
  459   cups_option_t *cupsd_settings,    /* New settings */
  460         *setting;       /* Current setting */
  461   _cups_globals_t *cg = _cupsGlobals(); /* Global data */
  462 
  463 
  464  /*
  465   * Range check input...
  466   */
  467 
  468   if (!http)
  469     http = _cupsConnect();
  470 
  471   if (!http || !num_settings || !settings)
  472   {
  473     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
  474 
  475     return (0);
  476   }
  477 
  478  /*
  479   * Get the cupsd.conf file...
  480   */
  481 
  482   if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf),
  483                      &remote) == HTTP_STATUS_OK)
  484   {
  485     if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
  486     {
  487       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
  488       return (0);
  489     }
  490   }
  491   else
  492     return (0);
  493 
  494  /*
  495   * Get current settings...
  496   */
  497 
  498   if (!cupsAdminGetServerSettings(http, &cupsd_num_settings,
  499                   &cupsd_settings))
  500     return (0);
  501 
  502   if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, cupsd_num_settings,
  503                            cupsd_settings)) != NULL)
  504     old_debug_logging = atoi(val);
  505   else
  506     old_debug_logging = 0;
  507 
  508   DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d",
  509                 old_debug_logging));
  510 
  511   if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, cupsd_num_settings,
  512                            cupsd_settings)) != NULL)
  513     old_remote_admin = atoi(val);
  514   else
  515     old_remote_admin = 0;
  516 
  517   DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d",
  518                 old_remote_admin));
  519 
  520   if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, cupsd_num_settings,
  521                            cupsd_settings)) != NULL)
  522     old_remote_any = atoi(val);
  523   else
  524     old_remote_any = 0;
  525 
  526   DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d",
  527                 old_remote_any));
  528 
  529   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings,
  530                            cupsd_settings)) != NULL)
  531     old_share_printers = atoi(val);
  532   else
  533     old_share_printers = 0;
  534 
  535   DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d",
  536                 old_share_printers));
  537 
  538   if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, cupsd_num_settings,
  539                            cupsd_settings)) != NULL)
  540     old_user_cancel_any = atoi(val);
  541   else
  542     old_user_cancel_any = 0;
  543 
  544   DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d",
  545                 old_user_cancel_any));
  546 
  547   cupsFreeOptions(cupsd_num_settings, cupsd_settings);
  548 
  549  /*
  550   * Get basic settings...
  551   */
  552 
  553   if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings,
  554                            settings)) != NULL)
  555   {
  556     debug_logging = atoi(val);
  557 
  558     if (debug_logging == old_debug_logging)
  559     {
  560      /*
  561       * No change to this setting...
  562       */
  563 
  564       debug_logging = -1;
  565     }
  566   }
  567   else
  568     debug_logging = -1;
  569 
  570   DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d",
  571                 debug_logging));
  572 
  573   if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, settings)) != NULL)
  574   {
  575     remote_any = atoi(val);
  576 
  577     if (remote_any == old_remote_any)
  578     {
  579      /*
  580       * No change to this setting...
  581       */
  582 
  583       remote_any = -1;
  584     }
  585   }
  586   else
  587     remote_any = -1;
  588 
  589   DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any));
  590 
  591   if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings,
  592                            settings)) != NULL)
  593   {
  594     remote_admin = atoi(val);
  595 
  596     if (remote_admin == old_remote_admin)
  597     {
  598      /*
  599       * No change to this setting...
  600       */
  601 
  602       remote_admin = -1;
  603     }
  604   }
  605   else
  606     remote_admin = -1;
  607 
  608   DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d",
  609                 remote_admin));
  610 
  611   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
  612                            settings)) != NULL)
  613   {
  614     share_printers = atoi(val);
  615 
  616     if (share_printers == old_share_printers)
  617     {
  618      /*
  619       * No change to this setting...
  620       */
  621 
  622       share_printers = -1;
  623     }
  624   }
  625   else
  626     share_printers = -1;
  627 
  628   DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d",
  629                 share_printers));
  630 
  631   if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings,
  632                            settings)) != NULL)
  633   {
  634     user_cancel_any = atoi(val);
  635 
  636     if (user_cancel_any == old_user_cancel_any)
  637     {
  638      /*
  639       * No change to this setting...
  640       */
  641 
  642       user_cancel_any = -1;
  643     }
  644   }
  645   else
  646     user_cancel_any = -1;
  647 
  648   DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d",
  649                 user_cancel_any));
  650 
  651  /*
  652   * Create a temporary file for the new cupsd.conf file...
  653   */
  654 
  655   if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
  656   {
  657     cupsFileClose(cupsd);
  658 
  659     if (remote)
  660       unlink(cupsdconf);
  661 
  662     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
  663     return (0);
  664   }
  665 
  666  /*
  667   * Copy the old file to the new, making changes along the way...
  668   */
  669 
  670   cupsd_num_settings   = 0;
  671   in_admin_location    = 0;
  672   in_cancel_job        = 0;
  673   in_conf_location     = 0;
  674   in_default_policy    = 0;
  675   in_location          = 0;
  676   in_log_location      = 0;
  677   in_policy            = 0;
  678   in_root_location     = 0;
  679   linenum              = 0;
  680   wrote_admin_location = 0;
  681   wrote_browsing       = 0;
  682   wrote_conf_location  = 0;
  683   wrote_log_location   = 0;
  684   wrote_loglevel       = 0;
  685   wrote_policy         = 0;
  686   wrote_port_listen    = 0;
  687   wrote_root_location  = 0;
  688   indent               = 0;
  689 
  690   if ((server_port_env = getenv("SERVER_PORT")) != NULL)
  691   {
  692     if ((server_port = atoi(server_port_env)) <= 0)
  693       server_port = ippPort();
  694   }
  695   else
  696     server_port = ippPort();
  697 
  698   if (server_port <= 0)
  699     server_port = IPP_PORT;
  700 
  701   while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
  702   {
  703     if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) &&
  704         (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
  705     {
  706       if (!wrote_port_listen)
  707       {
  708         wrote_port_listen = 1;
  709 
  710     if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
  711     {
  712       cupsFilePuts(temp, "# Allow remote access\n");
  713       cupsFilePrintf(temp, "Port %d\n", server_port);
  714     }
  715     else
  716     {
  717       cupsFilePuts(temp, "# Only listen for connections from the local "
  718                          "machine.\n");
  719       cupsFilePrintf(temp, "Listen localhost:%d\n", server_port);
  720     }
  721 
  722 #ifdef CUPS_DEFAULT_DOMAINSOCKET
  723         if ((!value || strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)) &&
  724         !access(CUPS_DEFAULT_DOMAINSOCKET, 0))
  725           cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
  726 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
  727       }
  728       else if (value && value[0] == '/'
  729 #ifdef CUPS_DEFAULT_DOMAINSOCKET
  730                && strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)
  731 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
  732                )
  733         cupsFilePrintf(temp, "Listen %s\n", value);
  734     }
  735     else if ((!_cups_strcasecmp(line, "Browsing") ||
  736               !_cups_strcasecmp(line, "BrowseLocalProtocols")) &&
  737          share_printers >= 0)
  738     {
  739       if (!wrote_browsing)
  740       {
  741     int new_share_printers = (share_printers > 0 ||
  742                   (share_printers == -1 &&
  743                    old_share_printers > 0));
  744 
  745         wrote_browsing = 1;
  746 
  747         if (new_share_printers)
  748     {
  749       const char *localp = cupsGetOption("BrowseLocalProtocols",
  750                          num_settings, settings);
  751 
  752           if (!localp || !localp[0])
  753         localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings,
  754                                cupsd_settings);
  755 
  756       cupsFilePuts(temp, "# Share local printers on the local network.\n");
  757       cupsFilePuts(temp, "Browsing On\n");
  758 
  759       if (!localp)
  760         localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
  761 
  762       cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp);
  763 
  764       cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp,
  765                          cupsd_num_settings,
  766                          &cupsd_settings);
  767         }
  768     else
  769     {
  770       cupsFilePuts(temp, "# Disable printer sharing.\n");
  771       cupsFilePuts(temp, "Browsing Off\n");
  772     }
  773       }
  774     }
  775     else if (!_cups_strcasecmp(line, "LogLevel") && debug_logging >= 0)
  776     {
  777       wrote_loglevel = 1;
  778 
  779       if (debug_logging)
  780       {
  781         cupsFilePuts(temp,
  782                  "# Show troubleshooting information in error_log.\n");
  783     cupsFilePuts(temp, "LogLevel debug\n");
  784       }
  785       else
  786       {
  787         cupsFilePuts(temp, "# Show general information in error_log.\n");
  788     cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
  789       }
  790     }
  791     else if (!_cups_strcasecmp(line, "<Policy"))
  792     {
  793       in_default_policy = !_cups_strcasecmp(value, "default");
  794       in_policy         = 1;
  795 
  796       cupsFilePrintf(temp, "%s %s>\n", line, value);
  797       indent += 2;
  798     }
  799     else if (!_cups_strcasecmp(line, "</Policy>"))
  800     {
  801       indent -= 2;
  802       if (!wrote_policy && in_default_policy)
  803       {
  804     wrote_policy = 1;
  805 
  806         if (!user_cancel_any)
  807       cupsFilePuts(temp, "  # Only the owner or an administrator can "
  808                          "cancel a job...\n"
  809                          "  <Limit Cancel-Job>\n"
  810                          "    Order deny,allow\n"
  811                  "    Require user @OWNER "
  812                  CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
  813                  "  </Limit>\n");
  814       }
  815 
  816       in_policy         = 0;
  817       in_default_policy = 0;
  818 
  819       cupsFilePuts(temp, "</Policy>\n");
  820     }
  821     else if (!_cups_strcasecmp(line, "<Location"))
  822     {
  823       in_location = 1;
  824       indent += 2;
  825       if (!strcmp(value, "/admin"))
  826     in_admin_location = 1;
  827       else if (!strcmp(value, "/admin/conf"))
  828     in_conf_location = 1;
  829       else if (!strcmp(value, "/admin/log"))
  830     in_log_location = 1;
  831       else if (!strcmp(value, "/"))
  832     in_root_location = 1;
  833 
  834       cupsFilePrintf(temp, "%s %s>\n", line, value);
  835     }
  836     else if (!_cups_strcasecmp(line, "</Location>"))
  837     {
  838       in_location = 0;
  839       indent -= 2;
  840       if (in_admin_location && remote_admin >= 0)
  841       {
  842     wrote_admin_location = 1;
  843 
  844     if (remote_admin)
  845           cupsFilePuts(temp, "  # Allow remote administration...\n");
  846     else if (remote_admin == 0)
  847           cupsFilePuts(temp, "  # Restrict access to the admin pages...\n");
  848 
  849         cupsFilePuts(temp, "  Order allow,deny\n");
  850 
  851     if (remote_admin)
  852       cupsFilePrintf(temp, "  Allow %s\n",
  853                      remote_any > 0 ? "all" : "@LOCAL");
  854       }
  855       else if (in_conf_location && remote_admin >= 0)
  856       {
  857     wrote_conf_location = 1;
  858 
  859     if (remote_admin)
  860           cupsFilePuts(temp, "  # Allow remote access to the configuration "
  861                          "files...\n");
  862     else
  863           cupsFilePuts(temp, "  # Restrict access to the configuration "
  864                          "files...\n");
  865 
  866         cupsFilePuts(temp, "  Order allow,deny\n");
  867 
  868     if (remote_admin)
  869       cupsFilePrintf(temp, "  Allow %s\n",
  870                      remote_any > 0 ? "all" : "@LOCAL");
  871       }
  872       else if (in_log_location && remote_admin >= 0)
  873       {
  874     wrote_log_location = 1;
  875 
  876     if (remote_admin)
  877           cupsFilePuts(temp, "  # Allow remote access to the log "
  878                          "files...\n");
  879     else
  880           cupsFilePuts(temp, "  # Restrict access to the log "
  881                          "files...\n");
  882 
  883         cupsFilePuts(temp, "  Order allow,deny\n");
  884 
  885     if (remote_admin)
  886       cupsFilePrintf(temp, "  Allow %s\n",
  887                      remote_any > 0 ? "all" : "@LOCAL");
  888       }
  889       else if (in_root_location &&
  890                (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
  891       {
  892     wrote_root_location = 1;
  893 
  894     if (remote_admin > 0 && share_printers > 0)
  895           cupsFilePuts(temp, "  # Allow shared printing and remote "
  896                          "administration...\n");
  897     else if (remote_admin > 0)
  898           cupsFilePuts(temp, "  # Allow remote administration...\n");
  899     else if (share_printers > 0)
  900           cupsFilePuts(temp, "  # Allow shared printing...\n");
  901     else if (remote_any > 0)
  902           cupsFilePuts(temp, "  # Allow remote access...\n");
  903     else
  904           cupsFilePuts(temp, "  # Restrict access to the server...\n");
  905 
  906         cupsFilePuts(temp, "  Order allow,deny\n");
  907 
  908     if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
  909       cupsFilePrintf(temp, "  Allow %s\n",
  910                      remote_any > 0 ? "all" : "@LOCAL");
  911       }
  912 
  913       in_admin_location = 0;
  914       in_conf_location  = 0;
  915       in_log_location   = 0;
  916       in_root_location  = 0;
  917 
  918       cupsFilePuts(temp, "</Location>\n");
  919     }
  920     else if (!_cups_strcasecmp(line, "<Limit"))
  921     {
  922       if (in_default_policy)
  923       {
  924        /*
  925     * See if the policy limit is for the Cancel-Job operation...
  926     */
  927 
  928     char    *valptr;        /* Pointer into value */
  929 
  930 
  931     if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0)
  932     {
  933      /*
  934       * Don't write anything for this limit section...
  935       */
  936 
  937       in_cancel_job = 2;
  938     }
  939     else
  940     {
  941       cupsFilePrintf(temp, "%*s%s", indent, "", line);
  942 
  943       while (*value)
  944       {
  945         for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);
  946 
  947         if (*valptr)
  948           *valptr++ = '\0';
  949 
  950         if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0)
  951         {
  952          /*
  953           * Write everything except for this definition...
  954           */
  955 
  956           in_cancel_job = 1;
  957         }
  958         else
  959           cupsFilePrintf(temp, " %s", value);
  960 
  961         for (value = valptr; _cups_isspace(*value); value ++);
  962       }
  963 
  964       cupsFilePuts(temp, ">\n");
  965     }
  966       }
  967       else
  968         cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value);
  969 
  970       indent += 2;
  971     }
  972     else if (!_cups_strcasecmp(line, "</Limit>") && in_cancel_job)
  973     {
  974       indent -= 2;
  975 
  976       if (in_cancel_job == 1)
  977     cupsFilePuts(temp, "  </Limit>\n");
  978 
  979       wrote_policy = 1;
  980 
  981       if (!user_cancel_any)
  982     cupsFilePuts(temp, "  # Only the owner or an administrator can cancel "
  983                "a job...\n"
  984                "  <Limit Cancel-Job>\n"
  985                "    Order deny,allow\n"
  986                "    Require user @OWNER "
  987                CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
  988                "  </Limit>\n");
  989 
  990       in_cancel_job = 0;
  991     }
  992     else if ((((in_admin_location || in_conf_location || in_root_location) &&
  993                (remote_admin >= 0 || remote_any >= 0)) ||
  994               (in_root_location && share_printers >= 0)) &&
  995              (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny") ||
  996           !_cups_strcasecmp(line, "Order")))
  997       continue;
  998     else if (in_cancel_job == 2)
  999       continue;
 1000     else if (line[0] == '<')
 1001     {
 1002       if (value)
 1003       {
 1004         cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value);
 1005     indent += 2;
 1006       }
 1007       else
 1008       {
 1009     if (line[1] == '/')
 1010       indent -= 2;
 1011 
 1012     cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
 1013       }
 1014     }
 1015     else if (!in_policy && !in_location &&
 1016              (val = cupsGetOption(line, num_settings, settings)) != NULL)
 1017     {
 1018      /*
 1019       * Replace this directive's value with the new one...
 1020       */
 1021 
 1022       cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings,
 1023                                          &cupsd_settings);
 1024 
 1025      /*
 1026       * Write the new value in its place, without indentation since we
 1027       * only support setting root directives, not in sections...
 1028       */
 1029 
 1030       cupsFilePrintf(temp, "%s %s\n", line, val);
 1031     }
 1032     else if (value)
 1033     {
 1034       if (!in_policy && !in_location)
 1035       {
 1036        /*
 1037         * Record the non-policy, non-location directives that we find
 1038     * in the server settings, since we cache this info and record it
 1039     * in cupsAdminGetServerSettings()...
 1040     */
 1041 
 1042     cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings,
 1043                                            &cupsd_settings);
 1044       }
 1045 
 1046       cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value);
 1047     }
 1048     else
 1049       cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
 1050   }
 1051 
 1052  /*
 1053   * Write any missing info...
 1054   */
 1055 
 1056   if (!wrote_browsing && share_printers >= 0)
 1057   {
 1058     if (share_printers > 0)
 1059     {
 1060       cupsFilePuts(temp, "# Share local printers on the local network.\n");
 1061       cupsFilePuts(temp, "Browsing On\n");
 1062     }
 1063     else
 1064     {
 1065       cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n");
 1066       cupsFilePuts(temp, "Browsing Off\n");
 1067     }
 1068   }
 1069 
 1070   if (!wrote_loglevel && debug_logging >= 0)
 1071   {
 1072     if (debug_logging)
 1073     {
 1074       cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n");
 1075       cupsFilePuts(temp, "LogLevel debug\n");
 1076     }
 1077     else
 1078     {
 1079       cupsFilePuts(temp, "# Show general information in error_log.\n");
 1080       cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
 1081     }
 1082   }
 1083 
 1084   if (!wrote_port_listen &&
 1085       (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
 1086   {
 1087     if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
 1088     {
 1089       cupsFilePuts(temp, "# Allow remote access\n");
 1090       cupsFilePrintf(temp, "Port %d\n", ippPort());
 1091     }
 1092     else
 1093     {
 1094       cupsFilePuts(temp,
 1095                    "# Only listen for connections from the local machine.\n");
 1096       cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort());
 1097     }
 1098 
 1099 #ifdef CUPS_DEFAULT_DOMAINSOCKET
 1100     if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0))
 1101       cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
 1102 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
 1103   }
 1104 
 1105   if (!wrote_root_location &&
 1106       (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
 1107   {
 1108     if (remote_admin > 0 && share_printers > 0)
 1109       cupsFilePuts(temp,
 1110                    "# Allow shared printing and remote administration...\n");
 1111     else if (remote_admin > 0)
 1112       cupsFilePuts(temp, "# Allow remote administration...\n");
 1113     else if (share_printers > 0)
 1114       cupsFilePuts(temp, "# Allow shared printing...\n");
 1115     else if (remote_any > 0)
 1116       cupsFilePuts(temp, "# Allow remote access...\n");
 1117     else
 1118       cupsFilePuts(temp, "# Restrict access to the server...\n");
 1119 
 1120     cupsFilePuts(temp, "<Location />\n"
 1121                        "  Order allow,deny\n");
 1122 
 1123     if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
 1124       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
 1125 
 1126     cupsFilePuts(temp, "</Location>\n");
 1127   }
 1128 
 1129   if (!wrote_admin_location && remote_admin >= 0)
 1130   {
 1131     if (remote_admin)
 1132       cupsFilePuts(temp, "# Allow remote administration...\n");
 1133     else
 1134       cupsFilePuts(temp, "# Restrict access to the admin pages...\n");
 1135 
 1136     cupsFilePuts(temp, "<Location /admin>\n"
 1137                        "  Order allow,deny\n");
 1138 
 1139     if (remote_admin)
 1140       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
 1141 
 1142     cupsFilePuts(temp, "</Location>\n");
 1143   }
 1144 
 1145   if (!wrote_conf_location && remote_admin >= 0)
 1146   {
 1147     if (remote_admin)
 1148       cupsFilePuts(temp,
 1149                    "# Allow remote access to the configuration files...\n");
 1150     else
 1151       cupsFilePuts(temp, "# Restrict access to the configuration files...\n");
 1152 
 1153     cupsFilePuts(temp, "<Location /admin/conf>\n"
 1154                        "  AuthType Default\n"
 1155                        "  Require user @SYSTEM\n"
 1156                        "  Order allow,deny\n");
 1157 
 1158     if (remote_admin)
 1159       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
 1160 
 1161     cupsFilePuts(temp, "</Location>\n");
 1162   }
 1163 
 1164   if (!wrote_log_location && remote_admin >= 0)
 1165   {
 1166     if (remote_admin)
 1167       cupsFilePuts(temp,
 1168                    "# Allow remote access to the log files...\n");
 1169     else
 1170       cupsFilePuts(temp, "# Restrict access to the log files...\n");
 1171 
 1172     cupsFilePuts(temp, "<Location /admin/log>\n"
 1173                        "  AuthType Default\n"
 1174                        "  Require user @SYSTEM\n"
 1175                        "  Order allow,deny\n");
 1176 
 1177     if (remote_admin)
 1178       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
 1179 
 1180     cupsFilePuts(temp, "</Location>\n");
 1181   }
 1182 
 1183   if (!wrote_policy && user_cancel_any >= 0)
 1184   {
 1185     cupsFilePuts(temp, "<Policy default>\n"
 1186                        "  # Job-related operations must be done by the owner "
 1187                "or an administrator...\n"
 1188                        "  <Limit Send-Document Send-URI Hold-Job Release-Job "
 1189                "Restart-Job Purge-Jobs Set-Job-Attributes "
 1190                "Create-Job-Subscription Renew-Subscription "
 1191                "Cancel-Subscription Get-Notifications Reprocess-Job "
 1192                "Cancel-Current-Job Suspend-Current-Job Resume-Job "
 1193                "CUPS-Move-Job>\n"
 1194                        "    Require user @OWNER @SYSTEM\n"
 1195                        "    Order deny,allow\n"
 1196                        "  </Limit>\n"
 1197                        "  # All administration operations require an "
 1198                "administrator to authenticate...\n"
 1199                "  <Limit Pause-Printer Resume-Printer "
 1200                        "Set-Printer-Attributes Enable-Printer "
 1201                "Disable-Printer Pause-Printer-After-Current-Job "
 1202                "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer "
 1203                "Activate-Printer Restart-Printer Shutdown-Printer "
 1204                "Startup-Printer Promote-Job Schedule-Job-After "
 1205                "CUPS-Add-Printer CUPS-Delete-Printer "
 1206                "CUPS-Add-Class CUPS-Delete-Class "
 1207                "CUPS-Accept-Jobs CUPS-Reject-Jobs "
 1208                "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
 1209                        "    AuthType Default\n"
 1210                "    Require user @SYSTEM\n"
 1211                        "    Order deny,allow\n"
 1212                        "</Limit>\n");
 1213 
 1214     if (!user_cancel_any)
 1215       cupsFilePuts(temp, "  # Only the owner or an administrator can cancel "
 1216                          "a job...\n"
 1217                      "  <Limit Cancel-Job>\n"
 1218                      "    Order deny,allow\n"
 1219                      "    Require user @OWNER "
 1220              CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
 1221              "  </Limit>\n");
 1222 
 1223     cupsFilePuts(temp, "  <Limit All>\n"
 1224                        "  Order deny,allow\n"
 1225                        "  </Limit>\n"
 1226                "</Policy>\n");
 1227   }
 1228 
 1229   for (i = num_settings, setting = settings; i > 0; i --, setting ++)
 1230     if (setting->name[0] != '_' &&
 1231         _cups_strcasecmp(setting->name, "Listen") &&
 1232     _cups_strcasecmp(setting->name, "Port") &&
 1233         !cupsGetOption(setting->name, cupsd_num_settings, cupsd_settings))
 1234     {
 1235      /*
 1236       * Add this directive to the list of directives we have written...
 1237       */
 1238 
 1239       cupsd_num_settings = cupsAddOption(setting->name, setting->value,
 1240                                          cupsd_num_settings, &cupsd_settings);
 1241 
 1242      /*
 1243       * Write the new value, without indentation since we only support
 1244       * setting root directives, not in sections...
 1245       */
 1246 
 1247       cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value);
 1248     }
 1249 
 1250   cupsFileClose(cupsd);
 1251   cupsFileClose(temp);
 1252 
 1253  /*
 1254   * Upload the configuration file to the server...
 1255   */
 1256 
 1257   status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
 1258 
 1259   if (status == HTTP_STATUS_CREATED)
 1260   {
 1261    /*
 1262     * Updated OK, add the basic settings...
 1263     */
 1264 
 1265     if (debug_logging >= 0)
 1266       cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
 1267                                      debug_logging ? "1" : "0",
 1268                      cupsd_num_settings, &cupsd_settings);
 1269     else
 1270       cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
 1271                                      old_debug_logging ? "1" : "0",
 1272                      cupsd_num_settings, &cupsd_settings);
 1273 
 1274     if (remote_admin >= 0)
 1275       cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
 1276                                      remote_admin ? "1" : "0",
 1277                      cupsd_num_settings, &cupsd_settings);
 1278     else
 1279       cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
 1280                                      old_remote_admin ? "1" : "0",
 1281                      cupsd_num_settings, &cupsd_settings);
 1282 
 1283     if (remote_any >= 0)
 1284       cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
 1285                      remote_any ? "1" : "0",
 1286                      cupsd_num_settings, &cupsd_settings);
 1287     else
 1288       cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
 1289                      old_remote_any ? "1" : "0",
 1290                      cupsd_num_settings, &cupsd_settings);
 1291 
 1292     if (share_printers >= 0)
 1293       cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
 1294                                      share_printers ? "1" : "0",
 1295                      cupsd_num_settings, &cupsd_settings);
 1296     else
 1297       cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
 1298                                      old_share_printers ? "1" : "0",
 1299                      cupsd_num_settings, &cupsd_settings);
 1300 
 1301     if (user_cancel_any >= 0)
 1302       cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
 1303                                      user_cancel_any ? "1" : "0",
 1304                      cupsd_num_settings, &cupsd_settings);
 1305     else
 1306       cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
 1307                                      old_user_cancel_any ? "1" : "0",
 1308                      cupsd_num_settings, &cupsd_settings);
 1309 
 1310    /*
 1311     * Save the new values...
 1312     */
 1313 
 1314     invalidate_cupsd_cache(cg);
 1315 
 1316     cg->cupsd_num_settings = cupsd_num_settings;
 1317     cg->cupsd_settings     = cupsd_settings;
 1318     cg->cupsd_update       = time(NULL);
 1319 
 1320     httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname));
 1321   }
 1322   else
 1323     cupsFreeOptions(cupsd_num_settings, cupsd_settings);
 1324 
 1325  /*
 1326   * Remote our temp files and return...
 1327   */
 1328 
 1329   if (remote)
 1330     unlink(cupsdconf);
 1331 
 1332   unlink(tempfile);
 1333 
 1334   return (status == HTTP_STATUS_CREATED);
 1335 }
 1336 
 1337 
 1338 /*
 1339  * 'get_cupsd_conf()' - Get the current cupsd.conf file.
 1340  */
 1341 
 1342 static http_status_t            /* O - Status of request */
 1343 get_cupsd_conf(
 1344     http_t          *http,      /* I - Connection to server */
 1345     _cups_globals_t *cg,        /* I - Global data */
 1346     time_t          last_update,    /* I - Last update time for file */
 1347     char            *name,      /* I - Filename buffer */
 1348     size_t          namesize,       /* I - Size of filename buffer */
 1349     int             *remote)        /* O - Remote file? */
 1350 {
 1351   int       fd;         /* Temporary file descriptor */
 1352 #ifndef _WIN32
 1353   struct stat   info;           /* cupsd.conf file information */
 1354 #endif /* _WIN32 */
 1355   http_status_t status;         /* Status of getting cupsd.conf */
 1356   char      host[HTTP_MAX_HOST];    /* Hostname for connection */
 1357 
 1358 
 1359  /*
 1360   * See if we already have the data we need...
 1361   */
 1362 
 1363   httpGetHostname(http, host, sizeof(host));
 1364 
 1365   if (_cups_strcasecmp(cg->cupsd_hostname, host))
 1366     invalidate_cupsd_cache(cg);
 1367 
 1368   snprintf(name, namesize, "%s/cupsd.conf", cg->cups_serverroot);
 1369   *remote = 0;
 1370 
 1371 #ifndef _WIN32
 1372   if (!_cups_strcasecmp(host, "localhost") && !access(name, R_OK))
 1373   {
 1374    /*
 1375     * Read the local file rather than using HTTP...
 1376     */
 1377 
 1378     if (stat(name, &info))
 1379     {
 1380       char  message[1024];      /* Message string */
 1381 
 1382 
 1383       snprintf(message, sizeof(message),
 1384                _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
 1385                name, strerror(errno));
 1386       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0);
 1387 
 1388       *name = '\0';
 1389 
 1390       return (HTTP_STATUS_SERVER_ERROR);
 1391     }
 1392     else if (last_update && info.st_mtime <= last_update)
 1393       status = HTTP_STATUS_NOT_MODIFIED;
 1394     else
 1395       status = HTTP_STATUS_OK;
 1396   }
 1397   else
 1398 #endif /* !_WIN32 */
 1399   {
 1400    /*
 1401     * Read cupsd.conf via a HTTP GET request...
 1402     */
 1403 
 1404     if ((fd = cupsTempFd(name, (int)namesize)) < 0)
 1405     {
 1406       *name = '\0';
 1407 
 1408       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
 1409 
 1410       invalidate_cupsd_cache(cg);
 1411 
 1412       return (HTTP_STATUS_SERVER_ERROR);
 1413     }
 1414 
 1415     *remote = 1;
 1416 
 1417     httpClearFields(http);
 1418 
 1419     if (last_update)
 1420       httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE,
 1421                    httpGetDateString(last_update));
 1422 
 1423     status = cupsGetFd(http, "/admin/conf/cupsd.conf", fd);
 1424 
 1425     close(fd);
 1426 
 1427     if (status != HTTP_STATUS_OK)
 1428     {
 1429       unlink(name);
 1430       *name = '\0';
 1431     }
 1432   }
 1433 
 1434   return (status);
 1435 }
 1436 
 1437 
 1438 /*
 1439  * 'invalidate_cupsd_cache()' - Invalidate the cached cupsd.conf settings.
 1440  */
 1441 
 1442 static void
 1443 invalidate_cupsd_cache(
 1444     _cups_globals_t *cg)        /* I - Global data */
 1445 {
 1446   cupsFreeOptions(cg->cupsd_num_settings, cg->cupsd_settings);
 1447 
 1448   cg->cupsd_hostname[0]  = '\0';
 1449   cg->cupsd_update       = 0;
 1450   cg->cupsd_num_settings = 0;
 1451   cg->cupsd_settings     = NULL;
 1452 }