+ if (n < 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad negative permissions value for %s on line %d of "
+ "%s.", line, linenum, filename);
+ return (0);
+ }
+ else
+ {
+ *((mode_t *)var->ptr) = (mode_t)n;
+ }
+ }
+ break;
+
+ case CUPSD_VARTYPE_TIME :
+ if (!value)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Missing time interval value for %s on line %d of "
+ "%s.", line, linenum, filename);
+ return (0);
+ }
+ else if (!_cups_strncasecmp(line, "PreserveJob", 11) &&
+ (!_cups_strcasecmp(value, "true") ||
+ !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "enabled") ||
+ !_cups_strcasecmp(value, "yes")))
+ {
+ *((int *)var->ptr) = INT_MAX;
+ }
+ else if (!_cups_strcasecmp(value, "false") ||
+ !_cups_strcasecmp(value, "off") ||
+ !_cups_strcasecmp(value, "disabled") ||
+ !_cups_strcasecmp(value, "no"))
+ {
+ *((int *)var->ptr) = 0;
+ }
+ else if (!isdigit(*value & 255))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unknown time interval value for %s on line %d of "
+ "%s.", line, linenum, filename);
+ return (0);
+ }
+ else
+ {
+ double n; /* Number */
+ char *units; /* Units */
+
+ n = strtod(value, &units);
+
+ if (units && *units)
+ {
+ if (tolower(units[0] & 255) == 'w')
+ n *= 7 * 24 * 60 * 60;
+ else if (tolower(units[0] & 255) == 'd')
+ n *= 24 * 60 * 60;
+ else if (tolower(units[0] & 255) == 'h')
+ n *= 60 * 60;
+ else if (tolower(units[0] & 255) == 'm')
+ n *= 60;
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unknown time interval value for %s on line "
+ "%d of %s.", line, linenum, filename);
+ return (0);
+ }
+ }
+
+ if (n < 0.0 || n > INT_MAX)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad time value for %s on line %d of %s.",
+ line, linenum, filename);
+ return (0);
+ }
+ else
+ {
+ *((int *)var->ptr) = (int)n;
+ }
+ }
+ break;
+
+ case CUPSD_VARTYPE_BOOLEAN :
+ if (!value)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Missing boolean value for %s on line %d of %s.",
+ line, linenum, filename);
+ return (0);
+ }
+ else if (!_cups_strcasecmp(value, "true") ||
+ !_cups_strcasecmp(value, "on") ||
+ !_cups_strcasecmp(value, "enabled") ||
+ !_cups_strcasecmp(value, "yes") ||
+ atoi(value) != 0)
+ {
+ *((int *)var->ptr) = TRUE;
+ }
+ else if (!_cups_strcasecmp(value, "false") ||
+ !_cups_strcasecmp(value, "off") ||
+ !_cups_strcasecmp(value, "disabled") ||
+ !_cups_strcasecmp(value, "no") ||
+ !_cups_strcasecmp(value, "0"))
+ {
+ *((int *)var->ptr) = FALSE;
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unknown boolean value %s on line %d of %s.",
+ value, linenum, filename);
+ return (0);
+ }
+ break;
+
+ case CUPSD_VARTYPE_PATHNAME :
+ if (!value)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Missing pathname value for %s on line %d of %s.",
+ line, linenum, filename);
+ return (0);
+ }
+
+ if (value[0] == '/')
+ strlcpy(temp, value, sizeof(temp));
+ else
+ snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
+
+ if (access(temp, 0) && _cups_strcasecmp(value, "internal") && _cups_strcasecmp(line, "ServerKeychain"))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "File or directory for \"%s %s\" on line %d of %s "
+ "does not exist.", line, value, linenum, filename);
+ return (0);
+ }
+
+ cupsdSetString((char **)var->ptr, temp);
+ break;
+
+ case CUPSD_VARTYPE_STRING :
+ cupsdSetString((char **)var->ptr, value);
+ break;
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'read_cupsd_conf()' - Read the cupsd.conf configuration file.
+ */
+
+static int /* O - 1 on success, 0 on failure */
+read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
+{
+ int linenum; /* Current line number */
+ char line[HTTP_MAX_BUFFER],
+ /* Line from file */
+ temp[HTTP_MAX_BUFFER],
+ /* Temporary buffer for value */
+ *value, /* Pointer to value */
+ *valueptr; /* Pointer into value */
+ int valuelen; /* Length of value */
+ http_addrlist_t *addrlist, /* Address list */
+ *addr; /* Current address */
+ cups_file_t *incfile; /* Include file */
+ char incname[1024]; /* Include filename */
+
+
+ /*
+ * Loop through each line in the file...
+ */
+
+ linenum = 0;
+
+ while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
+ {
+ /*
+ * Decode the directive...
+ */
+
+ if (!_cups_strcasecmp(line, "Include") && value)
+ {
+ /*
+ * Include filename
+ */
+
+ if (value[0] == '/')
+ strlcpy(incname, value, sizeof(incname));
+ else
+ snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
+
+ if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to include config file \"%s\" - %s",
+ incname, strerror(errno));
+ else
+ {
+ read_cupsd_conf(incfile);
+ cupsFileClose(incfile);
+ }
+ }
+ else if (!_cups_strcasecmp(line, "<Location") && value)
+ {
+ /*
+ * <Location path>
+ */
+
+ linenum = read_location(fp, value, linenum);
+ if (linenum == 0)
+ return (0);
+ }
+ else if (!_cups_strcasecmp(line, "<Policy") && value)
+ {
+ /*
+ * <Policy name>
+ */
+
+ linenum = read_policy(fp, value, linenum);
+ if (linenum == 0)
+ return (0);
+ }
+ else if (!_cups_strcasecmp(line, "FaxRetryInterval") && value)
+ {
+ JobRetryInterval = atoi(value);
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "FaxRetryInterval is deprecated; use "
+ "JobRetryInterval on line %d of %s.", linenum, ConfigurationFile);
+ }
+ else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value)
+ {
+ JobRetryLimit = atoi(value);
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "FaxRetryLimit is deprecated; use "
+ "JobRetryLimit on line %d of %s.", linenum, ConfigurationFile);
+ }
+#ifdef HAVE_SSL
+ else if (!_cups_strcasecmp(line, "SSLOptions"))
+ {
+ /*
+ * SSLOptions [AllowRC4] [AllowSSL3] [None]
+ */
+
+ int options = 0; /* SSL/TLS options */
+
+ if (value)
+ {
+ char *start, /* Start of option */
+ *end; /* End of option */
+
+ for (start = value; *start; start = end)
+ {
+ /*
+ * Find end of keyword...
+ */
+
+ end = start;
+ while (*end && !_cups_isspace(*end))
+ end ++;
+
+ if (*end)
+ *end++ = '\0';
+
+ /*
+ * Compare...
+ */
+
+ if (!_cups_strcasecmp(start, "AllowRC4"))
+ options |= _HTTP_TLS_ALLOW_RC4;
+ else if (!_cups_strcasecmp(start, "AllowSSL3"))
+ options |= _HTTP_TLS_ALLOW_SSL3;
+ else if (!_cups_strcasecmp(start, "None"))
+ options = 0;
+ else if (_cups_strcasecmp(start, "NoEmptyFragments"))
+ cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum);
+ }
+ }
+
+ _httpTLSSetOptions(options);
+ }
+#endif /* HAVE_SSL */
+ else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")
+#ifdef HAVE_SSL
+ || !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen")
+#endif /* HAVE_SSL */
+ ) && value)
+ {
+ /*
+ * Add listening address(es) to the list...
+ */
+
+ cupsd_listener_t *lis; /* New listeners array */
+
+
+ /*
+ * Get the address list...
+ */