int /* O - 0 on success, -1 on error */ helpSaveIndex(help_index_t *hi, /* I - Index */ const char *hifile) /* I - Index filename */ { cups_file_t *fp; /* Index file */ help_node_t *node; /* Current node */ help_word_t *word; /* Current word */ DEBUG_printf(("helpSaveIndex(hi=%p, hifile=\"%s\")", hi, hifile)); /* * Try creating a new index file... */ if ((fp = cupsFileOpen(hifile, "w9")) == NULL) return (-1); /* * Lock the file while we write it... */ cupsFileLock(fp, 1); cupsFilePuts(fp, "HELPV2\n"); for (node = (help_node_t *)cupsArrayFirst(hi->nodes); node; node = (help_node_t *)cupsArrayNext(hi->nodes)) { /* * Write the current node with/without the anchor... */ if (node->anchor) { if (cupsFilePrintf(fp, "%s#%s " CUPS_LLFMT " " CUPS_LLFMT " \"%s\"\n", node->filename, node->anchor, CUPS_LLCAST node->offset, CUPS_LLCAST node->length, node->text) < 0) break; } else { if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n", node->filename, (int)node->mtime, CUPS_LLCAST node->offset, CUPS_LLCAST node->length, node->section ? node->section : "", node->text) < 0) break; } /* * Then write the words associated with the node... */ for (word = (help_word_t *)cupsArrayFirst(node->words); word; word = (help_word_t *)cupsArrayNext(node->words)) if (cupsFilePrintf(fp, " %d %s\n", word->count, word->text) < 0) break; } cupsFileFlush(fp); if (cupsFileClose(fp) < 0) return (-1); else if (node) return (-1); else return (0); }
int /* O - 1 on success, 0 on failure */ cupsAdminSetServerSettings( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int num_settings, /* I - Number of settings */ cups_option_t *settings) /* I - Settings */ { int i; /* Looping var */ http_status_t status; /* GET/PUT status */ const char *server_port_env; /* SERVER_PORT env var */ int server_port; /* IPP port for server */ cups_file_t *cupsd; /* cupsd.conf file */ char cupsdconf[1024]; /* cupsd.conf filename */ int remote; /* Remote cupsd.conf file? */ char tempfile[1024]; /* Temporary new cupsd.conf */ cups_file_t *temp; /* Temporary file */ char line[1024], /* Line from cupsd.conf file */ *value; /* Value on line */ int linenum, /* Line number in file */ in_location, /* In a location section? */ in_policy, /* In a policy section? */ in_default_policy, /* In the default policy section? */ in_cancel_job, /* In a cancel-job section? */ in_admin_location, /* In the /admin location? */ in_conf_location, /* In the /admin/conf location? */ in_log_location, /* In the /admin/log location? */ in_root_location; /* In the / location? */ const char *val; /* Setting value */ int share_printers, /* Share local printers */ remote_admin, /* Remote administration allowed? */ remote_any, /* Remote access from anywhere? */ user_cancel_any, /* Cancel-job policy set? */ debug_logging; /* LogLevel debug set? */ int wrote_port_listen, /* Wrote the port/listen lines? */ wrote_browsing, /* Wrote the browsing lines? */ wrote_policy, /* Wrote the policy? */ wrote_loglevel, /* Wrote the LogLevel line? */ wrote_admin_location, /* Wrote the /admin location? */ wrote_conf_location, /* Wrote the /admin/conf location? */ wrote_log_location, /* Wrote the /admin/log location? */ wrote_root_location; /* Wrote the / location? */ int indent; /* Indentation */ int cupsd_num_settings; /* New number of settings */ int old_share_printers, /* Share local printers */ old_remote_admin, /* Remote administration allowed? */ old_remote_any, /* Remote access from anywhere? */ old_user_cancel_any, /* Cancel-job policy set? */ old_debug_logging; /* LogLevel debug set? */ cups_option_t *cupsd_settings, /* New settings */ *setting; /* Current setting */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!http) http = _cupsConnect(); if (!http || !num_settings || !settings) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (0); } /* * Get the cupsd.conf file... */ if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf), &remote) == HTTP_STATUS_OK) { if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); return (0); } } else return (0); /* * Get current settings... */ if (!cupsAdminGetServerSettings(http, &cupsd_num_settings, &cupsd_settings)) return (0); if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, cupsd_num_settings, cupsd_settings)) != NULL) old_debug_logging = atoi(val); else old_debug_logging = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d", old_debug_logging)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, cupsd_num_settings, cupsd_settings)) != NULL) old_remote_admin = atoi(val); else old_remote_admin = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d", old_remote_admin)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, cupsd_num_settings, cupsd_settings)) != NULL) old_remote_any = atoi(val); else old_remote_any = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d", old_remote_any)); if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings, cupsd_settings)) != NULL) old_share_printers = atoi(val); else old_share_printers = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d", old_share_printers)); if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, cupsd_num_settings, cupsd_settings)) != NULL) old_user_cancel_any = atoi(val); else old_user_cancel_any = 0; DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d", old_user_cancel_any)); cupsFreeOptions(cupsd_num_settings, cupsd_settings); /* * Get basic settings... */ if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings, settings)) != NULL) { debug_logging = atoi(val); if (debug_logging == old_debug_logging) { /* * No change to this setting... */ debug_logging = -1; } } else debug_logging = -1; DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d", debug_logging)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, settings)) != NULL) { remote_any = atoi(val); if (remote_any == old_remote_any) { /* * No change to this setting... */ remote_any = -1; } } else remote_any = -1; DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any)); if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings, settings)) != NULL) { remote_admin = atoi(val); if (remote_admin == old_remote_admin) { /* * No change to this setting... */ remote_admin = -1; } } else remote_admin = -1; DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d", remote_admin)); if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, settings)) != NULL) { share_printers = atoi(val); if (share_printers == old_share_printers) { /* * No change to this setting... */ share_printers = -1; } } else share_printers = -1; DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d", share_printers)); if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings, settings)) != NULL) { user_cancel_any = atoi(val); if (user_cancel_any == old_user_cancel_any) { /* * No change to this setting... */ user_cancel_any = -1; } } else user_cancel_any = -1; DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d", user_cancel_any)); /* * Create a temporary file for the new cupsd.conf file... */ if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) { cupsFileClose(cupsd); if (remote) unlink(cupsdconf); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0); return (0); } /* * Copy the old file to the new, making changes along the way... */ cupsd_num_settings = 0; in_admin_location = 0; in_cancel_job = 0; in_conf_location = 0; in_default_policy = 0; in_location = 0; in_log_location = 0; in_policy = 0; in_root_location = 0; linenum = 0; wrote_admin_location = 0; wrote_browsing = 0; wrote_conf_location = 0; wrote_log_location = 0; wrote_loglevel = 0; wrote_policy = 0; wrote_port_listen = 0; wrote_root_location = 0; indent = 0; if ((server_port_env = getenv("SERVER_PORT")) != NULL) { if ((server_port = atoi(server_port_env)) <= 0) server_port = ippPort(); } else server_port = ippPort(); if (server_port <= 0) server_port = IPP_PORT; while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) { if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (!wrote_port_listen) { wrote_port_listen = 1; if (remote_admin > 0 || remote_any > 0 || share_printers > 0) { cupsFilePuts(temp, "# Allow remote access\n"); cupsFilePrintf(temp, "Port %d\n", server_port); } else { cupsFilePuts(temp, "# Only listen for connections from the local " "machine.\n"); cupsFilePrintf(temp, "Listen localhost:%d\n", server_port); } #ifdef CUPS_DEFAULT_DOMAINSOCKET if ((!value || strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)) && !access(CUPS_DEFAULT_DOMAINSOCKET, 0)) cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); #endif /* CUPS_DEFAULT_DOMAINSOCKET */ } else if (value && value[0] == '/' #ifdef CUPS_DEFAULT_DOMAINSOCKET && strcmp(CUPS_DEFAULT_DOMAINSOCKET, value) #endif /* CUPS_DEFAULT_DOMAINSOCKET */ ) cupsFilePrintf(temp, "Listen %s\n", value); } else if ((!_cups_strcasecmp(line, "Browsing") || !_cups_strcasecmp(line, "BrowseLocalProtocols")) && share_printers >= 0) { if (!wrote_browsing) { int new_share_printers = (share_printers > 0 || (share_printers == -1 && old_share_printers > 0)); wrote_browsing = 1; if (new_share_printers) { const char *localp = cupsGetOption("BrowseLocalProtocols", num_settings, settings); if (!localp || !localp[0]) localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings, cupsd_settings); cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); if (!localp) localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp); cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp, cupsd_num_settings, &cupsd_settings); } else { cupsFilePuts(temp, "# Disable printer sharing.\n"); cupsFilePuts(temp, "Browsing Off\n"); } } } else if (!_cups_strcasecmp(line, "LogLevel") && debug_logging >= 0) { wrote_loglevel = 1; if (debug_logging) { cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n"); cupsFilePuts(temp, "LogLevel debug\n"); } else { cupsFilePuts(temp, "# Show general information in error_log.\n"); cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); } } else if (!_cups_strcasecmp(line, "<Policy")) { in_default_policy = !_cups_strcasecmp(value, "default"); in_policy = 1; cupsFilePrintf(temp, "%s %s>\n", line, value); indent += 2; } else if (!_cups_strcasecmp(line, "</Policy>")) { indent -= 2; if (!wrote_policy && in_default_policy) { wrote_policy = 1; if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can " "cancel a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); } in_policy = 0; in_default_policy = 0; cupsFilePuts(temp, "</Policy>\n"); } else if (!_cups_strcasecmp(line, "<Location")) { in_location = 1; indent += 2; if (!strcmp(value, "/admin")) in_admin_location = 1; else if (!strcmp(value, "/admin/conf")) in_conf_location = 1; else if (!strcmp(value, "/admin/log")) in_log_location = 1; else if (!strcmp(value, "/")) in_root_location = 1; cupsFilePrintf(temp, "%s %s>\n", line, value); } else if (!_cups_strcasecmp(line, "</Location>")) { in_location = 0; indent -= 2; if (in_admin_location && remote_admin >= 0) { wrote_admin_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote administration...\n"); else if (remote_admin == 0) cupsFilePuts(temp, " # Restrict access to the admin pages...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_conf_location && remote_admin >= 0) { wrote_conf_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote access to the configuration " "files...\n"); else cupsFilePuts(temp, " # Restrict access to the configuration " "files...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_log_location && remote_admin >= 0) { wrote_log_location = 1; if (remote_admin) cupsFilePuts(temp, " # Allow remote access to the log " "files...\n"); else cupsFilePuts(temp, " # Restrict access to the log " "files...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } else if (in_root_location && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { wrote_root_location = 1; if (remote_admin > 0 && share_printers > 0) cupsFilePuts(temp, " # Allow shared printing and remote " "administration...\n"); else if (remote_admin > 0) cupsFilePuts(temp, " # Allow remote administration...\n"); else if (share_printers > 0) cupsFilePuts(temp, " # Allow shared printing...\n"); else if (remote_any > 0) cupsFilePuts(temp, " # Allow remote access...\n"); else cupsFilePuts(temp, " # Restrict access to the server...\n"); cupsFilePuts(temp, " Order allow,deny\n"); if (remote_admin > 0 || remote_any > 0 || share_printers > 0) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); } in_admin_location = 0; in_conf_location = 0; in_log_location = 0; in_root_location = 0; cupsFilePuts(temp, "</Location>\n"); } else if (!_cups_strcasecmp(line, "<Limit")) { if (in_default_policy) { /* * See if the policy limit is for the Cancel-Job operation... */ char *valptr; /* Pointer into value */ if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) { /* * Don't write anything for this limit section... */ in_cancel_job = 2; } else { cupsFilePrintf(temp, "%*s%s", indent, "", line); while (*value) { for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); if (*valptr) *valptr++ = '\0'; if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0) { /* * Write everything except for this definition... */ in_cancel_job = 1; } else cupsFilePrintf(temp, " %s", value); for (value = valptr; _cups_isspace(*value); value ++); } cupsFilePuts(temp, ">\n"); } } else cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); indent += 2; } else if (!_cups_strcasecmp(line, "</Limit>") && in_cancel_job) { indent -= 2; if (in_cancel_job == 1) cupsFilePuts(temp, " </Limit>\n"); wrote_policy = 1; if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can cancel " "a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); in_cancel_job = 0; } else if ((((in_admin_location || in_conf_location || in_root_location) && (remote_admin >= 0 || remote_any >= 0)) || (in_root_location && share_printers >= 0)) && (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny") || !_cups_strcasecmp(line, "Order"))) continue; else if (in_cancel_job == 2) continue; else if (line[0] == '<') { if (value) { cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value); indent += 2; } else { if (line[1] == '/') indent -= 2; cupsFilePrintf(temp, "%*s%s\n", indent, "", line); } } else if (!in_policy && !in_location && (val = cupsGetOption(line, num_settings, settings)) != NULL) { /* * Replace this directive's value with the new one... */ cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings, &cupsd_settings); /* * Write the new value in its place, without indentation since we * only support setting root directives, not in sections... */ cupsFilePrintf(temp, "%s %s\n", line, val); } else if (value) { if (!in_policy && !in_location) { /* * Record the non-policy, non-location directives that we find * in the server settings, since we cache this info and record it * in cupsAdminGetServerSettings()... */ cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings, &cupsd_settings); } cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value); } else cupsFilePrintf(temp, "%*s%s\n", indent, "", line); } /* * Write any missing info... */ if (!wrote_browsing && share_printers >= 0) { if (share_printers > 0) { cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); } else { cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n"); cupsFilePuts(temp, "Browsing Off\n"); } } if (!wrote_loglevel && debug_logging >= 0) { if (debug_logging) { cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n"); cupsFilePuts(temp, "LogLevel debug\n"); } else { cupsFilePuts(temp, "# Show general information in error_log.\n"); cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n"); } } if (!wrote_port_listen && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (remote_admin > 0 || remote_any > 0 || share_printers > 0) { cupsFilePuts(temp, "# Allow remote access\n"); cupsFilePrintf(temp, "Port %d\n", ippPort()); } else { cupsFilePuts(temp, "# Only listen for connections from the local machine.\n"); cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort()); } #ifdef CUPS_DEFAULT_DOMAINSOCKET if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0)) cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n"); #endif /* CUPS_DEFAULT_DOMAINSOCKET */ } if (!wrote_root_location && (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0)) { if (remote_admin > 0 && share_printers > 0) cupsFilePuts(temp, "# Allow shared printing and remote administration...\n"); else if (remote_admin > 0) cupsFilePuts(temp, "# Allow remote administration...\n"); else if (share_printers > 0) cupsFilePuts(temp, "# Allow shared printing...\n"); else if (remote_any > 0) cupsFilePuts(temp, "# Allow remote access...\n"); else cupsFilePuts(temp, "# Restrict access to the server...\n"); cupsFilePuts(temp, "<Location />\n" " Order allow,deny\n"); if (remote_admin > 0 || remote_any > 0 || share_printers > 0) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_admin_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote administration...\n"); else cupsFilePuts(temp, "# Restrict access to the admin pages...\n"); cupsFilePuts(temp, "<Location /admin>\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_conf_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote access to the configuration files...\n"); else cupsFilePuts(temp, "# Restrict access to the configuration files...\n"); cupsFilePuts(temp, "<Location /admin/conf>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_log_location && remote_admin >= 0) { if (remote_admin) cupsFilePuts(temp, "# Allow remote access to the log files...\n"); else cupsFilePuts(temp, "# Restrict access to the log files...\n"); cupsFilePuts(temp, "<Location /admin/log>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order allow,deny\n"); if (remote_admin) cupsFilePrintf(temp, " Allow %s\n", remote_any > 0 ? "all" : "@LOCAL"); cupsFilePuts(temp, "</Location>\n"); } if (!wrote_policy && user_cancel_any >= 0) { cupsFilePuts(temp, "<Policy default>\n" " # Job-related operations must be done by the owner " "or an administrator...\n" " <Limit Send-Document Send-URI Hold-Job Release-Job " "Restart-Job Purge-Jobs Set-Job-Attributes " "Create-Job-Subscription Renew-Subscription " "Cancel-Subscription Get-Notifications Reprocess-Job " "Cancel-Current-Job Suspend-Current-Job Resume-Job " "CUPS-Move-Job>\n" " Require user @OWNER @SYSTEM\n" " Order deny,allow\n" " </Limit>\n" " # All administration operations require an " "administrator to authenticate...\n" " <Limit Pause-Printer Resume-Printer " "Set-Printer-Attributes Enable-Printer " "Disable-Printer Pause-Printer-After-Current-Job " "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer " "Activate-Printer Restart-Printer Shutdown-Printer " "Startup-Printer Promote-Job Schedule-Job-After " "CUPS-Add-Printer CUPS-Delete-Printer " "CUPS-Add-Class CUPS-Delete-Class " "CUPS-Accept-Jobs CUPS-Reject-Jobs " "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n" " AuthType Default\n" " Require user @SYSTEM\n" " Order deny,allow\n" "</Limit>\n"); if (!user_cancel_any) cupsFilePuts(temp, " # Only the owner or an administrator can cancel " "a job...\n" " <Limit Cancel-Job>\n" " Order deny,allow\n" " Require user @OWNER " CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n" " </Limit>\n"); cupsFilePuts(temp, " <Limit All>\n" " Order deny,allow\n" " </Limit>\n" "</Policy>\n"); } for (i = num_settings, setting = settings; i > 0; i --, setting ++) if (setting->name[0] != '_' && _cups_strcasecmp(setting->name, "Listen") && _cups_strcasecmp(setting->name, "Port") && !cupsGetOption(setting->name, cupsd_num_settings, cupsd_settings)) { /* * Add this directive to the list of directives we have written... */ cupsd_num_settings = cupsAddOption(setting->name, setting->value, cupsd_num_settings, &cupsd_settings); /* * Write the new value, without indentation since we only support * setting root directives, not in sections... */ cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value); } cupsFileClose(cupsd); cupsFileClose(temp); /* * Upload the configuration file to the server... */ status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile); if (status == HTTP_STATUS_CREATED) { /* * Updated OK, add the basic settings... */ if (debug_logging >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, debug_logging ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, old_debug_logging ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (remote_admin >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, remote_admin ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, old_remote_admin ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (remote_any >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, remote_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, old_remote_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (share_printers >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, share_printers ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, old_share_printers ? "1" : "0", cupsd_num_settings, &cupsd_settings); if (user_cancel_any >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, user_cancel_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); else cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, old_user_cancel_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); /* * Save the new values... */ invalidate_cupsd_cache(cg); cg->cupsd_num_settings = cupsd_num_settings; cg->cupsd_settings = cupsd_settings; cg->cupsd_update = time(NULL); httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); } else cupsFreeOptions(cupsd_num_settings, cupsd_settings); /* * Remote our temp files and return... */ if (remote) unlink(cupsdconf); unlink(tempfile); return (status == HTTP_STATUS_CREATED); }
static void backend_init_supplies( int snmp_fd, /* I - SNMP socket */ http_addr_t *addr) /* I - Printer address */ { int i, /* Looping var */ type; /* Current marker type */ cups_file_t *cachefile; /* Cache file */ const char *cachedir; /* CUPS_CACHEDIR value */ char addrstr[1024], /* Address string */ cachefilename[1024], /* Cache filename */ description[CUPS_SNMP_MAX_STRING], /* Device description string */ value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 4 + 3)], /* Value string */ *ptr, /* Pointer into value string */ *name_ptr; /* Pointer into name string */ cups_snmp_t packet; /* SNMP response packet */ ppd_file_t *ppd; /* PPD file for this queue */ ppd_attr_t *ppdattr; /* cupsSNMPSupplies attribute */ static const char * const types[] = /* Supply types */ { "other", "unknown", "toner", "waste-toner", "ink", "ink-cartridge", "ink-ribbon", "waste-ink", "opc", "developer", "fuser-oil", "solid-wax", "ribbon-wax", "waste-wax", "fuser", "corona-wire", "fuser-oil-wick", "cleaner-unit", "fuser-cleaning-pad", "transfer-unit", "toner-cartridge", "fuser-oiler", "water", "waste-water", "glue-water-additive", "waste-paper", "binding-supply", "banding-supply", "stitching-wire", "shrink-wrap", "paper-wrap", "staples", "inserts", "covers" }; /* * Reset state information... */ current_addr = *addr; current_state = -1; num_supplies = -1; charset = -1; memset(supplies, 0, sizeof(supplies)); /* * See if we should be getting supply levels via SNMP... */ if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL || ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL && ppdattr->value && _cups_strcasecmp(ppdattr->value, "true"))) { ppdClose(ppd); return; } if ((ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL) { if (!_cups_strcasecmp(ppdattr->value, "capacity")) quirks |= CUPS_SNMP_CAPACITY; } ppdClose(ppd); /* * Get the device description... */ if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1, hrDeviceDescr)) return; if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) || packet.object_type != CUPS_ASN1_OCTET_STRING) { strlcpy(description, "Unknown", sizeof(description)); num_supplies = 0; } else strlcpy(description, (char *)packet.object_value.string.bytes, sizeof(description)); fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description); /* * See if we have already queried this device... */ httpAddrString(addr, addrstr, sizeof(addrstr)); if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL) cachedir = CUPS_CACHEDIR; snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir, addrstr); if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL) { /* * Yes, read the cache file: * * 3 num_supplies charset * device description * supply structures... */ if (cupsFileGets(cachefile, value, sizeof(value))) { if (sscanf(value, "3 %d%d", &num_supplies, &charset) == 2 && num_supplies <= CUPS_MAX_SUPPLIES && cupsFileGets(cachefile, value, sizeof(value))) { if (!strcmp(description, value)) cupsFileRead(cachefile, (char *)supplies, (size_t)num_supplies * sizeof(backend_supplies_t)); else { num_supplies = -1; charset = -1; } } else { num_supplies = -1; charset = -1; } } cupsFileClose(cachefile); } /* * If the cache information isn't correct, scan for supplies... */ if (charset < 0) { /* * Get the configured character set... */ int oid[CUPS_SNMP_MAX_OID]; /* OID for character set */ if (!_cupsSNMPWrite(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1, prtGeneralCurrentLocalization)) return; if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) || packet.object_type != CUPS_ASN1_INTEGER) { fprintf(stderr, "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n", packet.object_type, CUPS_ASN1_INTEGER); return; } fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n", packet.object_value.integer); _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID); oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer; if (!_cupsSNMPWrite(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1, oid)) return; if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) || packet.object_type != CUPS_ASN1_INTEGER) { fprintf(stderr, "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n", packet.object_type, CUPS_ASN1_INTEGER); return; } fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n", packet.object_value.integer); charset = packet.object_value.integer; } if (num_supplies < 0) { /* * Walk the printer configuration information... */ _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry, CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL); } /* * Save the cached information... */ if (num_supplies < 0) num_supplies = 0; if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL) { cupsFilePrintf(cachefile, "3 %d %d\n", num_supplies, charset); cupsFilePrintf(cachefile, "%s\n", description); if (num_supplies > 0) cupsFileWrite(cachefile, (char *)supplies, (size_t)num_supplies * sizeof(backend_supplies_t)); cupsFileClose(cachefile); } if (num_supplies <= 0) return; /* * Get the colors... */ for (i = 0; i < num_supplies; i ++) strlcpy(supplies[i].color, "none", sizeof(supplies[i].color)); _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), prtMarkerColorantValue, CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL); /* * Output the marker-colors attribute... */ for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr)) { if (i) *ptr++ = ','; strlcpy(ptr, supplies[i].color, sizeof(value) - (size_t)(ptr - value)); } fprintf(stderr, "ATTR: marker-colors=%s\n", value); /* * Output the marker-names attribute (the double quoting is necessary to deal * with embedded quotes and commas in the marker names...) */ for (i = 0, ptr = value; i < num_supplies; i ++) { if (i) *ptr++ = ','; *ptr++ = '\''; *ptr++ = '\"'; for (name_ptr = supplies[i].name; *name_ptr;) { if (*name_ptr == '\\' || *name_ptr == '\"' || *name_ptr == '\'') { *ptr++ = '\\'; *ptr++ = '\\'; *ptr++ = '\\'; } *ptr++ = *name_ptr++; } *ptr++ = '\"'; *ptr++ = '\''; } *ptr = '\0'; fprintf(stderr, "ATTR: marker-names=%s\n", value); /* * Output the marker-types attribute... */ for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr)) { if (i) *ptr++ = ','; type = supplies[i].type; if (type < CUPS_TC_other || type > CUPS_TC_covers) strlcpy(ptr, "unknown", sizeof(value) - (size_t)(ptr - value)); else strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (size_t)(ptr - value)); } fprintf(stderr, "ATTR: marker-types=%s\n", value); }
int /* O - Exit code */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ const char *pofile, /* .po filename */ *stringsfile; /* .strings filename */ cups_file_t *po, /* .po file */ *strings; /* .strings file */ char s[4096], /* String buffer */ *ptr, /* Pointer into buffer */ *temp, /* New string */ *msgid, /* msgid string */ *msgstr; /* msgstr string */ int length; /* Length of combined strings */ int use_msgid; /* Use msgid strings for msgstr? */ /* * Process command-line arguments... */ pofile = NULL; stringsfile = NULL; use_msgid = 0; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "-m")) use_msgid = 1; else if (argv[i][0] == '-') { puts("Usage: po2strings [-m] filename.po filename.strings"); return (1); } else if (!pofile) pofile = argv[i]; else if (!stringsfile) stringsfile = argv[i]; else { puts("Usage: po2strings [-m] filename.po filename.strings"); return (1); } } if (!pofile || !stringsfile) { puts("Usage: po2strings [-m] filename.po filename.strings"); return (1); } /* * Read strings from the .po file and write to the .strings file... */ if ((po = cupsFileOpen(pofile, "r")) == NULL) { perror(pofile); return (1); } if ((strings = cupsFileOpen(stringsfile, "w")) == NULL) { perror(stringsfile); cupsFileClose(po); return (1); } msgid = msgstr = NULL; while (cupsFileGets(po, s, sizeof(s)) != NULL) { if (s[0] == '#' && s[1] == '.') { /* * Copy comment string... */ if (msgid && msgstr) { /* * First output the last localization string... */ if (*msgid) cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid, (use_msgid || !*msgstr) ? msgid : msgstr); free(msgid); free(msgstr); msgid = msgstr = NULL; } cupsFilePrintf(strings, "//%s\n", s + 2); } else if (s[0] == '#' || !s[0]) { /* * Skip blank and file comment lines... */ continue; } else { /* * Strip the trailing quote... */ if ((ptr = strrchr(s, '\"')) == NULL) continue; *ptr = '\0'; /* * Find start of value... */ if ((ptr = strchr(s, '\"')) == NULL) continue; ptr ++; /* * Create or add to a message... */ if (!strncmp(s, "msgid", 5)) { /* * Output previous message as needed... */ if (msgid && msgstr) { if (*msgid) cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid, (use_msgid || !*msgstr) ? msgid : msgstr); } if (msgid) free(msgid); if (msgstr) free(msgstr); msgid = strdup(ptr); msgstr = NULL; } else if (s[0] == '\"' && (msgid || msgstr)) { /* * Append to current string... */ size_t ptrlen = strlen(ptr); /* Length of string */ length = (int)strlen(msgstr ? msgstr : msgid); if ((temp = realloc(msgstr ? msgstr : msgid, length + ptrlen + 1)) == NULL) { free(msgid); if (msgstr) free(msgstr); perror("Unable to allocate string"); return (1); } if (msgstr) { /* * Copy the new portion to the end of the msgstr string - safe * to use strcpy because the buffer is allocated to the correct * size... */ msgstr = temp; memcpy(msgstr + length, ptr, ptrlen + 1); } else { /* * Copy the new portion to the end of the msgid string - safe * to use strcpy because the buffer is allocated to the correct * size... */ msgid = temp; memcpy(msgid + length, ptr, ptrlen + 1); } } else if (!strncmp(s, "msgstr", 6) && msgid) { /* * Set the string... */ if (msgstr) free(msgstr); if ((msgstr = strdup(ptr)) == NULL) { free(msgid); perror("Unable to allocate msgstr"); return (1); } } } } if (msgid && msgstr) { if (*msgid) cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid, (use_msgid || !*msgstr) ? msgid : msgstr); } if (msgid) free(msgid); if (msgstr) free(msgstr); cupsFileClose(po); cupsFileClose(strings); return (0); }
void email_message(const char *to, /* I - Recipient of message */ const char *subject, /* I - Subject of message */ const char *text) /* I - Text of message */ { cups_file_t *fp; /* Pipe/socket to mail server */ const char *nl; /* Newline to use */ char response[1024]; /* SMTP response buffer */ /* * Connect to the mail server... */ if (mailtoSendmail[0]) { /* * Use the sendmail command... */ fp = pipe_sendmail(to); if (!fp) return; nl = "\n"; } else { /* * Use an SMTP server... */ char hostbuf[1024]; /* Local hostname */ if (strchr(mailtoSMTPServer, ':')) fp = cupsFileOpen(mailtoSMTPServer, "s"); else { char spec[1024]; /* Host:service spec */ snprintf(spec, sizeof(spec), "%s:smtp", mailtoSMTPServer); fp = cupsFileOpen(spec, "s"); } if (!fp) { fprintf(stderr, "ERROR: Unable to connect to SMTP server \"%s\"!\n", mailtoSMTPServer); return; } fprintf(stderr, "DEBUG: Connected to \"%s\"...\n", mailtoSMTPServer); cupsFilePrintf(fp, "HELO %s\r\n", httpGetHostname(NULL, hostbuf, sizeof(hostbuf))); fprintf(stderr, "DEBUG: >>> HELO %s\n", hostbuf); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePrintf(fp, "MAIL FROM:%s\r\n", mailtoFrom); fprintf(stderr, "DEBUG: >>> MAIL FROM:%s\n", mailtoFrom); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePrintf(fp, "RCPT TO:%s\r\n", to); fprintf(stderr, "DEBUG: >>> RCPT TO:%s\n", to); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFilePuts(fp, "DATA\r\n"); fputs("DEBUG: DATA\n", stderr); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); nl = "\r\n"; } /* * Send the message... */ cupsFilePrintf(fp, "Date: %s%s", httpGetDateString(time(NULL)), nl); cupsFilePrintf(fp, "From: %s%s", mailtoFrom, nl); cupsFilePrintf(fp, "Subject: %s %s%s", mailtoSubject, subject, nl); if (mailtoReplyTo[0]) { cupsFilePrintf(fp, "Sender: %s%s", mailtoReplyTo, nl); cupsFilePrintf(fp, "Reply-To: %s%s", mailtoReplyTo, nl); } cupsFilePrintf(fp, "To: %s%s", to, nl); if (mailtoCc[0]) cupsFilePrintf(fp, "Cc: %s%s", mailtoCc, nl); cupsFilePrintf(fp, "Content-Type: text/plain%s", nl); cupsFilePuts(fp, nl); cupsFilePrintf(fp, "%s%s", text, nl); cupsFilePrintf(fp, ".\n", nl); /* * Close the connection to the mail server... */ if (mailtoSendmail[0]) { /* * Close the pipe and wait for the sendmail command to finish... */ int status; /* Exit status */ cupsFileClose(fp); if (wait(&status)) status = errno << 8; /* * Report any non-zero status... */ if (status) { if (WIFEXITED(status)) fprintf(stderr, "ERROR: Sendmail command returned status %d!\n", WEXITSTATUS(status)); else fprintf(stderr, "ERROR: Sendmail command crashed on signal %d!\n", WTERMSIG(status)); } } else { /* * Finish up the SMTP submission and close the connection... */ if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); /* * Process SMTP errors here... */ smtp_error: cupsFilePuts(fp, "QUIT\r\n"); fputs("DEBUG: QUIT\n", stderr); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) goto smtp_error; fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFileClose(fp); fprintf(stderr, "DEBUG: Closed connection to \"%s\"...\n", mailtoSMTPServer); } }
void * /* O - Profile or NULL on error */ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ int allow_networking)/* I - Allow networking off machine? */ { #ifdef HAVE_SANDBOX_H cups_file_t *fp; /* File pointer */ char profile[1024], /* File containing the profile */ bin[1024], /* Quoted ServerBin */ cache[1024], /* Quoted CacheDir */ domain[1024], /* Domain socket, if any */ request[1024], /* Quoted RequestRoot */ root[1024], /* Quoted ServerRoot */ state[1024], /* Quoted StateDir */ temp[1024]; /* Quoted TempDir */ const char *nodebug; /* " (with no-log)" for no debug */ cupsd_listener_t *lis; /* Current listening socket */ if (!UseSandboxing || Sandboxing == CUPSD_SANDBOXING_OFF) { /* * Only use sandbox profiles as root... */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); } if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s", strerror(errno)); return (NULL); } fchown(cupsFileNumber(fp), RunUser, Group); fchmod(cupsFileNumber(fp), 0640); cupsd_requote(bin, ServerBin, sizeof(bin)); cupsd_requote(cache, CacheDir, sizeof(cache)); cupsd_requote(request, RequestRoot, sizeof(request)); cupsd_requote(root, ServerRoot, sizeof(root)); cupsd_requote(state, StateDir, sizeof(state)); cupsd_requote(temp, TempDir, sizeof(temp)); nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : ""; cupsFilePuts(fp, "(version 1)\n"); if (Sandboxing == CUPSD_SANDBOXING_STRICT) cupsFilePuts(fp, "(deny default)\n"); else cupsFilePuts(fp, "(allow default)\n"); if (LogLevel >= CUPSD_LOG_DEBUG) cupsFilePuts(fp, "(debug deny)\n"); cupsFilePuts(fp, "(import \"system.sb\")\n"); cupsFilePuts(fp, "(system-network)\n"); cupsFilePuts(fp, "(allow mach-per-user-lookup)\n"); cupsFilePuts(fp, "(allow ipc-posix-sem)\n"); cupsFilePuts(fp, "(allow ipc-posix-shm)\n"); cupsFilePuts(fp, "(allow ipc-sysv-shm)\n"); cupsFilePuts(fp, "(allow mach-lookup)\n"); if (!RunUser) cupsFilePrintf(fp, "(deny file-write* file-read-data file-read-metadata\n" " (regex" " #\"^/Users$\"" " #\"^/Users/\"" ")%s)\n", nodebug); cupsFilePrintf(fp, "(deny file-write*\n" " (regex" " #\"^%s$\"" /* ServerRoot */ " #\"^%s/\"" /* ServerRoot/... */ " #\"^/private/etc$\"" " #\"^/private/etc/\"" " #\"^/usr/local/etc$\"" " #\"^/usr/local/etc/\"" " #\"^/Library$\"" " #\"^/Library/\"" " #\"^/System$\"" " #\"^/System/\"" ")%s)\n", root, root, nodebug); /* Specifically allow applications to stat RequestRoot and some other system folders */ cupsFilePrintf(fp, "(allow file-read-metadata\n" " (regex" " #\"^/$\"" /* / */ " #\"^/usr$\"" /* /usr */ " #\"^/Library$\"" /* /Library */ " #\"^/Library/Printers$\"" /* /Library/Printers */ " #\"^%s$\"" /* RequestRoot */ "))\n", request); /* Read and write TempDir, CacheDir, and other common folders */ cupsFilePuts(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" " #\"^/private/var/db/\"" " #\"^/private/var/folders/\"" " #\"^/private/var/lib/\"" " #\"^/private/var/log/\"" " #\"^/private/var/mysql/\"" " #\"^/private/var/run/\"" " #\"^/private/var/spool/\"" " #\"^/Library/Application Support/\"" " #\"^/Library/Caches/\"" " #\"^/Library/Logs/\"" " #\"^/Library/Preferences/\"" " #\"^/Library/WebServer/\"" " #\"^/Users/Shared/\"" "))\n"); cupsFilePrintf(fp, "(deny file-write*\n" " (regex #\"^%s$\")%s)\n", request, nodebug); cupsFilePrintf(fp, "(deny file-write* file-read-data file-read-metadata\n" " (regex #\"^%s/\")%s)\n", request, nodebug); cupsFilePrintf(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" " #\"^%s$\"" /* TempDir */ " #\"^%s/\"" /* TempDir/... */ " #\"^%s$\"" /* CacheDir */ " #\"^%s/\"" /* CacheDir/... */ " #\"^%s$\"" /* StateDir */ " #\"^%s/\"" /* StateDir/... */ "))\n", temp, temp, cache, cache, state, state); /* Read common folders */ cupsFilePrintf(fp, "(allow file-read-data file-read-metadata\n" " (regex" " #\"^/AppleInternal$\"" " #\"^/AppleInternal/\"" " #\"^/bin$\"" /* /bin */ " #\"^/bin/\"" /* /bin/... */ " #\"^/private$\"" " #\"^/private/etc$\"" " #\"^/private/etc/\"" " #\"^/private/tmp$\"" " #\"^/private/tmp/\"" " #\"^/private/var$\"" " #\"^/private/var/db$\"" " #\"^/private/var/folders$\"" " #\"^/private/var/lib$\"" " #\"^/private/var/log$\"" " #\"^/private/var/mysql$\"" " #\"^/private/var/run$\"" " #\"^/private/var/spool$\"" " #\"^/private/var/tmp$\"" " #\"^/private/var/tmp/\"" " #\"^/usr/bin$\"" /* /usr/bin */ " #\"^/usr/bin/\"" /* /usr/bin/... */ " #\"^/usr/libexec/cups$\"" /* /usr/libexec/cups */ " #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */ " #\"^/usr/libexec/fax$\"" /* /usr/libexec/fax */ " #\"^/usr/libexec/fax/\"" /* /usr/libexec/fax/... */ " #\"^/usr/sbin$\"" /* /usr/sbin */ " #\"^/usr/sbin/\"" /* /usr/sbin/... */ " #\"^/Library$\"" /* /Library */ " #\"^/Library/\"" /* /Library/... */ " #\"^/System$\"" /* /System */ " #\"^/System/\"" /* /System/... */ " #\"^%s/Library$\"" /* RequestRoot/Library */ " #\"^%s/Library/\"" /* RequestRoot/Library/... */ " #\"^%s$\"" /* ServerBin */ " #\"^%s/\"" /* ServerBin/... */ " #\"^%s$\"" /* ServerRoot */ " #\"^%s/\"" /* ServerRoot/... */ "))\n", request, request, bin, bin, root, root); if (Sandboxing == CUPSD_SANDBOXING_RELAXED) { /* Limited write access to /Library/Printers/... */ cupsFilePuts(fp, "(allow file-write*\n" " (regex" " #\"^/Library/Printers/.*/\"" "))\n"); cupsFilePrintf(fp, "(deny file-write*\n" " (regex" " #\"^/Library/Printers/PPDs$\"" " #\"^/Library/Printers/PPDs/\"" " #\"^/Library/Printers/PPD Plugins$\"" " #\"^/Library/Printers/PPD Plugins/\"" ")%s)\n", nodebug); } /* Allow execution of child processes as long as the programs are not in a user directory */ cupsFilePuts(fp, "(allow process*)\n"); cupsFilePuts(fp, "(deny process-exec (regex #\"^/Users/\"))\n"); if (RunUser && getenv("CUPS_TESTROOT")) { /* Allow source directory access in "make test" environment */ char testroot[1024]; /* Root directory of test files */ cupsd_requote(testroot, getenv("CUPS_TESTROOT"), sizeof(testroot)); cupsFilePrintf(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" " #\"^%s$\"" /* CUPS_TESTROOT */ " #\"^%s/\"" /* CUPS_TESTROOT/... */ "))\n", testroot, testroot); cupsFilePrintf(fp, "(allow process-exec\n" " (regex" " #\"^%s/\"" /* CUPS_TESTROOT/... */ "))\n", testroot); cupsFilePrintf(fp, "(allow sysctl*)\n"); } if (job_id) { /* Allow job filters to read the current job files... */ cupsFilePrintf(fp, "(allow file-read-data file-read-metadata\n" " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n", request, job_id, job_id); } else { /* Allow email notifications from notifiers... */ cupsFilePuts(fp, "(allow process-exec\n" " (literal \"/usr/sbin/sendmail\")\n" " (with no-sandbox))\n"); } /* Allow access to Bluetooth, USB, and notify_post. */ cupsFilePuts(fp, "(allow iokit*)\n"); cupsFilePuts(fp, "(allow distributed-notification-post)\n"); /* Allow outbound networking to local services */ cupsFilePuts(fp, "(allow network-outbound" "\n (regex #\"^/private/var/run/\" #\"^/private/tmp/\" #\"^/private/var/tmp/\")"); for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { if (httpAddrFamily(&(lis->address)) == AF_LOCAL) { httpAddrString(&(lis->address), domain, sizeof(domain)); cupsFilePrintf(fp, "\n (literal \"%s\")", domain); } } if (allow_networking) { /* Allow TCP and UDP networking off the machine... */ cupsFilePuts(fp, "\n (remote tcp))\n"); cupsFilePuts(fp, "(allow network-bind)\n"); /* for LPD resvport */ cupsFilePuts(fp, "(allow network*\n" " (local udp \"*:*\")\n" " (remote udp \"*:*\"))\n"); /* Also allow access to device files... */ cupsFilePuts(fp, "(allow file-write* file-read-data file-read-metadata file-ioctl\n" " (regex #\"^/dev/\"))\n"); /* And allow kernel extensions to be loaded, e.g., SMB */ cupsFilePuts(fp, "(allow system-kext-load)\n"); } else { /* Only allow SNMP (UDP) and LPD (TCP) off the machine... */ cupsFilePuts(fp, ")\n"); cupsFilePuts(fp, "(allow network-outbound\n" " (remote udp \"*:161\")\n" " (remote tcp \"*:515\"))\n"); cupsFilePuts(fp, "(allow network-inbound\n" " (local udp \"localhost:*\"))\n"); } cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d,allow_networking=%d) = \"%s\"", job_id, allow_networking, profile); return ((void *)strdup(profile)); #else cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); #endif /* HAVE_SANDBOX_H */ }
static void update_smb(int onoff) /* I - 1 = turn on, 0 = turn off */ { if (!SMBConfigFile) return; if (!strncmp(SMBConfigFile, "samba:///", 9)) { /* * Enable/disable SMB via the specified smb.conf config file... */ char newfile[1024]; /* New smb.conf.N file */ cups_file_t *ofp, /* Original file pointer */ *nfp; /* New file pointer */ char line[1024]; /* Line from file */ int in_printers; /* In [printers] section? */ snprintf(newfile, sizeof(newfile), "%s.N", SMBConfigFile + 8); if ((ofp = cupsFileOpen(SMBConfigFile + 8, "r")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s", SMBConfigFile + 8, strerror(errno)); return; } if ((nfp = cupsFileOpen(newfile, "w")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s", newfile, strerror(errno)); cupsFileClose(ofp); return; } /* * Copy all of the lines from the smb.conf file... */ in_printers = 0; while (cupsFileGets(ofp, line, sizeof(line))) { if (in_printers && strstr(line, "printable =")) snprintf(line, sizeof(line), " printable = %s", onoff ? "yes" : "no"); cupsFilePrintf(nfp, "%s\n", line); if (line[0] == '[') in_printers = !strcmp(line, "[printers]"); } cupsFileClose(nfp); cupsFileClose(ofp); rename(newfile, SMBConfigFile + 8); } else cupsdLogMessage(CUPSD_LOG_INFO, "Unknown SMBConfigFile scheme!"); }
void * /* O - Profile or NULL on error */ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ { #ifdef HAVE_SANDBOX_H cups_file_t *fp; /* File pointer */ char profile[1024], /* File containing the profile */ cache[1024], /* Quoted CacheDir */ request[1024], /* Quoted RequestRoot */ root[1024], /* Quoted ServerRoot */ temp[1024]; /* Quoted TempDir */ const char *nodebug; /* " (with no-log)" for no debug */ if (!UseProfiles) { /* * Only use sandbox profiles as root... */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", job_id); return (NULL); } if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", job_id); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s", strerror(errno)); return (NULL); } fchown(cupsFileNumber(fp), RunUser, Group); fchmod(cupsFileNumber(fp), 0640); cupsd_requote(cache, CacheDir, sizeof(cache)); cupsd_requote(request, RequestRoot, sizeof(request)); cupsd_requote(root, ServerRoot, sizeof(root)); cupsd_requote(temp, TempDir, sizeof(temp)); nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : ""; cupsFilePuts(fp, "(version 1)\n"); cupsFilePuts(fp, "(allow default)\n"); cupsFilePrintf(fp, "(deny file-write* file-read-data file-read-metadata\n" " (regex" " #\"^%s$\"" /* RequestRoot */ " #\"^%s/\"" /* RequestRoot/... */ ")%s)\n", request, request, nodebug); if (!RunUser) cupsFilePrintf(fp, "(deny file-write* file-read-data file-read-metadata\n" " (regex" " #\"^/Users$\"" " #\"^/Users/\"" ")%s)\n", nodebug); cupsFilePrintf(fp, "(deny file-write*\n" " (regex" " #\"^%s$\"" /* ServerRoot */ " #\"^%s/\"" /* ServerRoot/... */ " #\"^/private/etc$\"" " #\"^/private/etc/\"" " #\"^/usr/local/etc$\"" " #\"^/usr/local/etc/\"" " #\"^/Library$\"" " #\"^/Library/\"" " #\"^/System$\"" " #\"^/System/\"" ")%s)\n", root, root, nodebug); /* Specifically allow applications to stat RequestRoot */ cupsFilePrintf(fp, "(allow file-read-metadata\n" " (regex" " #\"^%s$\"" /* RequestRoot */ "))\n", request); cupsFilePrintf(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" " #\"^%s$\"" /* TempDir */ " #\"^%s/\"" /* TempDir/... */ " #\"^%s$\"" /* CacheDir */ " #\"^%s/\"" /* CacheDir/... */ " #\"^%s/Library$\"" /* RequestRoot/Library */ " #\"^%s/Library/\"" /* RequestRoot/Library/... */ " #\"^/Library/Application Support/\"" " #\"^/Library/Caches/\"" " #\"^/Library/Preferences/\"" " #\"^/Library/Printers/.*/\"" " #\"^/Users/Shared/\"" "))\n", temp, temp, cache, cache, request, request); cupsFilePrintf(fp, "(deny file-write*\n" " (regex" " #\"^/Library/Printers/PPDs$\"" " #\"^/Library/Printers/PPDs/\"" " #\"^/Library/Printers/PPD Plugins$\"" " #\"^/Library/Printers/PPD Plugins/\"" ")%s)\n", nodebug); if (job_id) { /* * Allow job filters to read the spool file(s)... */ cupsFilePrintf(fp, "(allow file-read-data file-read-metadata\n" " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n", request, job_id, job_id); } else { /* * Allow email notifications from notifiers... */ cupsFilePuts(fp, "(allow process-exec\n" " (literal \"/usr/sbin/sendmail\")\n" " (with no-sandbox)\n" ")\n"); } cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = \"%s\"", job_id, profile); return ((void *)strdup(profile)); #else cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", job_id); return (NULL); #endif /* HAVE_SANDBOX_H */ }
void cupsdSaveAllSubscriptions(void) { int i; /* Looping var */ cups_file_t *fp; /* subscriptions.conf file */ char filename[1024], /* subscriptions.conf filename */ temp[1024]; /* Temporary string */ cupsd_subscription_t *sub; /* Current subscription */ time_t curtime; /* Current time */ struct tm *curdate; /* Current date */ unsigned mask; /* Current event mask */ const char *name; /* Current event name */ int hex; /* Non-zero if we are writing hex data */ /* * Create the subscriptions.conf file... */ snprintf(filename, sizeof(filename), "%s/subscriptions.conf", ServerRoot); if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL) return; cupsdLogMessage(CUPSD_LOG_INFO, "Saving subscriptions.conf..."); /* * Write a small header to the file... */ curtime = time(NULL); curdate = localtime(&curtime); strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); cupsFilePuts(fp, "# Subscription configuration file for " CUPS_SVERSION "\n"); cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); cupsFilePrintf(fp, "NextSubscriptionId %d\n", NextSubscriptionId); /* * Write every subscription known to the system... */ for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions); sub; sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions)) { cupsFilePrintf(fp, "<Subscription %d>\n", sub->id); if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL) { /* * Simple event list... */ cupsFilePrintf(fp, "Events %s\n", name); } else { /* * Complex event list... */ cupsFilePuts(fp, "Events"); for (mask = 1; mask < CUPSD_EVENT_ALL; mask <<= 1) if (sub->mask & mask) cupsFilePrintf(fp, " %s", cupsdEventName((cupsd_eventmask_t)mask)); cupsFilePuts(fp, "\n"); } if (sub->owner) cupsFilePrintf(fp, "Owner %s\n", sub->owner); if (sub->recipient) cupsFilePrintf(fp, "Recipient %s\n", sub->recipient); if (sub->job) cupsFilePrintf(fp, "JobId %d\n", sub->job->id); if (sub->dest) cupsFilePrintf(fp, "PrinterName %s\n", sub->dest->name); if (sub->user_data_len > 0) { cupsFilePuts(fp, "UserData "); for (i = 0, hex = 0; i < sub->user_data_len; i ++) { if (sub->user_data[i] < ' ' || sub->user_data[i] > 0x7f || sub->user_data[i] == '<') { if (!hex) { cupsFilePrintf(fp, "<%02X", sub->user_data[i]); hex = 1; } else cupsFilePrintf(fp, "%02X", sub->user_data[i]); } else { if (hex) { cupsFilePrintf(fp, ">%c", sub->user_data[i]); hex = 0; } else cupsFilePutChar(fp, sub->user_data[i]); } } if (hex) cupsFilePuts(fp, ">\n"); else cupsFilePutChar(fp, '\n'); } cupsFilePrintf(fp, "LeaseDuration %d\n", sub->lease); cupsFilePrintf(fp, "Interval %d\n", sub->interval); cupsFilePrintf(fp, "ExpirationTime %ld\n", (long)sub->expire); cupsFilePrintf(fp, "NextEventId %d\n", sub->next_event_id); cupsFilePuts(fp, "</Subscription>\n"); } cupsdCloseCreatedConfFile(fp, filename); }
static void update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */ { if (!LPDConfigFile) return; #ifdef __APPLE__ /* * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf * setting for backwards-compatibility. */ if (onoff && !get_hostconfig("CUPS_LPD")) onoff = 0; #endif /* __APPLE__ */ if (!strncmp(LPDConfigFile, "xinetd:///", 10)) { /* * Enable/disable LPD via the xinetd.d config file for cups-lpd... */ char newfile[1024]; /* New cups-lpd.N file */ cups_file_t *ofp, /* Original file pointer */ *nfp; /* New file pointer */ char line[1024]; /* Line from file */ snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9); if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s", LPDConfigFile + 9, strerror(errno)); return; } if ((nfp = cupsFileOpen(newfile, "w")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s", newfile, strerror(errno)); cupsFileClose(ofp); return; } /* * Copy all of the lines from the cups-lpd file... */ while (cupsFileGets(ofp, line, sizeof(line))) { if (line[0] == '{') { cupsFilePrintf(nfp, "%s\n", line); snprintf(line, sizeof(line), "\tdisable = %s", onoff ? "no" : "yes"); } else if (!strstr(line, "disable =")) cupsFilePrintf(nfp, "%s\n", line); } cupsFileClose(nfp); cupsFileClose(ofp); rename(newfile, LPDConfigFile + 9); } #ifdef __APPLE__ else if (!strncmp(LPDConfigFile, "launchd:///", 11)) { /* * Enable/disable LPD via the launchctl command... */ char *argv[5], /* Arguments for command */ *envp[MAX_ENV]; /* Environment for command */ int pid; /* Process ID */ cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); argv[0] = (char *)"launchctl"; argv[1] = (char *)(onoff ? "load" : "unload"); argv[2] = (char *)"-w"; argv[3] = LPDConfigFile + 10; argv[4] = NULL; cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1, NULL, NULL, &pid); } #endif /* __APPLE__ */ else cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!"); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ char path[1024], /* Path to documentation */ line[1024]; /* Line from file */ help_index_t *hi; /* Help index */ cups_file_t *tokens, /* Tokens.xml file */ *fp; /* Current file */ if (argc < 4) { puts("Usage: makedocset directory revision *.tokens"); return (1); } /* * Index the help documents... */ snprintf(path, sizeof(path), "%s/Contents/Resources/Documentation", argv[1]); if ((hi = helpLoadIndex(NULL, path)) == NULL) { fputs("makedocset: Unable to index help files!\n", stderr); return (1); } snprintf(path, sizeof(path), "%s/Contents/Resources/Documentation/index.html", argv[1]); write_index(path, hi); snprintf(path, sizeof(path), "%s/Contents/Resources/Nodes.xml", argv[1]); write_nodes(path, hi); /* * Write the Info.plist file... */ snprintf(path, sizeof(path), "%s/Contents/Info.plist", argv[1]); write_info(path, argv[2]); /* * Merge the Tokens.xml files... */ snprintf(path, sizeof(path), "%s/Contents/Resources/Tokens.xml", argv[1]); if ((tokens = cupsFileOpen(path, "w")) == NULL) { fprintf(stderr, "makedocset: Unable to create \"%s\": %s\n", path, strerror(errno)); return (1); } cupsFilePuts(tokens, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); cupsFilePuts(tokens, "<Tokens version=\"1.0\">\n"); for (i = 3; i < argc; i ++) { if ((fp = cupsFileOpen(argv[i], "r")) == NULL) { fprintf(stderr, "makedocset: Unable to open \"%s\": %s\n", argv[i], strerror(errno)); return (1); } if (!cupsFileGets(fp, line, sizeof(line)) || strncmp(line, "<?xml ", 6) || !cupsFileGets(fp, line, sizeof(line)) || strncmp(line, "<Tokens ", 8)) { fprintf(stderr, "makedocset: Bad Tokens.xml file \"%s\"!\n", argv[i]); return (1); } while (cupsFileGets(fp, line, sizeof(line))) { if (strcmp(line, "</Tokens>")) cupsFilePrintf(tokens, "%s\n", line); } cupsFileClose(fp); } cupsFilePuts(tokens, "</Tokens>\n"); cupsFileClose(tokens); /* * Return with no errors... */ return (0); }
static void write_nodes(const char *path, /* I - File to write */ help_index_t *hi) /* I - Index of files */ { cups_file_t *fp; /* Output file */ int id; /* Current node ID */ help_node_t *node; /* Current help node */ int subnodes; /* Currently in Subnodes for file? */ int needclose; /* Need to close the current node? */ if ((fp = cupsFileOpen(path, "w")) == NULL) { fprintf(stderr, "makedocset: Unable to create %s: %s\n", path, strerror(errno)); exit(1); } cupsFilePuts(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<DocSetNodes version=\"1.0\">\n" "<TOC>\n" "<Node id=\"0\">\n" "<Name>CUPS Documentation</Name>\n" "<Path>Documentation/index.html</Path>\n" "</Node>\n"); for (node = (help_node_t *)cupsArrayFirst(hi->nodes), id = 1, subnodes = 0, needclose = 0; node; node = (help_node_t *)cupsArrayNext(hi->nodes), id ++) { if (node->anchor) { if (!subnodes) { cupsFilePuts(fp, "<Subnodes>\n"); subnodes = 1; } cupsFilePrintf(fp, "<Node id=\"%d\">\n" "<Path>Documentation/%s</Path>\n" "<Anchor>%s</Anchor>\n" "<Name>%s</Name>\n" "</Node>\n", id, node->filename, node->anchor, node->text); } else { if (subnodes) { cupsFilePuts(fp, "</Subnodes>\n"); subnodes = 0; } if (needclose) cupsFilePuts(fp, "</Node>\n"); cupsFilePrintf(fp, "<Node id=\"%d\">\n" "<Path>Documentation/%s</Path>\n" "<Name>%s</Name>\n", id, node->filename, node->text); needclose = 1; } } if (subnodes) cupsFilePuts(fp, "</Subnodes>\n"); if (needclose) cupsFilePuts(fp, "</Node>\n"); cupsFilePuts(fp, "</TOC>\n" "</DocSetNodes>\n"); cupsFileClose(fp); }
static void write_index(const char *path, /* I - File to write */ help_index_t *hi) /* I - Index of files */ { cups_file_t *fp; /* Output file */ help_node_t *node; /* Current help node */ _cups_section_t *section, /* Current section */ key; /* Section search key */ _cups_html_t *html; /* Current HTML file */ cups_array_t *sections, /* Sections in index */ *sections_files,/* Sections sorted by size */ *columns[3]; /* Columns in final HTML file */ int column, /* Current column */ lines[3], /* Number of lines in each column */ min_column, /* Smallest column */ min_lines; /* Smallest number of lines */ /* * Build an array of sections and their files. */ sections = cupsArrayNew((cups_array_func_t)compare_sections, NULL); for (node = (help_node_t *)cupsArrayFirst(hi->nodes); node; node = (help_node_t *)cupsArrayNext(hi->nodes)) { if (node->anchor) continue; key.name = node->section ? node->section : "Miscellaneous"; if ((section = (_cups_section_t *)cupsArrayFind(sections, &key)) == NULL) { section = (_cups_section_t *)calloc(1, sizeof(_cups_section_t)); section->name = key.name; section->files = cupsArrayNew((cups_array_func_t)compare_html, NULL); cupsArrayAdd(sections, section); } html = (_cups_html_t *)calloc(1, sizeof(_cups_html_t)); html->path = node->filename; html->title = node->text; cupsArrayAdd(section->files, html); } /* * Build a sorted list of sections based on the number of files in each section * and the section name... */ sections_files = cupsArrayNew((cups_array_func_t)compare_sections_files, NULL); for (section = (_cups_section_t *)cupsArrayFirst(sections); section; section = (_cups_section_t *)cupsArrayNext(sections)) cupsArrayAdd(sections_files, section); /* * Then build three columns to hold everything, trying to balance the number of * lines in each column... */ for (column = 0; column < 3; column ++) { columns[column] = cupsArrayNew((cups_array_func_t)compare_sections, NULL); lines[column] = 0; } for (section = (_cups_section_t *)cupsArrayFirst(sections_files); section; section = (_cups_section_t *)cupsArrayNext(sections_files)) { for (min_column = 0, min_lines = lines[0], column = 1; column < 3; column ++) { if (lines[column] < min_lines) { min_column = column; min_lines = lines[column]; } } cupsArrayAdd(columns[min_column], section); lines[min_column] += cupsArrayCount(section->files) + 2; } /* * Write the HTML file... */ if ((fp = cupsFileOpen(path, "w")) == NULL) { fprintf(stderr, "makedocset: Unable to create %s: %s\n", path, strerror(errno)); exit(1); } cupsFilePuts(fp, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " "Transitional//EN\" " "\"http://www.w3.org/TR/html4/loose.dtd\">\n" "<html>\n" "<head>\n" "<title>CUPS Documentation</title>\n" "<link rel='stylesheet' type='text/css' " "href='cups-printable.css'>\n" "</head>\n" "<body>\n" "<h1 class='title'>CUPS Documentation</h1>\n" "<table width='100%' summary=''>\n" "<tr>\n"); for (column = 0; column < 3; column ++) { if (column) cupsFilePuts(fp, "<td> </td>\n"); cupsFilePuts(fp, "<td valign='top' width='33%'>"); for (section = (_cups_section_t *)cupsArrayFirst(columns[column]); section; section = (_cups_section_t *)cupsArrayNext(columns[column])) { cupsFilePrintf(fp, "<h2 class='title'>%s</h2>\n", section->name); for (html = (_cups_html_t *)cupsArrayFirst(section->files); html; html = (_cups_html_t *)cupsArrayNext(section->files)) cupsFilePrintf(fp, "<p class='compact'><a href='%s'>%s</a></p>\n", html->path, html->title); } cupsFilePuts(fp, "</td>\n"); } cupsFilePuts(fp, "</tr>\n" "</table>\n" "</body>\n" "</html>\n"); cupsFileClose(fp); }
void cupsdSaveAllClasses(void) { cups_file_t *fp; /* classes.conf file */ char temp[1024], /* Temporary string */ backup[1024], /* printers.conf.O file */ value[2048]; /* Value string */ cupsd_printer_t *pclass; /* Current printer class */ int i; /* Looping var */ time_t curtime; /* Current time */ struct tm *curdate; /* Current date */ cups_option_t *option; /* Current option */ /* * Create the classes.conf file... */ snprintf(temp, sizeof(temp), "%s/classes.conf", ServerRoot); snprintf(backup, sizeof(backup), "%s/classes.conf.O", ServerRoot); if (rename(temp, backup)) { if (errno != ENOENT) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to backup classes.conf - %s", strerror(errno)); } if ((fp = cupsFileOpen(temp, "w")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to save classes.conf - %s", strerror(errno)); if (rename(backup, temp)) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to restore classes.conf - %s", strerror(errno)); return; } else cupsdLogMessage(CUPSD_LOG_INFO, "Saving classes.conf..."); /* * Restrict access to the file... */ fchown(cupsFileNumber(fp), RunUser, Group); fchmod(cupsFileNumber(fp), 0600); /* * Write a small header to the file... */ curtime = time(NULL); curdate = localtime(&curtime); strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); cupsFilePuts(fp, "# Class configuration file for " CUPS_SVERSION "\n"); cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); cupsFilePuts(fp, "# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING\n"); /* * Write each local class known to the system... */ for (pclass = (cupsd_printer_t *)cupsArrayFirst(Printers); pclass; pclass = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* * Skip remote destinations and regular printers... */ if ((pclass->type & CUPS_PRINTER_REMOTE) || (pclass->type & CUPS_PRINTER_IMPLICIT) || !(pclass->type & CUPS_PRINTER_CLASS)) continue; /* * Write printers as needed... */ if (pclass == DefaultPrinter) cupsFilePrintf(fp, "<DefaultClass %s>\n", pclass->name); else cupsFilePrintf(fp, "<Class %s>\n", pclass->name); if (pclass->num_auth_info_required > 0) { switch (pclass->num_auth_info_required) { case 1 : strlcpy(value, pclass->auth_info_required[0], sizeof(value)); break; case 2 : snprintf(value, sizeof(value), "%s,%s", pclass->auth_info_required[0], pclass->auth_info_required[1]); break; case 3 : default : snprintf(value, sizeof(value), "%s,%s,%s", pclass->auth_info_required[0], pclass->auth_info_required[1], pclass->auth_info_required[2]); break; } cupsFilePutConf(fp, "AuthInfoRequired", value); } if (pclass->info) cupsFilePutConf(fp, "Info", pclass->info); if (pclass->location) cupsFilePutConf(fp, "Location", pclass->location); if (pclass->state == IPP_PRINTER_STOPPED) cupsFilePuts(fp, "State Stopped\n"); else cupsFilePuts(fp, "State Idle\n"); cupsFilePrintf(fp, "StateTime %d\n", (int)pclass->state_time); if (pclass->accepting) cupsFilePuts(fp, "Accepting Yes\n"); else cupsFilePuts(fp, "Accepting No\n"); if (pclass->shared) cupsFilePuts(fp, "Shared Yes\n"); else cupsFilePuts(fp, "Shared No\n"); snprintf(value, sizeof(value), "%s %s", pclass->job_sheets[0], pclass->job_sheets[1]); cupsFilePutConf(fp, "JobSheets", value); for (i = 0; i < pclass->num_printers; i ++) cupsFilePrintf(fp, "Printer %s\n", pclass->printers[i]->name); cupsFilePrintf(fp, "QuotaPeriod %d\n", pclass->quota_period); cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit); cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit); for (i = 0; i < pclass->num_users; i ++) cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser", pclass->users[i]); if (pclass->op_policy) cupsFilePutConf(fp, "OpPolicy", pclass->op_policy); if (pclass->error_policy) cupsFilePutConf(fp, "ErrorPolicy", pclass->error_policy); for (i = pclass->num_options, option = pclass->options; i > 0; i --, option ++) { snprintf(value, sizeof(value), "%s %s", option->name, option->value); cupsFilePutConf(fp, "Option", value); } cupsFilePuts(fp, "</Class>\n"); } cupsFileClose(fp); }
static int /* O - 0 on success, 1 on fail */ set_printer_options( http_t *http, /* I - Server connection */ char *printer, /* I - Printer */ int num_options, /* I - Number of options */ cups_option_t *options, /* I - Options */ char *file) /* I - PPD file/interface script */ { ipp_t *request; /* IPP Request */ const char *ppdfile; /* PPD filename */ int ppdchanged = 0; /* PPD changed? */ ppd_file_t *ppd; /* PPD file */ ppd_choice_t *choice; /* Marked choice */ char uri[HTTP_MAX_URI], /* URI for printer/class */ line[1024], /* Line from PPD file */ keyword[1024], /* Keyword from Default line */ *keyptr, /* Pointer into keyword... */ tempfile[1024]; /* Temporary filename */ cups_file_t *in, /* PPD file */ *out; /* Temporary file */ const char *ppdname, /* ppd-name value */ *protocol, /* Old protocol option */ *customval, /* Custom option value */ *boolval; /* Boolean value */ int wrote_ipp_supplies = 0, /* Wrote cupsIPPSupplies keyword? */ wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */ copied_options = 0; /* Copied options? */ DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, " "options=%p, file=\"%s\")\n", http, printer, num_options, options, file)); /* * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request, * which requires the following attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name * other options */ if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Add the options... */ if (file) ppdfile = file; else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "raw") && num_options > 1) { if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL) { /* * Copy options array and remove ppd-name from it... */ cups_option_t *temp = NULL, *optr; int i, num_temp = 0; for (i = num_options, optr = options; i > 0; i --, optr ++) if (strcmp(optr->name, "ppd-name")) num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp); copied_options = 1; ppdchanged = 1; num_options = num_temp; options = temp; } } else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER) ppdfile = cupsGetPPD(printer); else ppdfile = NULL; cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION); cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER); if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL) { if (!_cups_strcasecmp(protocol, "bcp")) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor", NULL, "bcp"); else if (!_cups_strcasecmp(protocol, "tbcp")) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor", NULL, "tbcp"); } if (ppdfile) { /* * Set default options in the PPD file... */ if ((ppd = ppdOpenFile(ppdfile)) == NULL) { int linenum; /* Line number of error */ ppd_status_t status = ppdLastError(&linenum); /* Status code */ _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum); } ppdMarkDefaults(ppd); cupsMarkOptions(ppd, num_options, options); if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL) { _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file")); ippDelete(request); if (ppdfile != file) unlink(ppdfile); if (copied_options) cupsFreeOptions(num_options, options); return (1); } if ((in = cupsFileOpen(ppdfile, "r")) == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD file \"%s\" - %s"), ppdfile, strerror(errno)); ippDelete(request); if (ppdfile != file) unlink(ppdfile); if (copied_options) cupsFreeOptions(num_options, options); cupsFileClose(out); unlink(tempfile); return (1); } while (cupsFileGets(in, line, sizeof(line))) { if (!strncmp(line, "*cupsIPPSupplies:", 17) && (boolval = cupsGetOption("cupsIPPSupplies", num_options, options)) != NULL) { wrote_ipp_supplies = 1; cupsFilePrintf(out, "*cupsIPPSupplies: %s\n", (!_cups_strcasecmp(boolval, "true") || !_cups_strcasecmp(boolval, "yes") || !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); } else if (!strncmp(line, "*cupsSNMPSupplies:", 18) && (boolval = cupsGetOption("cupsSNMPSupplies", num_options, options)) != NULL) { wrote_snmp_supplies = 1; cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n", (!_cups_strcasecmp(boolval, "true") || !_cups_strcasecmp(boolval, "yes") || !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); } else if (strncmp(line, "*Default", 8)) cupsFilePrintf(out, "%s\n", line); else { /* * Get default option name... */ strlcpy(keyword, line + 8, sizeof(keyword)); for (keyptr = keyword; *keyptr; keyptr ++) if (*keyptr == ':' || isspace(*keyptr & 255)) break; *keyptr++ = '\0'; while (isspace(*keyptr & 255)) keyptr ++; if (!strcmp(keyword, "PageRegion") || !strcmp(keyword, "PageSize") || !strcmp(keyword, "PaperDimension") || !strcmp(keyword, "ImageableArea")) { if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL) choice = ppdFindMarkedChoice(ppd, "PageRegion"); } else choice = ppdFindMarkedChoice(ppd, keyword); if (choice && strcmp(choice->choice, keyptr)) { if (strcmp(choice->choice, "Custom")) { cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice); ppdchanged = 1; } else if ((customval = cupsGetOption(keyword, num_options, options)) != NULL) { cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval); ppdchanged = 1; } else cupsFilePrintf(out, "%s\n", line); } else cupsFilePrintf(out, "%s\n", line); } } if (!wrote_ipp_supplies && (boolval = cupsGetOption("cupsIPPSupplies", num_options, options)) != NULL) { cupsFilePrintf(out, "*cupsIPPSupplies: %s\n", (!_cups_strcasecmp(boolval, "true") || !_cups_strcasecmp(boolval, "yes") || !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); } if (!wrote_snmp_supplies && (boolval = cupsGetOption("cupsSNMPSupplies", num_options, options)) != NULL) { cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n", (!_cups_strcasecmp(boolval, "true") || !_cups_strcasecmp(boolval, "yes") || !_cups_strcasecmp(boolval, "on")) ? "True" : "False"); } cupsFileClose(in); cupsFileClose(out); ppdClose(ppd); /* * Do the request... */ ippDelete(cupsDoFileRequest(http, request, "/admin/", ppdchanged ? tempfile : file)); /* * Clean up temp files... (TODO: catch signals in case we CTRL-C during * lpadmin) */ if (ppdfile != file) unlink(ppdfile); unlink(tempfile); } else { /* * No PPD file - just set the options... */ ippDelete(cupsDoRequest(http, request, "/admin/")); } if (copied_options) cupsFreeOptions(num_options, options); /* * Check the response... */ if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); return (1); } else return (0); }