int /* O - -1 on error, 0 on success */ httpSaveCredentials( const char *path, /* I - Keychain/PKCS#12 path */ cups_array_t *credentials, /* I - Credentials */ const char *common_name) /* I - Common name for credentials */ { cups_file_t *fp; /* Certificate file */ char filename[1024], /* filename.crt */ nfilename[1024],/* filename.crt.N */ temp[1024], /* Temporary string */ line[256]; /* Base64-encoded line */ const unsigned char *ptr; /* Pointer into certificate */ ssize_t remaining; /* Bytes left */ http_credential_t *cred; /* Current credential */ if (!credentials || !common_name) return (-1); if (!path) path = http_gnutls_default_path(temp, sizeof(temp)); if (!path) return (-1); http_gnutls_make_path(filename, sizeof(filename), path, common_name, "crt"); snprintf(nfilename, sizeof(nfilename), "%s.N", filename); if ((fp = cupsFileOpen(nfilename, "w")) == NULL) return (-1); fchmod(cupsFileNumber(fp), 0600); for (cred = (http_credential_t *)cupsArrayFirst(credentials); cred; cred = (http_credential_t *)cupsArrayNext(credentials)) { cupsFilePuts(fp, "-----BEGIN CERTIFICATE-----\n"); for (ptr = cred->data, remaining = (ssize_t)cred->datalen; remaining > 0; remaining -= 45, ptr += 45) { httpEncode64_2(line, sizeof(line), (char *)ptr, remaining > 45 ? 45 : remaining); cupsFilePrintf(fp, "%s\n", line); } cupsFilePuts(fp, "-----END CERTIFICATE-----\n"); } cupsFileClose(fp); return (rename(nfilename, filename)); }
void cupsdInitCerts(void) { #ifndef HAVE_ARC4RANDOM cups_file_t *fp; /* /dev/random file */ /* * Initialize the random number generator using the random device or * the current time, as available... */ if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL) { struct timeval tod; /* Time of day */ /* * Get the time in usecs and use it as the initial seed... */ gettimeofday(&tod, NULL); CUPS_SRAND((unsigned)(tod.tv_sec + tod.tv_usec)); } else { unsigned seed; /* Seed for random number generator */ /* * Read 4 random characters from the random device and use * them as the seed... */ seed = cupsFileGetChar(fp); seed = (seed << 8) | cupsFileGetChar(fp); seed = (seed << 8) | cupsFileGetChar(fp); CUPS_SRAND((seed << 8) | cupsFileGetChar(fp)); cupsFileClose(fp); } #endif /* !HAVE_ARC4RANDOM */ /* * Create a root certificate and return... */ if (!RunUser) cupsdAddCert(0, "root", cupsdDefaultAuthType()); }
int /* O - 1 on success, 0 on error */ save_messages(cups_array_t *cat, /* I - Message catalog */ const char *filename) /* I - File to save to */ { _cups_message_t *m; /* Current message */ cups_file_t *fp; /* File pointer */ /* * Open the message catalog... */ if ((fp = cupsFileOpen(filename, "w")) == NULL) return (0); /* * Save the messages to a file... */ for (m = (_cups_message_t *)cupsArrayFirst(cat); m; m = (_cups_message_t *)cupsArrayNext(cat)) { if (cupsFilePuts(fp, "msgid \"") < 0) break; if (!write_string(fp, m->id)) break; if (cupsFilePuts(fp, "\"\nmsgstr \"") < 0) break; if (m->str) { if (!write_string(fp, m->str)) break; } if (cupsFilePuts(fp, "\"\n") < 0) break; } cupsFileClose(fp); return (!m); }
static int /* O - 1 for YES or AUTOMATIC, 0 for NO */ get_hostconfig(const char *name) /* I - Name of service */ { cups_file_t *fp; /* Hostconfig file */ char line[1024], /* Line from file */ *ptr; /* Pointer to value */ int state = 1; /* State of service */ /* * Try opening the /etc/hostconfig file; if we can't open it, assume that * the service is enabled/auto. */ if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL) { /* * Read lines from the file until we find the service... */ while (cupsFileGets(fp, line, sizeof(line))) { if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL) continue; *ptr++ = '\0'; if (!_cups_strcasecmp(line, name)) { /* * Found the service, see if it is set to "-NO-"... */ if (!_cups_strncasecmp(ptr, "-NO-", 4)) state = 0; break; } } cupsFileClose(fp); } return (state); }
static void write_info(const char *path, /* I - File to write */ const char *revision) /* I - Subversion revision number */ { cups_file_t *fp; /* File */ if ((fp = cupsFileOpen(path, "w")) == NULL) { fprintf(stderr, "makedocset: Unable to create %s: %s\n", path, strerror(errno)); exit(1); } cupsFilePrintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" " "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">\n" "<dict>\n" "\t<key>CFBundleIdentifier</key>\n" "\t<string>org.cups.docset</string>\n" "\t<key>CFBundleName</key>\n" "\t<string>CUPS Documentation</string>\n" "\t<key>CFBundleVersion</key>\n" "\t<string>%d.%d.%s</string>\n" "\t<key>CFBundleShortVersionString</key>\n" "\t<string>%d.%d.%d</string>\n" "\t<key>DocSetFeedName</key>\n" "\t<string>cups.org</string>\n" "\t<key>DocSetFeedURL</key>\n" "\t<string>http://www.cups.org/org.cups.docset.atom" "</string>\n" "\t<key>DocSetPublisherIdentifier</key>\n" "\t<string>org.cups</string>\n" "\t<key>DocSetPublisherName</key>\n" "\t<string>CUPS</string>\n" "</dict>\n" "</plist>\n", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR, revision, CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR, CUPS_VERSION_PATCH); cupsFileClose(fp); }
const char * /* O - Default community name */ _cupsSNMPDefaultCommunity(void) { cups_file_t *fp; /* snmp.conf file */ char line[1024], /* Line from file */ *value; /* Value from file */ int linenum; /* Line number in file */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ DEBUG_puts("4_cupsSNMPDefaultCommunity()"); if (!cg->snmp_community[0]) { strlcpy(cg->snmp_community, "public", sizeof(cg->snmp_community)); snprintf(line, sizeof(line), "%s/snmp.conf", cg->cups_serverroot); if ((fp = cupsFileOpen(line, "r")) != NULL) { linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) if (!_cups_strcasecmp(line, "Community") && value) { strlcpy(cg->snmp_community, value, sizeof(cg->snmp_community)); break; } cupsFileClose(fp); } } DEBUG_printf(("5_cupsSNMPDefaultCommunity: Returning \"%s\"", cg->snmp_community)); return (cg->snmp_community); }
static int /* O - 0 on success, 1 on failure */ check_file(const char *filename) /* I - File to read from */ { int i; /* Looping var */ cups_file_t *fp; /* File */ char line[1024]; /* Line from file */ int ch; /* Current character */ size_t bytes; /* Length of line */ int status; /* Status of test */ int linenum; /* Line number */ int binary; /* File contains binary data? */ float version; /* DSC version */ int lbrt[4]; /* Bounding box */ char page_label[256]; /* Page label string */ int page_number; /* Page number */ int last_page_number; /* Last page number seen */ int level; /* Embedded document level */ int saw_bounding_box, /* %%BoundingBox seen? */ saw_pages, /* %%Pages seen? */ saw_end_comments, /* %%EndComments seen? */ saw_begin_prolog, /* %%BeginProlog seen? */ saw_end_prolog, /* %%EndProlog seen? */ saw_begin_setup, /* %%BeginSetup seen? */ saw_end_setup, /* %%EndSetup seen? */ saw_page, /* %%Page seen? */ saw_trailer, /* %%Trailer seen? */ saw_long_line; /* Saw long lines? */ /* * Open the file... */ if (!strcmp(filename, "(stdin)")) fp = cupsFileStdin(); else fp = cupsFileOpen(filename, "r"); if (!fp) { perror(filename); return (1); } /* * Scan the file... */ binary = 0; last_page_number = 0; level = 0; linenum = 0; saw_begin_prolog = 0; saw_begin_setup = 0; saw_bounding_box = 0; saw_end_comments = 0; saw_end_prolog = 0; saw_end_setup = 0; saw_long_line = 0; saw_page = 0; saw_pages = 0; saw_trailer = 0; status = 0; version = 0.0f; /* TODO: Fixme */ printf("%s: ", filename); fflush(stdout); while ((bytes = cupsFileGetLine(fp, line, sizeof(line))) > 0) { linenum ++; if (bytes > 255) { if (!saw_long_line) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Line %d is longer than 255 characters (%d).\n" " REF: Page 25, Line Length"), linenum, (int)bytes); } saw_long_line ++; } if (linenum == 1) { if (strncmp(line, "%!PS-Adobe-", 11)) { if (!status) _cupsLangPuts(stdout, _("FAIL")); _cupsLangPuts(stdout, _(" Missing %!PS-Adobe-3.0 on first line.\n" " REF: Page 17, 3.1 Conforming Documents")); cupsFileClose(fp); return (1); } else version = atof(line + 11); } else if (level > 0) { if (!strncmp(line, "%%BeginDocument:", 16)) level ++; else if (!strncmp(line, "%%EndDocument", 13)) level --; } else if (saw_trailer) { if (!strncmp(line, "%%Pages:", 8)) { if (atoi(line + 8) <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d.\n" " REF: Page 43, %%%%Pages:"), linenum); } else saw_pages = 1; } else if (!strncmp(line, "%%BoundingBox:", 14)) { if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2, lbrt + 3) != 4) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n" " REF: Page 39, %%%%BoundingBox:"), linenum); } else saw_bounding_box = 1; } } else if (!saw_end_comments) { if (!strncmp(line, "%%EndComments", 13)) saw_end_comments = 1; else if (line[0] != '%') saw_end_comments = -1; else if (!strncmp(line, "%%Pages:", 8)) { if (strstr(line + 8, "(atend)")) saw_pages = -1; else if (atoi(line + 8) <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d.\n" " REF: Page 43, %%%%Pages:"), linenum); } else saw_pages = 1; } else if (!strncmp(line, "%%BoundingBox:", 14)) { if (strstr(line, "(atend)")) saw_bounding_box = -1; else if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2, lbrt + 3) != 4) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n" " REF: Page 39, %%%%BoundingBox:"), linenum); } else saw_bounding_box = 1; } } else if (saw_begin_prolog && !saw_end_prolog) { if (!strncmp(line, "%%EndProlog", 11)) saw_end_prolog = 1; } else if (saw_begin_setup && !saw_end_setup) { if (!strncmp(line, "%%EndSetup", 10)) saw_end_setup = 1; } else if (saw_end_comments) { if (!strncmp(line, "%%Page:", 7)) { if (sscanf(line + 7, "%255s%d", page_label, &page_number) != 2 || page_number != (last_page_number + 1) || page_number < 1) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPrintf(stdout, _(" Bad %%%%Page: on line %d.\n" " REF: Page 53, %%%%Page:"), linenum); } else { last_page_number = page_number; saw_page = 1; } } else if (!strncmp(line, "%%BeginProlog", 13)) saw_begin_prolog = 1; else if (!strncmp(line, "%%BeginSetup", 12)) saw_begin_setup = 1; else if (!strncmp(line, "%%BeginDocument:", 16)) level ++; else if (!strncmp(line, "%%EndDocument", 13)) level --; else if (!strncmp(line, "%%Trailer", 9)) saw_trailer = 1; } for (i = 0; !binary && i < bytes; i ++) { ch = line[i]; if ((ch < ' ' || (ch & 0x80)) && ch != '\n' && ch != '\r' && ch != '\t') binary = 1; } } if (saw_bounding_box <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%BoundingBox: comment.\n" " REF: Page 39, %%BoundingBox:")); } if (saw_pages <= 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%Pages: comment.\n" " REF: Page 43, %%Pages:")); } if (!saw_end_comments) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing %%EndComments comment." " REF: Page 41, %%EndComments")); } if (!saw_page) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Missing or bad %%Page: comments.\n" " REF: Page 53, %%Page:")); } if (level < 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Too many %%EndDocument comments.")); } else if (level > 0) { if (!status) _cupsLangPuts(stdout, _("FAIL")); status ++; _cupsLangPuts(stdout, _(" Too many %%BeginDocument comments.")); } if (saw_long_line > 1) _cupsLangPrintf(stderr, _(" Saw %d lines that exceeded 255 characters."), saw_long_line); if (!status) _cupsLangPuts(stdout, _("PASS")); if (binary) _cupsLangPuts(stdout, _(" Warning: file contains binary data.")); if (version < 3.0f) _cupsLangPrintf(stdout, _(" Warning: obsolete DSC version %.1f in file."), version); if (saw_end_comments < 0) _cupsLangPuts(stdout, _(" Warning: no %%EndComments comment in file.")); cupsFileClose(fp); return (status); }
cups_array_t * /* O - New message array */ _cupsMessageLoad(const char *filename, /* I - Message catalog to load */ int unquote) /* I - Unescape \foo in strings? */ { cups_file_t *fp; /* Message file */ cups_array_t *a; /* Message array */ _cups_message_t *m; /* Current message */ char s[4096], /* String buffer */ *ptr, /* Pointer into buffer */ *temp; /* New string */ size_t length, /* Length of combined strings */ ptrlen; /* Length of string */ DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename)); /* * Create an array to hold the messages... */ if ((a = _cupsMessageNew(NULL)) == NULL) { DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!"); return (NULL); } /* * Open the message catalog file... */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { DEBUG_printf(("5_cupsMessageLoad: Unable to open file: %s", strerror(errno))); return (a); } /* * Read messages from the catalog file until EOF... * * The format is the GNU gettext .po format, which is fairly simple: * * msgid "some text" * msgstr "localized text" * * The ID and localized text can span multiple lines using the form: * * msgid "" * "some long text" * msgstr "" * "localized text spanning " * "multiple lines" */ m = NULL; while (cupsFileGets(fp, s, sizeof(s)) != NULL) { /* * Skip blank and comment lines... */ if (s[0] == '#' || !s[0]) continue; /* * Strip the trailing quote... */ if ((ptr = strrchr(s, '\"')) == NULL) continue; *ptr = '\0'; /* * Find start of value... */ if ((ptr = strchr(s, '\"')) == NULL) continue; ptr ++; /* * Unquote the text... */ if (unquote) cups_unquote(ptr, ptr); /* * Create or add to a message... */ if (!strncmp(s, "msgid", 5)) { /* * Add previous message as needed... */ if (m) { if (m->str && m->str[0]) { cupsArrayAdd(a, m); } else { /* * Translation is empty, don't add it... (STR #4033) */ free(m->id); if (m->str) free(m->str); free(m); } } /* * Create a new message with the given msgid string... */ if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL) { cupsFileClose(fp); return (a); } if ((m->id = strdup(ptr)) == NULL) { free(m); cupsFileClose(fp); return (a); } } else if (s[0] == '\"' && m) { /* * Append to current string... */ length = strlen(m->str ? m->str : m->id); ptrlen = strlen(ptr); if ((temp = realloc(m->str ? m->str : m->id, length + ptrlen + 1)) == NULL) { if (m->str) free(m->str); free(m->id); free(m); cupsFileClose(fp); return (a); } if (m->str) { /* * Copy the new portion to the end of the msgstr string - safe * to use memcpy because the buffer is allocated to the correct * size... */ m->str = temp; memcpy(m->str + length, ptr, ptrlen + 1); } else { /* * Copy the new portion to the end of the msgid string - safe * to use memcpy because the buffer is allocated to the correct * size... */ m->id = temp; memcpy(m->id + length, ptr, ptrlen + 1); } } else if (!strncmp(s, "msgstr", 6) && m) { /* * Set the string... */ if ((m->str = strdup(ptr)) == NULL) { free(m->id); free(m); cupsFileClose(fp); return (a); } } } /* * Add the last message string to the array as needed... */ if (m) { if (m->str && m->str[0]) { cupsArrayAdd(a, m); } else { /* * Translation is empty, don't add it... (STR #4033) */ free(m->id); if (m->str) free(m->str); free(m); } } /* * Close the message catalog file and return the new array... */ cupsFileClose(fp); DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...", cupsArrayCount(a))); return (a); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ char *opt; /* Option character */ int fg; /* Run in the foreground */ int fds; /* Number of ready descriptors */ cupsd_client_t *con; /* Current client */ cupsd_job_t *job; /* Current job */ cupsd_listener_t *lis; /* Current listener */ time_t current_time, /* Current time */ activity, /* Client activity timer */ senddoc_time, /* Send-Document time */ expire_time, /* Subscription expire time */ report_time, /* Malloc/client/job report time */ event_time; /* Last event notification time */ long timeout; /* Timeout for cupsdDoSelect() */ struct rlimit limit; /* Runtime limit */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ #ifdef __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */ #endif /* __sgi */ int run_as_child = 0; /* Needed for background fork/exec */ #ifdef __APPLE__ int use_sysman = !getuid(); /* Use system management functions? */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if HAVE_LAUNCHD int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ #ifdef HAVE_GETEUID /* * Check for setuid invocation, which we do not support! */ if (getuid() != geteuid()) { fputs("cupsd: Cannot run as a setuid program\n", stderr); return (1); } #endif /* HAVE_GETEUID */ /* * Check for command-line arguments... */ fg = 0; #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { Launchd = 1; fg = 1; } #endif /* HAVE_LAUNCHD */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { case 'C' : /* Run as child with config file */ run_as_child = 1; fg = -1; case 'c' : /* Configuration file */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected config filename " "after \"-c\" option.")); usage(1); } if (argv[i][0] == '/') { /* * Absolute directory... */ cupsdSetString(&ConfigurationFile, argv[i]); } else { /* * Relative directory... */ char *current; /* Current directory */ /* * Allocate a buffer for the current working directory to * reduce run-time stack usage; this approximates the * behavior of some implementations of getcwd() when they * are passed a NULL pointer. */ if ((current = malloc(1024)) == NULL) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); return (1); } if (!getcwd(current, 1024)) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory.")); free(current); return (1); } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); free(current); } break; case 'f' : /* Run in foreground... */ fg = 1; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = -1; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd... */ #ifdef HAVE_LAUNCHD Launchd = 1; fg = 1; #else _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " "in, running in normal mode.")); fg = 0; #endif /* HAVE_LAUNCHD */ break; case 'p' : /* Stop immediately for profiling */ fputs("cupsd: -p (startup profiling) is for internal testing " "use only!\n", stderr); stop_scheduler = 1; fg = 1; break; case 'P' : /* Disable security profiles */ fputs("cupsd: -P (disable security profiles) is for internal " "testing use only!\n", stderr); UseProfiles = 0; break; #ifdef __APPLE__ case 'S' : /* Disable system management functions */ fputs("cupsd: -S (disable system management) for internal " "testing use only!\n", stderr); use_sysman = 0; break; #endif /* __APPLE__ */ case 't' : /* Test the cupsd.conf file... */ TestConfigFile = 1; fg = 1; break; default : /* Unknown option */ _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " "aborting."), *opt); usage(1); break; } else { _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting."), argv[i]); usage(1); } if (!ConfigurationFile) cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); /* * If the user hasn't specified "-f", run in the background... */ if (!fg) { /* * Setup signal handlers for the parent... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGUSR1, parent_handler); sigset(SIGCHLD, parent_handler); sigset(SIGHUP, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGUSR1); action.sa_handler = parent_handler; sigaction(SIGUSR1, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGHUP, &action, NULL); #else signal(SIGUSR1, parent_handler); signal(SIGCLD, parent_handler); signal(SIGHUP, SIG_IGN); #endif /* HAVE_SIGSET */ if (fork() > 0) { /* * OK, wait for the child to startup and send us SIGUSR1 or to crash * and the OS send us SIGCHLD... We also need to ignore SIGHUP which * might be sent by the init script to restart the scheduler... */ for (; parent_signal == 0;) sleep(1); if (parent_signal == SIGUSR1) return (0); if (wait(&i) < 0) { perror("cupsd"); return (1); } else if (WIFEXITED(i)) { fprintf(stderr, "cupsd: Child exited with status %d\n", WEXITSTATUS(i)); return (2); } else { fprintf(stderr, "cupsd: Child exited on signal %d\n", WTERMSIG(i)); return (3); } } #ifdef __OpenBSD__ /* * Call _thread_sys_closefrom() so the child process doesn't reset the * parent's file descriptors to be blocking. This is a workaround for a * limitation of userland libpthread on OpenBSD. */ _thread_sys_closefrom(0); #endif /* __OpenBSD__ */ /* * Since CoreFoundation and DBUS both create fork-unsafe data on execution of * a program, and since this kind of really unfriendly behavior seems to be * more common these days in system libraries, we need to re-execute the * background cupsd with the "-C" option to avoid problems. Unfortunately, * we also have to assume that argv[0] contains the name of the cupsd * executable - there is no portable way to get the real pathname... */ execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0); exit(errno); } if (fg < 1) { /* * Make sure we aren't tying up any filesystems... */ chdir("/"); #ifndef DEBUG /* * Disable core dumps... */ getrlimit(RLIMIT_CORE, &limit); limit.rlim_cur = 0; setrlimit(RLIMIT_CORE, &limit); /* * Disconnect from the controlling terminal... */ setsid(); /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < limit.rlim_cur && i < 1024; i ++) close(i); /* * Redirect stdin/out/err to /dev/null... */ if ((i = open("/dev/null", O_RDONLY)) != 0) { dup2(i, 0); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 1) { dup2(i, 1); close(i); } if ((i = open("/dev/null", O_WRONLY)) != 2) { dup2(i, 2); close(i); } #endif /* DEBUG */ } /* * Set the timezone info... */ tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #endif /* LC_TIME */ /* * Set the maximum number of files... */ getrlimit(RLIMIT_NOFILE, &limit); #if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) if (limit.rlim_max > FD_SETSIZE) MaxFDs = FD_SETSIZE; else #endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */ #ifdef RLIM_INFINITY if (limit.rlim_max == RLIM_INFINITY) MaxFDs = 16384; else #endif /* RLIM_INFINITY */ MaxFDs = limit.rlim_max; limit.rlim_cur = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); cupsdStartSelect(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { if (TestConfigFile) printf("%s contains errors\n", ConfigurationFile); else syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } else if (TestConfigFile) { printf("%s is OK\n", ConfigurationFile); return (0); } /* * Clean out old temp files and printer cache data. */ if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) cupsdCleanFiles(TempDir, NULL); cupsdCleanFiles(CacheDir, "*.ipp"); #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ httpInitialize(); cupsdStartServer(); /* * Catch hangup and child signals and ignore broken pipes... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGCHLD, sigchld_handler); sigset(SIGHUP, sighup_handler); sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigchld_handler; sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGHUP); action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */ signal(SIGHUP, sighup_handler); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ #ifdef __sgi /* * Try to create a fake lpsched lock file if one is not already there. * Some Adobe applications need it under IRIX in order to enable * printing... */ if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL) { syslog(LOG_LPR, "Unable to create fake lpsched lock file " "\"/var/spool/lp/SCHEDLOCK\"\' - %s!", strerror(errno)); } else { fchmod(cupsFileNumber(fp), 0644); fchown(cupsFileNumber(fp), User, Group); cupsFileClose(fp); } #endif /* __sgi */ /* * Initialize authentication certificates... */ cupsdInitCerts(); /* * If we are running in the background, signal the parent process that * we are up and running... */ if (!fg || run_as_child) { /* * Send a signal to the parent process, but only if the parent is * not PID 1 (init). This avoids accidentally shutting down the * system on OpenBSD if you CTRL-C the server before it is up... */ i = getppid(); /* Save parent PID to avoid race condition */ if (i != 1) kill(i, SIGUSR1); } #ifdef __APPLE__ /* * Start power management framework... */ if (use_sysman) cupsdStartSystemMonitor(); #endif /* __APPLE__ */ /* * Send server-started event... */ #ifdef HAVE_LAUNCHD if (Launchd) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started via launchd."); else #endif /* HAVE_LAUNCHD */ if (fg) cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in foreground."); else cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in background."); /* * Start any pending print jobs... */ cupsdCheckJobs(); /* * Loop forever... */ current_time = time(NULL); event_time = current_time; expire_time = current_time; fds = 1; report_time = 0; senddoc_time = current_time; while (!stop_scheduler) { /* * Check if there are dead children to handle... */ if (dead_children) process_children(); /* * Check if we need to load the server configuration file... */ if (NeedReload) { /* * Close any idle clients... */ if (cupsArrayCount(Clients) > 0) { for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) if (con->http.state == HTTP_WAITING) cupsdCloseClient(con); else con->http.keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } /* * Restart if all clients are closed and all jobs finished, or * if the reload timeout has elapsed... */ if ((cupsArrayCount(Clients) == 0 && (cupsArrayCount(PrintingJobs) == 0 || NeedReload != RELOAD_ALL)) || (time(NULL) - ReloadTime) >= ReloadTimeout) { /* * Shutdown the server... */ DoingShutdown = 1; cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); break; } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd, get the listen socket file * descriptors... */ launchd_checkin(); launchd_checkout(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ DoingShutdown = 0; cupsdStartServer(); /* * Send a server-restarted event... */ cupsdAddEvent(CUPSD_EVENT_SERVER_RESTARTED, NULL, NULL, "Scheduler restarted."); } } /* * Check for available input or ready output. If cupsdDoSelect() * returns 0 or -1, something bad happened and we should exit * immediately. * * Note that we at least have one listening socket open at all * times. */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; #if HAVE_LAUNCHD /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && Launchd && LaunchdTimeout && !cupsArrayCount(ActiveJobs) && (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; } else launchd_idle_exit = 0; #endif /* HAVE_LAUNCHD */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #ifdef HAVE_DNSSD cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD */ if (errno == EINTR) /* Just interrupted by a signal */ continue; /* * Log all sorts of debug info to help track down the problem. */ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!", strerror(errno)); for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients); con; i ++, con = (cupsd_client_t *)cupsArrayNext(Clients)) cupsdLogMessage(CUPSD_LOG_EMERG, "Clients[%d] = %d, file = %d, state = %d", i, con->http.fd, con->file, con->http.state); for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd); cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]); #ifdef __APPLE__ cupsdLogMessage(CUPSD_LOG_EMERG, "SysEventPipes[0] = %d", SysEventPipes[0]); #endif /* __APPLE__ */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) cupsdLogMessage(CUPSD_LOG_EMERG, "Jobs[%d] = %d < [%d %d] > [%d %d]", job->id, job->status_buffer ? job->status_buffer->fd : -1, job->print_pipes[0], job->print_pipes[1], job->back_pipes[0], job->back_pipes[1]); #ifdef HAVE_DNSSD for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] reg_name=\"%s\"", p->name, p->reg_name ? p->reg_name : "(null)"); #endif /* HAVE_DNSSD */ break; } current_time = time(NULL); /* * Write dirty config/state files... */ if (DirtyCleanTime && current_time >= DirtyCleanTime) cupsdCleanDirty(); #ifdef __APPLE__ /* * If we are going to sleep and still have pending jobs, stop them after * a period of time... */ if (SleepJobs > 0 && current_time >= SleepJobs && cupsArrayCount(PrintingJobs) > 0) { SleepJobs = 0; cupsdStopAllJobs(CUPSD_JOB_DEFAULT, 5); } #endif /* __APPLE__ */ #ifndef __APPLE__ /* * Update the network interfaces once a minute... */ if ((current_time - netif_time) >= 60) { netif_time = current_time; NetIFUpdate = 1; } #endif /* !__APPLE__ */ #if HAVE_LAUNCHD /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ if (!fds && launchd_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " "will restart on demand."); stop_scheduler = 1; break; } #endif /* HAVE_LAUNCHD */ /* * Resume listening for new connections as needed... */ if (ListeningPaused && ListeningPaused <= current_time && cupsArrayCount(Clients) < MaxClients) cupsdResumeListening(); /* * Expire subscriptions and unload completed jobs as needed... */ if (current_time > expire_time) { if (cupsArrayCount(Subscriptions) > 0) cupsdExpireSubscriptions(NULL, NULL); cupsdUnloadCompletedJobs(); expire_time = current_time; } #ifndef HAVE_AUTHORIZATION_H /* * Update the root certificate once every 5 minutes if we have client * connections... */ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration && !RunUser && cupsArrayCount(Clients)) { /* * Update the root certificate... */ cupsdDeleteCert(0); cupsdAddCert(0, "root", NULL); } #endif /* !HAVE_AUTHORIZATION_H */ /* * Check for new data on the client sockets... */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) { /* * Process pending data in the input buffer... */ if (con->http.used) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (con->http.activity < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity...", con->http.fd, Timeout); cupsdCloseClient(con); continue; } } /* * Update any pending multi-file documents... */ if ((current_time - senddoc_time) >= 10) { cupsdCheckJobs(); senddoc_time = current_time; } /* * Clean job history... */ if (JobHistoryUpdate && current_time >= JobHistoryUpdate) cupsdCleanJobs(); /* * Log statistics at most once a minute when in debug mode... */ if ((current_time - report_time) >= 60 && LogLevel >= CUPSD_LOG_DEBUG) { size_t string_count, /* String count */ alloc_bytes, /* Allocated string bytes */ total_bytes; /* Total string bytes */ #ifdef HAVE_MALLINFO struct mallinfo mem; /* Malloc information */ mem = mallinfo(); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-arena=%lu", mem.arena); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-used=%lu", mem.usmblks + mem.uordblks); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-free=%lu", mem.fsmblks + mem.fordblks); #endif /* HAVE_MALLINFO */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: clients=%d", cupsArrayCount(Clients)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs=%d", cupsArrayCount(Jobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs-active=%d", cupsArrayCount(ActiveJobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d", cupsArrayCount(Printers)); string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-string-count=" CUPS_LLFMT, CUPS_LLCAST string_count); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-alloc-bytes=" CUPS_LLFMT, CUPS_LLCAST alloc_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-total-bytes=" CUPS_LLFMT, CUPS_LLCAST total_bytes); report_time = current_time; } /* * Handle OS-specific event notification for any events that have * accumulated. Don't send these more than once a second... */ if (LastEvent && (current_time - event_time) >= 1) { #ifdef HAVE_NOTIFY_POST if (LastEvent & (CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_DELETED | CUPSD_EVENT_PRINTER_MODIFIED)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerListChange\")"); notify_post("com.apple.printerListChange"); } if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerHistoryChange\")"); notify_post("com.apple.printerHistoryChange"); } if (LastEvent & (CUPSD_EVENT_JOB_STATE_CHANGED | CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_PROGRESS)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.jobChange\")"); notify_post("com.apple.jobChange"); } #endif /* HAVE_NOTIFY_POST */ /* * Reset the accumulated events... */ LastEvent = CUPSD_EVENT_NONE; event_time = current_time; } } /* * Log a message based on what happened... */ if (stop_scheduler) { cupsdLogMessage(CUPSD_LOG_INFO, "Scheduler shutting down normally."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down normally."); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Scheduler shutting down due to program error."); cupsdAddEvent(CUPSD_EVENT_SERVER_STOPPED, NULL, NULL, "Scheduler shutting down due to program error."); } /* * Close all network clients... */ DoingShutdown = 1; cupsdStopServer(); #ifdef HAVE_LAUNCHD /* * Update the launchd KeepAlive file as needed... */ if (Launchd) launchd_checkout(); #endif /* HAVE_LAUNCHD */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ if (use_sysman) cupsdStopSystemMonitor(); #endif /* __APPLE__ */ #ifdef HAVE_GSSAPI /* * Free the scheduler's Kerberos context... */ # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ if (KerberosContext) krb5_free_context(KerberosContext); #endif /* HAVE_GSSAPI */ #ifdef __sgi /* * Remove the fake IRIX lpsched lock file, but only if the existing * file is not a FIFO which indicates that the real IRIX lpsched is * running... */ if (!stat("/var/spool/lp/FIFO", &statbuf)) if (!S_ISFIFO(statbuf.st_mode)) unlink("/var/spool/lp/SCHEDLOCK"); #endif /* __sgi */ cupsdStopSelect(); return (!stop_scheduler); }
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!"); }
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!"); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { help_index_t *hi, /* Help index */ *si; /* Search index */ help_node_t *n; /* Current help node */ int i; /* Looping var */ const char *query; /* Search query */ const char *cache_dir; /* CUPS_CACHEDIR environment variable */ const char *docroot; /* CUPS_DOCROOT environment variable */ const char *helpfile, /* Current help file */ *helptitle = NULL; /* Current help title */ const char *topic; /* Current topic */ char topic_data[1024]; /* Topic form data */ const char *section; /* Current section */ char filename[1024], /* Filename */ directory[1024]; /* Directory */ cups_file_t *fp; /* Help file */ char line[1024]; /* Line from file */ int printable; /* Show printable version? */ /* * Get any form variables... */ cgiInitialize(); printable = cgiGetVariable("PRINTABLE") != NULL; /* * Set the web interface section... */ cgiSetVariable("SECTION", "help"); cgiSetVariable("REFRESH_PAGE", ""); /* * Load the help index... */ if ((cache_dir = getenv("CUPS_CACHEDIR")) == NULL) cache_dir = CUPS_CACHEDIR; snprintf(filename, sizeof(filename), "%s/help.index", cache_dir); if ((docroot = getenv("CUPS_DOCROOT")) == NULL) docroot = CUPS_DOCROOT; snprintf(directory, sizeof(directory), "%s/help", docroot); fprintf(stderr, "DEBUG: helpLoadIndex(filename=\"%s\", directory=\"%s\")\n", filename, directory); hi = helpLoadIndex(filename, directory); if (!hi) { perror(filename); cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Unable to load help index."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } fprintf(stderr, "DEBUG: %d nodes in help index...\n", cupsArrayCount(hi->nodes)); /* * See if we are viewing a file... */ for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); if ((helpfile = getenv("PATH_INFO")) != NULL) { helpfile ++; if (!*helpfile) helpfile = NULL; } if (helpfile) { /* * Verify that the help file exists and is part of the index... */ snprintf(filename, sizeof(filename), "%s/help/%s", docroot, helpfile); fprintf(stderr, "DEBUG: helpfile=\"%s\", filename=\"%s\"\n", helpfile, filename); if (access(filename, R_OK)) { perror(filename); cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Unable to access help file."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } if ((n = helpFindNode(hi, helpfile, NULL)) == NULL) { cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Help file not in index."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } /* * Save the page title and help file... */ helptitle = n->text; topic = n->section; /* * Send a standard page header... */ if (printable) puts("Content-Type: text/html;charset=utf-8\n"); else cgiStartHTML(n->text); } else { /* * Send a standard page header... */ cgiStartHTML(cgiText(_("Online Help"))); topic = cgiGetVariable("TOPIC"); } /* * Do a search as needed... */ if (cgiGetVariable("CLEAR")) cgiSetVariable("QUERY", ""); query = cgiGetVariable("QUERY"); si = helpSearchIndex(hi, query, topic, helpfile); cgiClearVariables(); if (query) cgiSetVariable("QUERY", query); if (topic) cgiSetVariable("TOPIC", topic); if (helpfile) cgiSetVariable("HELPFILE", helpfile); if (helptitle) cgiSetVariable("HELPTITLE", helptitle); fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n", query ? query : "(null)", topic ? topic : "(null)"); if (si) { help_node_t *nn; /* Parent node */ fprintf(stderr, "DEBUG: si=%p, si->sorted=%p, cupsArrayCount(si->sorted)=%d\n", si, si->sorted, cupsArrayCount(si->sorted)); for (i = 0, n = (help_node_t *)cupsArrayFirst(si->sorted); n; i ++, n = (help_node_t *)cupsArrayNext(si->sorted)) { if (helpfile && n->anchor) snprintf(line, sizeof(line), "#%s", n->anchor); else if (n->anchor) snprintf(line, sizeof(line), "/help/%s?QUERY=%s#%s", n->filename, query ? query : "", n->anchor); else snprintf(line, sizeof(line), "/help/%s?QUERY=%s", n->filename, query ? query : ""); cgiSetArray("QTEXT", i, n->text); cgiSetArray("QLINK", i, line); if (!helpfile && n->anchor) { nn = helpFindNode(hi, n->filename, NULL); snprintf(line, sizeof(line), "/help/%s?QUERY=%s", nn->filename, query ? query : ""); cgiSetArray("QPTEXT", i, nn->text); cgiSetArray("QPLINK", i, line); } else { cgiSetArray("QPTEXT", i, ""); cgiSetArray("QPLINK", i, ""); } fprintf(stderr, "DEBUG: [%d] = \"%s\" @ \"%s\"\n", i, n->text, line); } helpDeleteIndex(si); } /* * OK, now list the bookmarks within the index... */ for (i = 0, section = NULL, n = (help_node_t *)cupsArrayFirst(hi->sorted); n; n = (help_node_t *)cupsArrayNext(hi->sorted)) { if (n->anchor) continue; /* * Add a section link as needed... */ if (n->section && (!section || strcmp(n->section, section))) { /* * Add a link for this node... */ snprintf(line, sizeof(line), "/help/?TOPIC=%s&QUERY=%s", cgiFormEncode(topic_data, n->section, sizeof(topic_data)), query ? query : ""); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, n->section); cgiSetArray("BMINDENT", i, "0"); i ++; section = n->section; } if (!topic || strcmp(n->section, topic)) continue; /* * Add a link for this node... */ snprintf(line, sizeof(line), "/help/%s?TOPIC=%s&QUERY=%s", n->filename, cgiFormEncode(topic_data, n->section, sizeof(topic_data)), query ? query : ""); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, n->text); cgiSetArray("BMINDENT", i, "1"); i ++; if (helpfile && !strcmp(helpfile, n->filename)) { help_node_t *nn; /* Pointer to sub-node */ cupsArraySave(hi->sorted); for (nn = (help_node_t *)cupsArrayFirst(hi->sorted); nn; nn = (help_node_t *)cupsArrayNext(hi->sorted)) if (nn->anchor && !strcmp(helpfile, nn->filename)) { /* * Add a link for this node... */ snprintf(line, sizeof(line), "#%s", nn->anchor); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, nn->text); cgiSetArray("BMINDENT", i, "2"); i ++; } cupsArrayRestore(hi->sorted); } } /* * Show the search and bookmark content... */ if (!helpfile || !printable) cgiCopyTemplateLang("help-header.tmpl"); else cgiCopyTemplateLang("help-printable.tmpl"); /* * If we are viewing a file, copy it in now... */ if (helpfile) { if ((fp = cupsFileOpen(filename, "r")) != NULL) { int inbody; /* Are we inside the body? */ inbody = 0; while (cupsFileGets(fp, line, sizeof(line))) { if (inbody) { if (!_cups_strncasecmp(line, "</BODY>", 7)) break; printf("%s\n", line); } else if (!_cups_strncasecmp(line, "<BODY", 5)) inbody = 1; } cupsFileClose(fp); } else { perror(filename); cgiSetVariable("ERROR", cgiText(_("Unable to open help file."))); cgiCopyTemplateLang("error.tmpl"); } } /* * Send a standard trailer... */ if (!printable) { cgiCopyTemplateLang("help-trailer.tmpl"); cgiEndHTML(); } else puts("</BODY>\n</HTML>"); /* * Delete the index... */ helpDeleteIndex(hi); /* * Return with no errors... */ return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[] /* I - Command-line arguments */ #ifdef PRINT_AUXV , char* envp[] #endif ) { int i; /* Looping var */ char *opt; /* Option character */ int fg; /* Run in the foreground */ int fds; /* Number of ready descriptors */ cupsd_client_t *con; /* Current client */ cupsd_job_t *job; /* Current job */ cupsd_listener_t *lis; /* Current listener */ time_t current_time, /* Current time */ activity, /* Client activity timer */ browse_time, /* Next browse send time */ senddoc_time, /* Send-Document time */ expire_time, /* Subscription expire time */ report_time, /* Malloc/client/job report time */ event_time; /* Last time an event notification was done */ long timeout; /* Timeout for cupsdDoSelect() */ struct rlimit limit; /* Runtime limit */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ #ifdef __sgi cups_file_t *fp; /* Fake lpsched lock file */ struct stat statbuf; /* Needed for checking lpsched FIFO */ #endif /* __sgi */ #ifdef __APPLE__ int run_as_child = 0; /* Needed for Mac OS X fork/exec */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ #if HAVE_LAUNCHD int launchd_idle_exit; /* Idle exit on select timeout? */ #endif /* HAVE_LAUNCHD */ #ifdef PRINT_AUXV Elf32_auxv_t *auxv; while(*envp++ != NULL); for (auxv = (Elf32_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { if (auxv->a_type == AT_SYSINFO) { printf("AT_RANDOM is 0x%x\n", auxv->a_un.a_val); } } #endif #if UNDERSTAND_CUPS printf("[main.c::main()] cups has just started in main()\n"); #endif int count = 0; int loops_desired = -1; // loop forever unless this is set #ifdef HAVE_GETEUID /* * Check for setuid invocation, which we do not support! */ if (getuid() != geteuid()) { fputs("cupsd: Cannot run as a setuid program!\n", stderr); return (1); } #if UNDERSTAND_CUPS printf("[main.c::main()] uid = %d, euid = %d\n", getuid(), geteuid()); #endif #endif /* HAVE_GETEUID */ /* * Check for command-line arguments... */ #if UNDERSTAND_CUPS printf("[main.c::main()] parsing command line arguments \n"); #endif fg = 0; #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { Launchd = 1; fg = 1; } #endif /* HAVE_LAUNCHD */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-') for (opt = argv[i] + 1; *opt != '\0'; opt ++) switch (*opt) { #ifdef __APPLE__ case 'C' : /* Run as child with config file */ run_as_child = 1; fg = -1; #endif /* __APPLE__ */ case 'c' : /* Configuration file */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("cupsd: Expected config filename " "after \"-c\" option!\n")); usage(1); } if (argv[i][0] == '/') { /* * Absolute directory... */ cupsdSetString(&ConfigurationFile, argv[i]); } else { /* * Relative directory... */ char *current; /* Current directory */ /* * Allocate a buffer for the current working directory to * reduce run-time stack usage; this approximates the * behavior of some implementations of getcwd() when they * are passed a NULL pointer. */ if ((current = malloc(1024)) == NULL) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory!\n")); return (1); } if (!getcwd(current, 1024)) { _cupsLangPuts(stderr, _("cupsd: Unable to get current directory!\n")); free(current); return (1); } cupsdSetStringf(&ConfigurationFile, "%s/%s", current, argv[i]); free(current); } break; case 'f' : /* Run in foreground... */ fg = 1; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ fg = -1; break; case 'h' : /* Show usage/help */ usage(0); break; case 'l' : /* Started by launchd... */ #ifdef HAVE_LAUNCHD Launchd = 1; fg = 1; #else _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " "in, running in normal mode.\n")); fg = 0; #endif /* HAVE_LAUNCHD */ break; case 'p' : /* Stop immediately for profiling */ puts("Warning: -p option is for internal testing use only!"); stop_scheduler = 1; fg = 1; break; /// XXX RAZA case 'x' : /* Number of Iterations to Perform */ i ++; loops_desired = atoi(argv[i]); break; default : /* Unknown option */ _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " "aborting!\n"), *opt); usage(1); break; } else { _cupsLangPrintf(stderr, _("cupsd: Unknown argument \"%s\" - aborting!\n"), argv[i]); usage(1); } #if UNDERSTAND_CUPS printf("[main.c::main()] done parsing command line arguments \n"); printf("[main.c::main()] num_loops = %d, foreground = %d\n", loops_desired, fg); #endif if (!ConfigurationFile) cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); printf("[main.c::main()] configuration file = %s\n", ConfigurationFile); /* * If the user hasn't specified "-f", run in the background... */ if (!fg) { /* * Setup signal handlers for the parent... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGUSR1, parent_handler); sigset(SIGCHLD, parent_handler); sigset(SIGHUP, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGUSR1); action.sa_handler = parent_handler; sigaction(SIGUSR1, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGHUP, &action, NULL); #else signal(SIGUSR1, parent_handler); signal(SIGCLD, parent_handler); signal(SIGHUP, SIG_IGN); #endif /* HAVE_SIGSET */ if (fork() > 0) { /* * OK, wait for the child to startup and send us SIGUSR1 or to crash * and the OS send us SIGCHLD... We also need to ignore SIGHUP which * might be sent by the init script to restart the scheduler... */ for (; parent_signal == 0;) sleep(1); if (parent_signal == SIGUSR1) return (0); if (wait(&i) < 0) { perror("cupsd"); return (1); } else if (WIFEXITED(i)) { fprintf(stderr, "cupsd: Child exited with status %d!\n", WEXITSTATUS(i)); return (2); } else { fprintf(stderr, "cupsd: Child exited on signal %d!\n", WTERMSIG(i)); return (3); } } #ifdef __APPLE__ /* * Since CoreFoundation has an overly-agressive check for whether a * process has forked but not exec'd (whether CF has been called or * not...), we now have to exec ourselves with the "-f" option to * eliminate their bogus warning messages. */ execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0); exit(errno); #endif /* __APPLE__ */ } if (fg < 1) { /* * Make sure we aren't tying up any filesystems... */ chdir("/"); #ifndef DEBUG /* * Disable core dumps... */ getrlimit(RLIMIT_CORE, &limit); limit.rlim_cur = 0; setrlimit(RLIMIT_CORE, &limit); /* * Disconnect from the controlling terminal... */ setsid(); /* * Close all open files... */ getrlimit(RLIMIT_NOFILE, &limit); for (i = 0; i < limit.rlim_cur && i < 1024; i ++) close(i); #endif /* DEBUG */ } /* * Set the timezone info... */ #if UNDERSTAND_CUPS printf("[main.c::main()] setting timezone info, tzset()\n"); #endif tzset(); #ifdef LC_TIME setlocale(LC_TIME, ""); #if UNDERSTAND_CUPS printf("[main.c::main()] setting locale info, setlocale()\n"); #endif #endif /* LC_TIME */ /* * Set the maximum number of files... */ getrlimit(RLIMIT_NOFILE, &limit); #if !defined(HAVE_POLL) && !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) if (limit.rlim_max > FD_SETSIZE) MaxFDs = FD_SETSIZE; else #endif /* !HAVE_POLL && !HAVE_EPOLL && !HAVE_KQUEUE */ #ifdef RLIM_INFINITY if (limit.rlim_max == RLIM_INFINITY) MaxFDs = 16384; else #endif /* RLIM_INFINITY */ MaxFDs = limit.rlim_max; limit.rlim_cur = MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); #if UNDERSTAND_CUPS printf("[main.c::main()] set the maximum nuber of files = %d\n", MaxFDs); #endif cupsdStartSelect(); #if UNDERSTAND_CUPS printf("[main.c::main()] done with cupsdStartSelect() i.e. polling engine\n"); #endif /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); return (1); } printf("[main.c::main()] done with cupsdReadConfiguration\n"); if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot))) { /* * Clean out the temporary directory... */ cups_dir_t *dir; /* Temporary directory */ cups_dentry_t *dent; /* Directory entry */ char tempfile[1024]; /* Temporary filename */ printf("[main.c::main()] cleaning temp dir = %s\n", TempDir); if ((dir = cupsDirOpen(TempDir)) != NULL) { cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old temporary files in \"%s\"...", TempDir); while ((dent = cupsDirRead(dir)) != NULL) { snprintf(tempfile, sizeof(tempfile), "%s/%s", TempDir, dent->filename); printf("[main.c::main()] deleting temp file = %s\n", tempfile); if (cupsdRemoveFile(tempfile)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove temporary file \"%s\" - %s", tempfile, strerror(errno)); printf("[main.c::main()] failed in deleting temp file = %s\n", tempfile); } else { cupsdLogMessage(CUPSD_LOG_DEBUG, "Removed temporary file \"%s\"...", tempfile); printf("[main.c::main()] deleted temp file = %s\n", tempfile); } } cupsDirClose(dir); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open temporary directory \"%s\" - %s", TempDir, strerror(errno)); printf("[main.c::main()] couldn't open temp dir = %s\n", TempDir); } printf("[main.c::main()] DONE cleaning temp dir = %s\n", TempDir); } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ printf("[main.c::main()] launchd check in \n"); launchd_checkin(); } #endif /* HAVE_LAUNCHD */ #if defined(__APPLE__) && defined(HAVE_DLFCN_H) /* * Load Print Service quota enforcement library (X Server only) */ PSQLibRef = dlopen(PSQLibPath, RTLD_LAZY); if (PSQLibRef) PSQUpdateQuotaProc = dlsym(PSQLibRef, PSQLibFuncName); #endif /* __APPLE__ && HAVE_DLFCN_H */ #ifdef HAVE_GSSAPI # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ /* * Setup a Kerberos context for the scheduler to use... */ if (krb5_init_context(&KerberosContext)) { KerberosContext = NULL; printf("[main.c::main()] unable to use krb5_init_context() \n"); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context"); } else { printf("[main.c::main()] used krb5_init_context() \n"); } #endif /* HAVE_GSSAPI */ /* * Startup the server... */ cupsdStartServer(); /* * Catch hangup and child signals and ignore broken pipes... */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGCHLD, sigchld_handler); sigset(SIGHUP, sighup_handler); sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); printf("[main.c::main()] used system V signals over POSIX\n"); #elif defined(HAVE_SIGACTION) printf("[main.c::main()] used HAVE_SIGACTION\n"); memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigchld_handler; sigaction(SIGCHLD, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGHUP); action.sa_handler = sighup_handler; sigaction(SIGHUP, &action, NULL); sigemptyset(&action.sa_mask); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGCHLD); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else printf("[main.c::main()]last signal options\n"); signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */ signal(SIGHUP, sighup_handler); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ #ifdef __sgi /* * Try to create a fake lpsched lock file if one is not already there. * Some Adobe applications need it under IRIX in order to enable * printing... */ printf("[main.c::main()] creating fake lpsched lock file \n"); if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL) { syslog(LOG_LPR, "Unable to create fake lpsched lock file " "\"/var/spool/lp/SCHEDLOCK\"\' - %s!", strerror(errno)); } else { fchmod(cupsFileNumber(fp), 0644); fchown(cupsFileNumber(fp), User, Group); cupsFileClose(fp); } #endif /* __sgi */ /* * Initialize authentication certificates... */ cupsdInitCerts(); /* * If we are running in the background, signal the parent process that * we are up and running... */ #ifdef __APPLE__ if (!fg || run_as_child) #else if (!fg) #endif /* __APPLE__ */ { /* * Send a signal to the parent process, but only if the parent is * not PID 1 (init). This avoids accidentally shutting down the * system on OpenBSD if you CTRL-C the server before it is up... */ i = getppid(); /* Save parent PID to avoid race condition */ if (i != 1) kill(i, SIGUSR1); } #ifdef __APPLE__ /* * Start power management framework... */ printf("[main.c::main()] starting system monitor (power management) \n"); cupsdStartSystemMonitor(); #endif /* __APPLE__ */ /* * Start any pending print jobs... */ printf("[main.c::main()] starting any pending print jobs \n"); cupsdCheckJobs(); /* * Loop forever... */ current_time = time(NULL); browse_time = current_time; event_time = current_time; expire_time = current_time; fds = 1; report_time = 0; senddoc_time = current_time; while (!stop_scheduler) { // XXX RAZA printf("[main.c::main()] scheduler loop # %d\n", count); if (count++ == loops_desired) { printf("[main.c::main()] stopping scheduler loop\n"); stop_scheduler = 1; continue; } printf("[main.c::main()] Top of loop, dead_children=%d, NeedReload=%d\n", dead_children, NeedReload); #ifdef DEBUG cupsdLogMessage(CUPSD_LOG_DEBUG2, "main: Top of loop, dead_children=%d, NeedReload=%d", dead_children, NeedReload); #endif /* DEBUG */ /* * Check if there are dead children to handle... */ if (dead_children) process_children(); /* * Check if we need to load the server configuration file... */ if (NeedReload) { /* * Close any idle clients... */ if (cupsArrayCount(Clients) > 0) { for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) if (con->http.state == HTTP_WAITING) cupsdCloseClient(con); else con->http.keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } /* * Check for any active jobs... */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) if (job->state_value == IPP_JOB_PROCESSING) break; /* * Restart if all clients are closed and all jobs finished, or * if the reload timeout has elapsed... */ if ((cupsArrayCount(Clients) == 0 && (!job || NeedReload != RELOAD_ALL)) || (time(NULL) - ReloadTime) >= ReloadTimeout) { /* * Shutdown the server... */ cupsdStopServer(); /* * Read configuration... */ if (!cupsdReadConfiguration()) { syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", ConfigurationFile); break; } #if HAVE_LAUNCHD if (Launchd) { /* * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); } #endif /* HAVE_LAUNCHD */ /* * Startup the server... */ cupsdStartServer(); } } /* * Check for available input or ready output. If cupsdDoSelect() * returns 0 or -1, something bad happened and we should exit * immediately. * * Note that we at least have one listening socket open at all * times. */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; #if HAVE_LAUNCHD /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled && !cupsArrayCount(ActiveJobs) && (!Browsing || (!BrowseRemoteProtocols && (!NumBrowsers || !BrowseLocalProtocols || cupsArrayCount(Printers) == 0)))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; } else launchd_idle_exit = 0; #endif /* HAVE_LAUNCHD */ if ((fds = cupsdDoSelect(timeout)) < 0) { /* * Got an error from select! */ #ifdef HAVE_DNSSD cupsd_printer_t *p; /* Current printer */ #endif /* HAVE_DNSSD */ if (errno == EINTR) /* Just interrupted by a signal */ continue; /* * Log all sorts of debug info to help track down the problem. */ cupsdLogMessage(CUPSD_LOG_EMERG, "cupsdDoSelect() failed - %s!", strerror(errno)); for (i = 0, con = (cupsd_client_t *)cupsArrayFirst(Clients); con; i ++, con = (cupsd_client_t *)cupsArrayNext(Clients)) cupsdLogMessage(CUPSD_LOG_EMERG, "Clients[%d] = %d, file = %d, state = %d", i, con->http.fd, con->file, con->http.state); for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd); cupsdLogMessage(CUPSD_LOG_EMERG, "BrowseSocket = %d", BrowseSocket); cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]); #ifdef __APPLE__ cupsdLogMessage(CUPSD_LOG_EMERG, "SysEventPipes[0] = %d", SysEventPipes[0]); #endif /* __APPLE__ */ for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) cupsdLogMessage(CUPSD_LOG_EMERG, "Jobs[%d] = %d < [%d %d] > [%d %d]", job->id, job->status_buffer ? job->status_buffer->fd : -1, job->print_pipes[0], job->print_pipes[1], job->back_pipes[0], job->back_pipes[1]); #ifdef HAVE_DNSSD for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) cupsdLogMessage(CUPSD_LOG_EMERG, "printer[%s] %d", p->name, p->dnssd_ipp_fd); #endif /* HAVE_DNSSD */ break; } current_time = time(NULL); #ifndef __APPLE__ /* * Update the network interfaces once a minute... */ if ((current_time - netif_time) >= 60) { netif_time = current_time; NetIFUpdate = 1; } #endif /* !__APPLE__ */ #if HAVE_LAUNCHD /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ if (!fds && launchd_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " "will restart on demand."); stop_scheduler = 1; break; } #endif /* HAVE_LAUNCHD */ /* * Resume listening for new connections as needed... */ if (ListeningPaused && ListeningPaused <= current_time && cupsArrayCount(Clients) < MaxClients) cupsdResumeListening(); /* * Expire subscriptions and unload completed jobs as needed... */ if (current_time > expire_time) { if (cupsArrayCount(Subscriptions) > 0) cupsdExpireSubscriptions(NULL, NULL); cupsdUnloadCompletedJobs(); expire_time = current_time; } /* * Update the browse list as needed... */ if (Browsing) { #ifdef HAVE_LIBSLP if ((BrowseRemoteProtocols & BROWSE_SLP) && BrowseSLPRefresh <= current_time) cupsdUpdateSLPBrowse(); #endif /* HAVE_LIBSLP */ #ifdef HAVE_LDAP if ((BrowseRemoteProtocols & BROWSE_LDAP) && BrowseLDAPRefresh <= current_time) cupsdUpdateLDAPBrowse(); #endif /* HAVE_LDAP */ } if (Browsing && current_time > browse_time) { cupsdSendBrowseList(); browse_time = current_time; } /* * Update the root certificate once every 5 minutes if we have client * connections... */ if ((current_time - RootCertTime) >= RootCertDuration && RootCertDuration && !RunUser && cupsArrayCount(Clients)) { /* * Update the root certificate... */ cupsdDeleteCert(0); cupsdAddCert(0, "root", NULL); } /* * Check for new data on the client sockets... */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) { /* * Process pending data in the input buffer... */ if (con->http.used) { cupsdReadClient(con); continue; } /* * Check the activity and close old clients... */ activity = current_time - Timeout; if (con->http.activity < activity && !con->pipe_pid) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity...", con->http.fd, Timeout); cupsdCloseClient(con); continue; } } /* * Update any pending multi-file documents... */ if ((current_time - senddoc_time) >= 10) { cupsdCheckJobs(); senddoc_time = current_time; } /* * Log statistics at most once a minute when in debug mode... */ if ((current_time - report_time) >= 60 && LogLevel >= CUPSD_LOG_DEBUG) { size_t string_count, /* String count */ alloc_bytes, /* Allocated string bytes */ total_bytes; /* Total string bytes */ #ifdef HAVE_MALLINFO struct mallinfo mem; /* Malloc information */ mem = mallinfo(); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-arena=%lu", mem.arena); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-used=%lu", mem.usmblks + mem.uordblks); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: malloc-free=%lu", mem.fsmblks + mem.fordblks); #endif /* HAVE_MALLINFO */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: clients=%d", cupsArrayCount(Clients)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs=%d", cupsArrayCount(Jobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: jobs-active=%d", cupsArrayCount(ActiveJobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d", cupsArrayCount(Printers)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers-implicit=%d", cupsArrayCount(ImplicitPrinters)); string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-string-count=" CUPS_LLFMT, CUPS_LLCAST string_count); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-alloc-bytes=" CUPS_LLFMT, CUPS_LLCAST alloc_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: stringpool-total-bytes=" CUPS_LLFMT, CUPS_LLCAST total_bytes); report_time = current_time; } /* * Handle OS-specific event notification for any events that have * accumulated. Don't send these more than once a second... */ if (LastEvent && (current_time - event_time) >= 1) { #ifdef HAVE_NOTIFY_POST if (LastEvent & (CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_DELETED | CUPSD_EVENT_PRINTER_MODIFIED)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerListChange\")"); notify_post("com.apple.printerListChange"); } if (LastEvent & CUPSD_EVENT_PRINTER_STATE_CHANGED) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.printerHistoryChange\")"); notify_post("com.apple.printerHistoryChange"); } if (LastEvent & (CUPSD_EVENT_JOB_STATE_CHANGED | CUPSD_EVENT_JOB_CONFIG_CHANGED | CUPSD_EVENT_JOB_PROGRESS)) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "notify_post(\"com.apple.jobChange\")"); notify_post("com.apple.jobChange"); } #endif /* HAVE_NOTIFY_POST */ /* * Reset the accumulated events... */ LastEvent = CUPSD_EVENT_NONE; event_time = current_time; } } /* * Log a message based on what happened... */ if (stop_scheduler) cupsdLogMessage(CUPSD_LOG_INFO, "Scheduler shutting down normally."); else cupsdLogMessage(CUPSD_LOG_ERROR, "Scheduler shutting down due to program error."); /* * Close all network clients... */ cupsdStopServer(); #ifdef HAVE_LAUNCHD /* * Update the launchd KeepAlive file as needed... */ if (Launchd) launchd_checkout(); #endif /* HAVE_LAUNCHD */ /* * Stop all jobs... */ cupsdFreeAllJobs(); #ifdef __APPLE__ /* * Stop monitoring system event monitoring... */ cupsdStopSystemMonitor(); #endif /* __APPLE__ */ #ifdef HAVE_GSSAPI /* * Free the scheduler's Kerberos context... */ # ifdef __APPLE__ /* * If the weak-linked GSSAPI/Kerberos library is not present, don't try * to use it... */ if (krb5_init_context != NULL) # endif /* __APPLE__ */ if (KerberosContext) krb5_free_context(KerberosContext); #endif /* HAVE_GSSAPI */ #ifdef __APPLE__ #ifdef HAVE_DLFCN_H /* * Unload Print Service quota enforcement library (X Server only) */ PSQUpdateQuotaProc = NULL; if (PSQLibRef) { dlclose(PSQLibRef); PSQLibRef = NULL; } #endif /* HAVE_DLFCN_H */ #endif /* __APPLE__ */ #ifdef __sgi /* * Remove the fake IRIX lpsched lock file, but only if the existing * file is not a FIFO which indicates that the real IRIX lpsched is * running... */ if (!stat("/var/spool/lp/FIFO", &statbuf)) if (!S_ISFIFO(statbuf.st_mode)) unlink("/var/spool/lp/SCHEDLOCK"); #endif /* __sgi */ cupsdStopSelect(); return (!stop_scheduler); }
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); }
static void mime_load_convs( mime_t *mime, /* I - MIME database */ const char *filename, /* I - Convs file to load */ const char *filterpath, /* I - Path for filters */ cups_array_t *filtercache) /* I - Filter program cache */ { cups_file_t *fp; /* Convs file */ char line[1024], /* Input line from file */ *lineptr, /* Current position in line */ super[MIME_MAX_SUPER], /* Super-type name */ type[MIME_MAX_TYPE], /* Type name */ *temp, /* Temporary pointer */ *filter; /* Filter program */ mime_type_t *temptype, /* MIME type looping var */ *dsttype; /* Destination MIME type */ int cost; /* Cost of filter */ DEBUG_printf(("2mime_load_convs(mime=%p, filename=\"%s\", filterpath=\"%s\", " "filtercache=%p)", mime, filename, filterpath, filtercache)); /* * First try to open the file... */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { DEBUG_printf(("3mime_load_convs: Unable to open \"%s\": %s", filename, strerror(errno))); _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); return; } /* * Then read each line from the file, skipping any comments in the file... */ while (cupsFileGets(fp, line, sizeof(line)) != NULL) { /* * Skip blank lines and lines starting with a #... */ if (!line[0] || line[0] == '#') continue; /* * Strip trailing whitespace... */ for (lineptr = line + strlen(line) - 1; lineptr >= line && isspace(*lineptr & 255); lineptr --) *lineptr = '\0'; /* * Extract the destination super-type and type names from the middle of * the line. */ lineptr = line; while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') lineptr ++; while (*lineptr == ' ' || *lineptr == '\t') lineptr ++; temp = super; while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; if (*lineptr != '/') continue; lineptr ++; temp = type; while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; if (*lineptr == '\0' || *lineptr == '\n') continue; if ((dsttype = mimeType(mime, super, type)) == NULL) { DEBUG_printf(("3mime_load_convs: Destination type %s/%s not found.", super, type)); continue; } /* * Then get the cost and filter program... */ while (*lineptr == ' ' || *lineptr == '\t') lineptr ++; if (*lineptr < '0' || *lineptr > '9') continue; cost = atoi(lineptr); while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0') lineptr ++; while (*lineptr == ' ' || *lineptr == '\t') lineptr ++; if (*lineptr == '\0' || *lineptr == '\n') continue; filter = lineptr; if (strcmp(filter, "-")) { /* * Verify that the filter exists and is executable... */ if (!mime_add_fcache(filtercache, filter, filterpath)) { DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, filterpath)); _mimeError(mime, "Filter \"%s\" not found.", filter); continue; } } /* * Finally, get the source super-type and type names from the beginning of * the line. We do it here so we can support wildcards... */ lineptr = line; temp = super; while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; if (*lineptr != '/') continue; lineptr ++; temp = type; while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; if (!strcmp(super, "*") && !strcmp(type, "*")) { /* * Force * / * to be "application/octet-stream"... */ strlcpy(super, "application", sizeof(super)); strlcpy(type, "octet-stream", sizeof(type)); } /* * Add the filter to the MIME database, supporting wildcards as needed... */ for (temptype = (mime_type_t *)cupsArrayFirst(mime->types); temptype; temptype = (mime_type_t *)cupsArrayNext(mime->types)) if ((super[0] == '*' || !strcmp(temptype->super, super)) && (type[0] == '*' || !strcmp(temptype->type, type))) mimeAddFilter(mime, temptype, dsttype, cost, filter); } cupsFileClose(fp); }
static int /* O - Status */ random_tests(void) { int status, /* Status of tests */ pass, /* Current pass */ count, /* Number of records read */ record, /* Current record */ num_records; /* Number of records */ ssize_t pos, /* Position in file */ expected; /* Expected position in file */ cups_file_t *fp; /* File */ char buffer[512]; /* Data buffer */ /* * Run 4 passes, each time appending to a data file and then reopening the * file for reading to validate random records in the file. */ for (status = 0, pass = 0; pass < 4; pass ++) { /* * cupsFileOpen(append) */ printf("\ncupsFileOpen(append %d): ", pass); if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileTell() */ expected = 256 * sizeof(buffer) * pass; fputs("cupsFileTell(): ", stdout); if ((pos = cupsFileTell(fp)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else puts("PASS"); /* * cupsFileWrite() */ fputs("cupsFileWrite(256 512-byte records): ", stdout); for (record = 0; record < 256; record ++) { memset(buffer, record, sizeof(buffer)); if (cupsFileWrite(fp, buffer, sizeof(buffer)) < sizeof(buffer)) break; } if (record < 256) { printf("FAIL (%d: %s)\n", record, strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileTell() */ expected += 256 * sizeof(buffer); fputs("cupsFileTell(): ", stdout); if ((pos = cupsFileTell(fp)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else puts("PASS"); cupsFileClose(fp); /* * cupsFileOpen(read) */ printf("\ncupsFileOpen(read %d): ", pass); if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileSeek, cupsFileRead */ fputs("cupsFileSeek(), cupsFileRead(): ", stdout); for (num_records = (pass + 1) * 256, count = (pass + 1) * 256, record = CUPS_RAND() % num_records; count > 0; count --, record = (record + (CUPS_RAND() & 31) - 16 + num_records) % num_records) { /* * The last record is always the first... */ if (count == 1) record = 0; /* * Try reading the data for the specified record, and validate the * contents... */ expected = sizeof(buffer) * record; if ((pos = cupsFileSeek(fp, expected)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else { if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer)) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else if ((buffer[0] & 255) != (record & 255) || memcmp(buffer, buffer + 1, sizeof(buffer) - 1)) { printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255, record & 255); status ++; break; } } } if (count == 0) puts("PASS"); cupsFileClose(fp); } /* * Remove the test file... */ unlink("testfile.dat"); /* * Return the test status... */ return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int status; /* Exit status */ char filename[1024]; /* Filename buffer */ cups_file_t *fp; /* File pointer */ #ifndef WIN32 int fds[2]; /* Open file descriptors */ cups_file_t *fdfile; /* File opened with cupsFileOpenFd() */ #endif /* !WIN32 */ int count; /* Number of lines in file */ if (argc == 1) { /* * Do uncompressed file tests... */ status = read_write_tests(0); #ifdef HAVE_LIBZ /* * Do compressed file tests... */ putchar('\n'); status += read_write_tests(1); #endif /* HAVE_LIBZ */ /* * Do uncompressed random I/O tests... */ status += random_tests(); #ifndef WIN32 /* * Test fdopen and close without reading... */ pipe(fds); close(fds[1]); fputs("\ncupsFileOpenFd(fd, \"r\"): ", stdout); fflush(stdout); if ((fdfile = cupsFileOpenFd(fds[0], "r")) == NULL) { puts("FAIL"); status ++; } else { /* * Able to open file, now close without reading. If we don't return * before the alarm fires, that is a failure and we will crash on the * alarm signal... */ puts("PASS"); fputs("cupsFileClose(no read): ", stdout); fflush(stdout); alarm(5); cupsFileClose(fdfile); alarm(0); puts("PASS"); } #endif /* !WIN32 */ /* * Count lines in psglyphs, rewind, then count again. */ fputs("\ncupsFileOpen(\"../data/media.defs\", \"r\"): ", stdout); if ((fp = cupsFileOpen("../data/media.defs", "r")) == NULL) { puts("FAIL"); status ++; } else { puts("PASS"); fputs("cupsFileGets: ", stdout); if ((count = count_lines(fp)) != 208) { printf("FAIL (got %d lines, expected 208)\n", count); status ++; } else { puts("PASS"); fputs("cupsFileRewind: ", stdout); if (cupsFileRewind(fp) != 0) { puts("FAIL"); status ++; } else { puts("PASS"); fputs("cupsFileGets: ", stdout); if ((count = count_lines(fp)) != 208) { printf("FAIL (got %d lines, expected 208)\n", count); status ++; } else puts("PASS"); } } cupsFileClose(fp); } /* * Test path functions... */ fputs("\ncupsFileFind: ", stdout); #ifdef WIN32 if (cupsFileFind("notepad.exe", "C:/WINDOWS", 1, filename, sizeof(filename)) && cupsFileFind("notepad.exe", "C:/WINDOWS;C:/WINDOWS/SYSTEM32", 1, filename, sizeof(filename))) #else if (cupsFileFind("cat", "/bin", 1, filename, sizeof(filename)) && cupsFileFind("cat", "/bin:/usr/bin", 1, filename, sizeof(filename))) #endif /* WIN32 */ printf("PASS (%s)\n", filename); else { puts("FAIL"); status ++; } /* * Summarize the results and return... */ if (!status) puts("\nALL TESTS PASSED!"); else printf("\n%d TEST(S) FAILED!\n", status); } else { /* * Cat the filename on the command-line... */ char line[1024]; /* Line from file */ if ((fp = cupsFileOpen(argv[1], "r")) == NULL) { perror(argv[1]); status = 1; } else { status = 0; while (cupsFileGets(fp, line, sizeof(line))) puts(line); if (!cupsFileEOF(fp)) perror(argv[1]); cupsFileClose(fp); } } return (status); }
int /* O - 1 if log file open */ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ const char *logname) /* I - Log filename */ { char backname[1024], /* Backup log filename */ filename[1024], /* Formatted log filename */ *ptr; /* Pointer into filename */ const char *logptr; /* Pointer into log filename */ /* * See if we have a log file to check... */ if (!lf || !logname || !logname[0]) return (1); /* * Handle logging to stderr... */ if (!strcmp(logname, "stderr")) { *lf = LogStderr; return (1); } /* * Format the filename as needed... */ if (!*lf || (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize && MaxLogSize > 0)) { /* * Handle format strings... */ filename[sizeof(filename) - 1] = '\0'; if (logname[0] != '/') { strlcpy(filename, ServerRoot, sizeof(filename)); strlcat(filename, "/", sizeof(filename)); } else filename[0] = '\0'; for (logptr = logname, ptr = filename + strlen(filename); *logptr && ptr < (filename + sizeof(filename) - 1); logptr ++) if (*logptr == '%') { /* * Format spec... */ logptr ++; if (*logptr == 's') { /* * Insert the server name... */ strlcpy(ptr, ServerName, sizeof(filename) - (size_t)(ptr - filename)); ptr += strlen(ptr); } else { /* * Otherwise just insert the character... */ *ptr++ = *logptr; } } else *ptr++ = *logptr; *ptr = '\0'; } /* * See if the log file is open... */ if (!*lf) { /* * Nope, open the log file... */ if ((*lf = cupsFileOpen(filename, "a")) == NULL) { /* * If the file is in CUPS_LOGDIR then try to create a missing directory... */ if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR))) { /* * Try updating the permissions of the containing log directory, using * the log file permissions as a basis... */ mode_t log_dir_perm = (mode_t)(0300 | LogFilePerm); /* LogFilePerm + owner write/search */ if (log_dir_perm & 0040) log_dir_perm |= 0010; /* Add group search */ if (log_dir_perm & 0004) log_dir_perm |= 0001; /* Add other search */ cupsdCheckPermissions(CUPS_LOGDIR, NULL, log_dir_perm, RunUser, Group, 1, -1); *lf = cupsFileOpen(filename, "a"); } if (*lf == NULL) { #ifdef HAVE_SYSTEMD_SD_JOURNAL_H sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); #else syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ if (FatalErrors & CUPSD_FATAL_LOG) cupsdEndProcess(getpid(), 0); return (0); } } if (strncmp(filename, "/dev/", 5)) { /* * Change ownership and permissions of non-device logs... */ fchown(cupsFileNumber(*lf), RunUser, Group); fchmod(cupsFileNumber(*lf), LogFilePerm); } } /* * Do we need to rotate the log? */ if (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize && MaxLogSize > 0) { /* * Rotate log file... */ cupsFileClose(*lf); strlcpy(backname, filename, sizeof(backname)); strlcat(backname, ".O", sizeof(backname)); unlink(backname); rename(filename, backname); if ((*lf = cupsFileOpen(filename, "a")) == NULL) { #ifdef HAVE_SYSTEMD_SD_JOURNAL_H sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); #else syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ if (FatalErrors & CUPSD_FATAL_LOG) cupsdEndProcess(getpid(), 0); return (0); } /* * Change ownership and permissions of non-device logs... */ fchown(cupsFileNumber(*lf), RunUser, Group); fchmod(cupsFileNumber(*lf), LogFilePerm); } return (1); }
static void print_file(http_t *http, /* I - Connection to destination */ cups_dest_t *dest, /* I - Destination */ cups_dinfo_t *dinfo, /* I - Destination information */ const char *filename, /* I - File to print */ int num_options, /* I - Number of options */ cups_option_t *options) /* I - Options */ { cups_file_t *fp; /* File to print */ int job_id; /* Job ID */ ipp_status_t status; /* Submission status */ const char *title; /* Title of job */ char buffer[32768]; /* File buffer */ ssize_t bytes; /* Bytes read/to write */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { printf("Unable to open \"%s\": %s\n", filename, strerror(errno)); return; } if ((title = strrchr(filename, '/')) != NULL) title ++; else title = filename; if ((status = cupsCreateDestJob(http, dest, dinfo, &job_id, title, num_options, options)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) { printf("Unable to create job: %s\n", cupsLastErrorString()); cupsFileClose(fp); return; } printf("Created job ID: %d\n", job_id); if (cupsStartDestDocument(http, dest, dinfo, job_id, title, CUPS_FORMAT_AUTO, 0, NULL, 1) != HTTP_STATUS_CONTINUE) { printf("Unable to send document: %s\n", cupsLastErrorString()); cupsFileClose(fp); return; } while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) { if (cupsWriteRequestData(http, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE) { printf("Unable to write document data: %s\n", cupsLastErrorString()); break; } } cupsFileClose(fp); if ((status = cupsFinishDestDocument(http, dest, dinfo)) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) { printf("Unable to send document: %s\n", cupsLastErrorString()); return; } puts("Job queued."); }
static int /* O - Number of options or -1 on error */ get_printer(http_t *http, /* I - HTTP connection */ const char *name, /* I - Printer name from request */ char *dest, /* I - Destination buffer */ size_t destsize, /* I - Size of destination buffer */ cups_option_t **options, /* O - Printer options */ int *accepting, /* O - printer-is-accepting-jobs value */ int *shared, /* O - printer-is-shared value */ ipp_pstate_t *state) /* O - printer-state value */ { int num_options; /* Number of options */ cups_file_t *fp; /* lpoptions file */ char line[1024], /* Line from lpoptions file */ *value, /* Pointer to value on line */ *optptr; /* Pointer to options on line */ int linenum; /* Line number in file */ const char *cups_serverroot; /* CUPS_SERVERROOT env var */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ char uri[HTTP_MAX_URI]; /* Printer URI */ static const char * const requested[] = { /* Requested attributes */ "printer-info", "printer-is-accepting-jobs", "printer-is-shared", "printer-name", "printer-state" }; /* * Initialize everything... */ if (accepting) *accepting = 0; if (shared) *shared = 0; if (state) *state = IPP_PRINTER_STOPPED; if (options) *options = NULL; /* * See if the name is a queue name optionally with an instance name. */ strlcpy(dest, name, destsize); if ((value = strchr(dest, '/')) != NULL) *value = '\0'; /* * Setup the Get-Printer-Attributes request... */ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", dest); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested) / sizeof(requested[0])), NULL, requested); /* * Do the request... */ response = cupsDoRequest(http, request, "/"); if (!response || cupsLastError() > IPP_OK_CONFLICT) { /* * If we can't find the printer by name, look up the printer-name * using the printer-info values... */ ipp_attribute_t *accepting_attr,/* printer-is-accepting-jobs */ *info_attr, /* printer-info */ *name_attr, /* printer-name */ *shared_attr, /* printer-is-shared */ *state_attr; /* printer-state */ ippDelete(response); /* * Setup the CUPS-Get-Printers request... */ request = ippNewRequest(CUPS_GET_PRINTERS); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested) / sizeof(requested[0])), NULL, requested); /* * Do the request... */ response = cupsDoRequest(http, request, "/"); if (!response || cupsLastError() > IPP_OK_CONFLICT) { syslog(LOG_ERR, "Unable to get list of printers - %s", cupsLastErrorString()); ippDelete(response); return (-1); } /* * Scan the response for printers... */ *dest = '\0'; attr = response->attrs; while (attr) { /* * Skip to the next printer... */ while (attr && attr->group_tag != IPP_TAG_PRINTER) attr = attr->next; if (!attr) break; /* * Get all of the attributes for the current printer... */ accepting_attr = NULL; info_attr = NULL; name_attr = NULL; shared_attr = NULL; state_attr = NULL; while (attr && attr->group_tag == IPP_TAG_PRINTER) { if (!strcmp(attr->name, "printer-is-accepting-jobs") && attr->value_tag == IPP_TAG_BOOLEAN) accepting_attr = attr; else if (!strcmp(attr->name, "printer-info") && attr->value_tag == IPP_TAG_TEXT) info_attr = attr; else if (!strcmp(attr->name, "printer-name") && attr->value_tag == IPP_TAG_NAME) name_attr = attr; else if (!strcmp(attr->name, "printer-is-shared") && attr->value_tag == IPP_TAG_BOOLEAN) shared_attr = attr; else if (!strcmp(attr->name, "printer-state") && attr->value_tag == IPP_TAG_ENUM) state_attr = attr; attr = attr->next; } if (info_attr && name_attr && !_cups_strcasecmp(name, info_attr->values[0].string.text)) { /* * Found a match, use this one! */ strlcpy(dest, name_attr->values[0].string.text, destsize); if (accepting && accepting_attr) *accepting = accepting_attr->values[0].boolean; if (shared && shared_attr) *shared = shared_attr->values[0].boolean; if (state && state_attr) *state = (ipp_pstate_t)state_attr->values[0].integer; break; } } ippDelete(response); if (!*dest) { syslog(LOG_ERR, "Unable to find \"%s\" in list of printers!", name); return (-1); } name = dest; } else { /* * Get values from the response... */ if (accepting) { if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) == NULL) syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in " "response from server!"); else *accepting = attr->values[0].boolean; } if (shared) { if ((attr = ippFindAttribute(response, "printer-is-shared", IPP_TAG_BOOLEAN)) == NULL) { syslog(LOG_ERR, "No printer-is-shared attribute found in " "response from server!"); *shared = 1; } else *shared = attr->values[0].boolean; } if (state) { if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) syslog(LOG_ERR, "No printer-state attribute found in " "response from server!"); else *state = (ipp_pstate_t)attr->values[0].integer; } ippDelete(response); } /* * Next look for the printer in the lpoptions file... */ num_options = 0; if (options && shared && accepting) { if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL) cups_serverroot = CUPS_SERVERROOT; snprintf(line, sizeof(line), "%s/lpoptions", cups_serverroot); if ((fp = cupsFileOpen(line, "r")) != NULL) { linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { /* * Make sure we have "Dest name options" or "Default name options"... */ if ((_cups_strcasecmp(line, "Dest") && _cups_strcasecmp(line, "Default")) || !value) continue; /* * Separate destination name from options... */ for (optptr = value; *optptr && !isspace(*optptr & 255); optptr ++); while (*optptr == ' ') *optptr++ = '\0'; /* * If this is our destination, parse the options and break out of * the loop - we're done! */ if (!_cups_strcasecmp(value, name)) { num_options = cupsParseOptions(optptr, num_options, options); break; } } cupsFileClose(fp); } } else if (options) *options = NULL; /* * Return the number of options for this destination... */ return (num_options); }
void _cupsSetDefaults(void) { cups_file_t *fp; /* File */ const char *home; /* Home directory of user */ char filename[1024]; /* Filename */ _cups_client_conf_t cc; /* client.conf values */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_puts("_cupsSetDefaults()"); /* * Load initial client.conf values... */ cups_init_client_conf(&cc); /* * Read the /etc/cups/client.conf and ~/.cups/client.conf files, if * present. */ snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot); if ((fp = cupsFileOpen(filename, "r")) != NULL) { cups_read_client_conf(fp, &cc); cupsFileClose(fp); } # ifdef HAVE_GETEUID if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && (home = getenv("HOME")) != NULL) # elif !defined(WIN32) if (getuid() && (home = getenv("HOME")) != NULL) # else if ((home = getenv("HOME")) != NULL) # endif /* HAVE_GETEUID */ { /* * Look for ~/.cups/client.conf... */ snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); if ((fp = cupsFileOpen(filename, "r")) != NULL) { cups_read_client_conf(fp, &cc); cupsFileClose(fp); } } /* * Finalize things so every client.conf value is set... */ cups_finalize_client_conf(&cc); if (cg->encryption == (http_encryption_t)-1) cg->encryption = cc.encryption; if (!cg->server[0] || !cg->ipp_port) cupsSetServer(cc.server_name); if (!cg->ipp_port) cups_set_default_ipp_port(cg); if (!cg->user[0]) strlcpy(cg->user, cc.user, sizeof(cg->user)); #ifdef HAVE_GSSAPI if (!cg->gss_service_name[0]) strlcpy(cg->gss_service_name, cc.gss_service_name, sizeof(cg->gss_service_name)); #endif /* HAVE_GSSAPI */ if (cg->any_root < 0) cg->any_root = cc.any_root; if (cg->expired_certs < 0) cg->expired_certs = cc.expired_certs; if (cg->validate_certs < 0) cg->validate_certs = cc.validate_certs; #ifdef HAVE_SSL _httpTLSSetOptions(cc.ssl_options); #endif /* HAVE_SSL */ }
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 */ normalized[8192];/* Normalized msgid string */ size_t 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, normalize_string((use_msgid || !*msgstr) ? msgid : msgstr, normalized, sizeof(normalized))); } 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 = 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, normalize_string((use_msgid || !*msgstr) ? msgid : msgstr, normalized, sizeof(normalized))); } if (msgid) free(msgid); if (msgstr) free(msgstr); cupsFileClose(po); cupsFileClose(strings); return (0); }
static int /* O - Status */ read_write_tests(int compression) /* I - Use compression? */ { int i; /* Looping var */ cups_file_t *fp; /* File */ int status; /* Exit status */ char line[1024], /* Line from file */ *value; /* Directive value from line */ int linenum; /* Line number */ unsigned char readbuf[8192], /* Read buffer */ writebuf[8192]; /* Write buffer */ int byte; /* Byte from file */ off_t length; /* Length of file */ static const char *partial_line = "partial line"; /* Partial line */ /* * No errors so far... */ status = 0; /* * Initialize the write buffer with random data... */ CUPS_SRAND((unsigned)time(NULL)); for (i = 0; i < (int)sizeof(writebuf); i ++) writebuf[i] = CUPS_RAND(); /* * cupsFileOpen(write) */ printf("cupsFileOpen(write%s): ", compression ? " compressed" : ""); fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", compression ? "w9" : "w"); if (fp) { puts("PASS"); /* * cupsFileCompression() */ fputs("cupsFileCompression(): ", stdout); if (cupsFileCompression(fp) == compression) puts("PASS"); else { printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp), compression); status ++; } /* * cupsFilePuts() */ fputs("cupsFilePuts(): ", stdout); if (cupsFilePuts(fp, "# Hello, World\n") > 0) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFilePrintf() */ fputs("cupsFilePrintf(): ", stdout); for (i = 0; i < 1000; i ++) if (cupsFilePrintf(fp, "TestLine %03d\n", i) < 0) break; if (i >= 1000) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFilePutChar() */ fputs("cupsFilePutChar(): ", stdout); for (i = 0; i < 256; i ++) if (cupsFilePutChar(fp, i) < 0) break; if (i >= 256) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileWrite() */ fputs("cupsFileWrite(): ", stdout); for (i = 0; i < 10000; i ++) if (cupsFileWrite(fp, (char *)writebuf, sizeof(writebuf)) < 0) break; if (i >= 10000) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFilePuts() with partial line... */ fputs("cupsFilePuts(\"partial line\"): ", stdout); if (cupsFilePuts(fp, partial_line) > 0) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileTell() */ fputs("cupsFileTell(): ", stdout); if ((length = cupsFileTell(fp)) == 81933283) puts("PASS"); else { printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length); status ++; } /* * cupsFileClose() */ fputs("cupsFileClose(): ", stdout); if (!cupsFileClose(fp)) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileOpen(read) */ fputs("\ncupsFileOpen(read): ", stdout); fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", "r"); if (fp) { puts("PASS"); /* * cupsFileGets() */ fputs("cupsFileGets(): ", stdout); if (cupsFileGets(fp, line, sizeof(line))) { if (line[0] == '#') puts("PASS"); else { printf("FAIL (Got line \"%s\", expected comment line)\n", line); status ++; } } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileCompression() */ fputs("cupsFileCompression(): ", stdout); if (cupsFileCompression(fp) == compression) puts("PASS"); else { printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp), compression); status ++; } /* * cupsFileGetConf() */ linenum = 1; fputs("cupsFileGetConf(): ", stdout); for (i = 0; i < 1000; i ++) if (!cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) break; else if (_cups_strcasecmp(line, "TestLine") || !value || atoi(value) != i || linenum != (i + 2)) break; if (i >= 1000) puts("PASS"); else if (line[0]) { printf("FAIL (Line %d, directive \"%s\", value \"%s\")\n", linenum, line, value ? value : "(null)"); status ++; } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileGetChar() */ fputs("cupsFileGetChar(): ", stdout); for (i = 0; i < 256; i ++) if ((byte = cupsFileGetChar(fp)) != i) break; if (i >= 256) puts("PASS"); else if (byte >= 0) { printf("FAIL (Got %d, expected %d)\n", byte, i); status ++; } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileRead() */ fputs("cupsFileRead(): ", stdout); for (i = 0; i < 10000; i ++) if ((byte = cupsFileRead(fp, (char *)readbuf, sizeof(readbuf))) < 0) break; else if (memcmp(readbuf, writebuf, sizeof(readbuf))) break; if (i >= 10000) puts("PASS"); else if (byte > 0) { printf("FAIL (Pass %d, ", i); for (i = 0; i < (int)sizeof(readbuf); i ++) if (readbuf[i] != writebuf[i]) break; printf("match failed at offset %d - got %02X, expected %02X)\n", i, readbuf[i], writebuf[i]); } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * cupsFileGetChar() with partial line... */ fputs("cupsFileGetChar(partial line): ", stdout); for (i = 0; i < (int)strlen(partial_line); i ++) if ((byte = cupsFileGetChar(fp)) < 0) break; else if (byte != partial_line[i]) break; if (!partial_line[i]) puts("PASS"); else { printf("FAIL (got '%c', expected '%c')\n", byte, partial_line[i]); status ++; } /* * cupsFileTell() */ fputs("cupsFileTell(): ", stdout); if ((length = cupsFileTell(fp)) == 81933283) puts("PASS"); else { printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length); status ++; } /* * cupsFileClose() */ fputs("cupsFileClose(): ", stdout); if (!cupsFileClose(fp)) puts("PASS"); else { printf("FAIL (%s)\n", strerror(errno)); status ++; } } else { printf("FAIL (%s)\n", strerror(errno)); status ++; } /* * Remove the test file... */ unlink(compression ? "testfile.dat.gz" : "testfile.dat"); /* * Return the test status... */ return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { _ippdata_t data; /* IPP buffer */ ipp_uchar_t buffer[8192]; /* Write buffer data */ ipp_t *cols[2], /* Collections */ *size; /* media-size collection */ ipp_t *request; /* Request */ ipp_attribute_t *media_col, /* media-col attribute */ *media_size, /* media-size attribute */ *attr; /* Other attribute */ ipp_state_t state; /* State */ size_t length; /* Length of data */ cups_file_t *fp; /* File pointer */ size_t i; /* Looping var */ int status; /* Status of tests (0 = success, 1 = fail) */ #ifdef DEBUG const char *name; /* Option name */ #endif /* DEBUG */ status = 0; if (argc == 1) { /* * Test request generation code... */ printf("Create Sample Request: "); request = ippNew(); request->request.op.version[0] = 0x01; request->request.op.version[1] = 0x01; request->request.op.operation_id = IPP_OP_PRINT_JOB; request->request.op.request_id = 1; ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, "en"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/foo"); cols[0] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21590); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 27940); ippAddCollection(cols[0], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue"); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "plain"); cols[1] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21000); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 29700); ippAddCollection(cols[1], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "plaid"); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "glossy"); ippAddCollections(request, IPP_TAG_JOB, "media-col", 2, (const ipp_t **)cols); ippDelete(cols[0]); ippDelete(cols[1]); length = ippLength(request); if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); status = 1; } else puts("PASS"); /* * Write test #1... */ printf("Write Sample to Memory: "); data.wused = 0; data.wsize = sizeof(buffer); data.wbuffer = buffer; while ((state = ippWriteIO(&data, (ipp_iocb_t)write_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes written.\n", (int)data.wused); status = 1; } else if (data.wused != sizeof(collection)) { printf("FAIL - wrote %d bytes, expected %d bytes!\n", (int)data.wused, (int)sizeof(collection)); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else if (memcmp(data.wbuffer, collection, data.wused)) { for (i = 0; i < data.wused; i ++) if (data.wbuffer[i] != collection[i]) break; printf("FAIL - output does not match baseline at 0x%04x!\n", (unsigned)i); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the data back in and confirm... */ printf("Read Sample from Memory: "); request = ippNew(); data.rpos = 0; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != data.wused) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)data.wused); print_attributes(request, 8); status = 1; } else if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(media-col): ", stdout); if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_col->value_tag)); status = 1; } else if (media_col->num_values != 2) { printf("FAIL (wrong count - %d)\n", media_col->num_values); status = 1; } else puts("PASS"); if (media_col) { fputs("ippFindAttribute(media-size 1): ", stdout); if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 27940) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } fputs("ippFindAttribute(media-size 2): ", stdout); if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 29700) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } } /* * Test hierarchical find... */ fputs("ippFindAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension) again: ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { printf("FAIL (got %d, expected nothing)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the mixed data and confirm we converted everything to rangeOfInteger * values... */ printf("Read Mixed integer/rangeOfInteger from Memory: "); request = ippNew(); data.rpos = 0; data.wused = sizeof(mixed); data.wsize = sizeof(mixed); data.wbuffer = mixed; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != sizeof(mixed)) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)sizeof(mixed)); print_attributes(request, 8); status = 1; } else if (length != (sizeof(mixed) + 4)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(mixed) + 4); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(notify-lease-duration-supported): ", stdout); if ((attr = ippFindAttribute(request, "notify-lease-duration-supported", IPP_TAG_ZERO)) == NULL) { puts("FAIL (not found)"); status = 1; } else if (attr->value_tag != IPP_TAG_RANGE) { printf("FAIL (wrong type - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->num_values != 2) { printf("FAIL (wrong count - %d)\n", attr->num_values); status = 1; } else if (attr->values[0].range.lower != 1 || attr->values[0].range.upper != 1 || attr->values[1].range.lower != 16 || attr->values[1].range.upper != 32) { printf("FAIL (wrong values - %d,%d and %d,%d)\n", attr->values[0].range.lower, attr->values[0].range.upper, attr->values[1].range.lower, attr->values[1].range.upper); status = 1; } else puts("PASS"); ippDelete(request); #ifdef DEBUG /* * Test that private option array is sorted... */ fputs("_ippCheckOptions: ", stdout); if ((name = _ippCheckOptions()) == NULL) puts("PASS"); else { printf("FAIL (\"%s\" out of order)\n", name); status = 1; } #endif /* DEBUG */ /* * Test _ippFindOption() private API... */ fputs("_ippFindOption(\"printer-type\"): ", stdout); if (_ippFindOption("printer-type")) puts("PASS"); else { puts("FAIL"); status = 1; } /* * Summarize... */ putchar('\n'); if (status) puts("Core IPP tests failed."); else puts("Core IPP tests passed."); } else { /* * Read IPP files... */ for (i = 1; i < (size_t)argc; i ++) { if ((fp = cupsFileOpen(argv[i], "r")) == NULL) { printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno)); status = 1; continue; } request = ippNew(); while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, request)) == IPP_STATE_ATTRIBUTE); if (state != IPP_STATE_DATA) { printf("Error reading IPP message from \"%s\"!\n", argv[i]); status = 1; } else { printf("\n%s:\n", argv[i]); print_attributes(request, 4); } ippDelete(request); cupsFileClose(fp); } } return (status); }
help_index_t * /* O - Index pointer or NULL */ helpLoadIndex(const char *hifile, /* I - Index filename */ const char *directory) /* I - Directory that is indexed */ { help_index_t *hi; /* Help index */ cups_file_t *fp; /* Current file */ char line[2048], /* Line from file */ *ptr, /* Pointer into line */ *filename, /* Filename in line */ *anchor, /* Anchor in line */ *sectptr, /* Section pointer in line */ section[1024], /* Section name */ *text; /* Text in line */ time_t mtime; /* Modification time */ off_t offset; /* Offset into file */ size_t length; /* Length in bytes */ int update; /* Update? */ help_node_t *node; /* Current node */ help_word_t *word; /* Current word */ DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")", hifile, directory)); /* * Create a new, empty index. */ if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL) return (NULL); hi->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL); hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL); if (!hi->nodes || !hi->sorted) { cupsArrayDelete(hi->nodes); cupsArrayDelete(hi->sorted); free(hi); return (NULL); } /* * Try loading the existing index file... */ if ((fp = cupsFileOpen(hifile, "r")) != NULL) { /* * Lock the file and then read the first line... */ cupsFileLock(fp, 1); if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2")) { /* * Got a valid header line, now read the data lines... */ node = NULL; while (cupsFileGets(fp, line, sizeof(line))) { /* * Each line looks like one of the following: * * filename mtime offset length "section" "text" * filename#anchor offset length "text" * SP count word */ if (line[0] == ' ') { /* * Read a word in the current node... */ if (!node || (ptr = strrchr(line, ' ')) == NULL) continue; if ((word = help_add_word(node, ptr + 1)) != NULL) word->count = atoi(line + 1); } else { /* * Add a node... */ filename = line; if ((ptr = strchr(line, ' ')) == NULL) break; while (isspace(*ptr & 255)) *ptr++ = '\0'; if ((anchor = strrchr(filename, '#')) != NULL) { *anchor++ = '\0'; mtime = 0; } else mtime = strtol(ptr, &ptr, 10); offset = strtoll(ptr, &ptr, 10); length = strtoll(ptr, &ptr, 10); while (isspace(*ptr & 255)) ptr ++; if (!anchor) { /* * Get section... */ if (*ptr != '\"') break; ptr ++; sectptr = ptr; while (*ptr && *ptr != '\"') ptr ++; if (*ptr != '\"') break; *ptr++ = '\0'; strlcpy(section, sectptr, sizeof(section)); while (isspace(*ptr & 255)) ptr ++; } if (*ptr != '\"') break; ptr ++; text = ptr; while (*ptr && *ptr != '\"') ptr ++; if (*ptr != '\"') break; *ptr++ = '\0'; if ((node = help_new_node(filename, anchor, section, text, mtime, offset, length)) == NULL) break; node->score = -1; cupsArrayAdd(hi->nodes, node); } } } cupsFileClose(fp); } /* * Scan for new/updated files... */ update = help_load_directory(hi, directory, NULL); /* * Remove any files that are no longer installed... */ for (node = (help_node_t *)cupsArrayFirst(hi->nodes); node; node = (help_node_t *)cupsArrayNext(hi->nodes)) if (node->score < 0) { /* * Delete this node... */ cupsArrayRemove(hi->nodes, node); help_delete_node(node); } /* * Add nodes to the sorted array... */ for (node = (help_node_t *)cupsArrayFirst(hi->nodes); node; node = (help_node_t *)cupsArrayNext(hi->nodes)) cupsArrayAdd(hi->sorted, node); /* * Save the index if we updated it... */ if (update) helpSaveIndex(hi, hifile); /* * Return the index... */ return (hi); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int status = 0; /* Exit status */ cups_file_t *fp; /* Command file */ char line[1024], /* Line from file */ *value; /* Value on line */ int linenum; /* Line number in file */ ppd_file_t *ppd; /* PPD file */ /* * Check for valid arguments... */ if (argc < 6 || argc > 7) { /* * We don't have the correct number of arguments; write an error message * and return. */ _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (1); } /* * Open the PPD file... */ if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL) { fputs("ERROR: Unable to open PPD file!\n", stderr); return (1); } /* * Open the command file as needed... */ if (argc == 7) { if ((fp = cupsFileOpen(argv[6], "r")) == NULL) { perror("ERROR: Unable to open command file - "); return (1); } } else fp = cupsFileStdin(); /* * Read the commands from the file and send the appropriate commands... */ linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { /* * Parse the command... */ if (!_cups_strcasecmp(line, "AutoConfigure")) status |= auto_configure(ppd, argv[2]); else if (!_cups_strcasecmp(line, "PrintSelfTestPage")) print_self_test_page(ppd, argv[2]); else if (!_cups_strcasecmp(line, "ReportLevels")) report_levels(ppd, argv[2]); else { _cupsLangPrintFilter(stderr, "ERROR", _("Invalid printer command \"%s\"."), line); status = 1; } } return (status); }
static int /* O - 0 = success, -1 = error */ help_load_file( help_index_t *hi, /* I - Index */ const char *filename, /* I - Filename */ const char *relative, /* I - Relative path */ time_t mtime) /* I - Modification time */ { cups_file_t *fp; /* HTML file */ help_node_t *node; /* Current node */ char line[1024], /* Line from file */ temp[1024], /* Temporary word */ section[1024], /* Section */ *ptr, /* Pointer into line */ *anchor, /* Anchor name */ *text; /* Text for anchor */ off_t offset; /* File offset */ char quote; /* Quote character */ help_word_t *word; /* Current word */ int wordlen; /* Length of word */ DEBUG_printf(("2help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", " "mtime=%ld)", hi, filename, relative, mtime)); if ((fp = cupsFileOpen(filename, "r")) == NULL) return (-1); node = NULL; offset = 0; strlcpy(section, "Other", sizeof(section)); while (cupsFileGets(fp, line, sizeof(line))) { /* * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix... */ if (!_cups_strncasecmp(line, "<!-- SECTION:", 13)) { /* * Got section line, copy it! */ for (ptr = line + 13; isspace(*ptr & 255); ptr ++); strlcpy(section, ptr, sizeof(section)); if ((ptr = strstr(section, "-->")) != NULL) { /* * Strip comment stuff from end of line... */ for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0'); if (isspace(*ptr & 255)) *ptr = '\0'; } continue; } for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;) { ptr ++; if (!_cups_strncasecmp(ptr, "TITLE>", 6)) { /* * Found the title... */ anchor = NULL; ptr += 6; } else if (!_cups_strncasecmp(ptr, "A NAME=", 7)) { /* * Found an anchor... */ ptr += 7; if (*ptr == '\"' || *ptr == '\'') { /* * Get quoted anchor... */ quote = *ptr; anchor = ptr + 1; if ((ptr = strchr(anchor, quote)) != NULL) *ptr++ = '\0'; else break; } else { /* * Get unquoted anchor... */ anchor = ptr + 1; for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++); if (*ptr) *ptr++ = '\0'; else break; } /* * Got the anchor, now lets find the end... */ while (*ptr && *ptr != '>') ptr ++; if (*ptr != '>') break; ptr ++; } else continue; /* * Now collect text for the link... */ text = ptr; while ((ptr = strchr(text, '<')) == NULL) { ptr = text + strlen(text); if (ptr >= (line + sizeof(line) - 2)) break; *ptr++ = ' '; if (!cupsFileGets(fp, ptr, sizeof(line) - (ptr - line) - 1)) break; } *ptr = '\0'; if (node) node->length = offset - node->offset; if (!*text) { node = NULL; break; } if ((node = helpFindNode(hi, relative, anchor)) != NULL) { /* * Node already in the index, so replace the text and other * data... */ cupsArrayRemove(hi->nodes, node); if (node->section) free(node->section); if (node->text) free(node->text); if (node->words) { for (word = (help_word_t *)cupsArrayFirst(node->words); word; word = (help_word_t *)cupsArrayNext(node->words)) help_delete_word(word); cupsArrayDelete(node->words); node->words = NULL; } node->section = section[0] ? strdup(section) : NULL; node->text = strdup(text); node->mtime = mtime; node->offset = offset; node->score = 0; } else { /* * New node... */ node = help_new_node(relative, anchor, section, text, mtime, offset, 0); } /* * Go through the text value and replace tabs and newlines with * whitespace and eliminate extra whitespace... */ for (ptr = node->text, text = node->text; *ptr;) if (isspace(*ptr & 255)) { while (isspace(*ptr & 255)) ptr ++; *text++ = ' '; } else if (text != ptr) *text++ = *ptr++; else { text ++; ptr ++; } *text = '\0'; /* * (Re)add the node to the array... */ cupsArrayAdd(hi->nodes, node); if (!anchor) node = NULL; break; } if (node) { /* * Scan this line for words... */ for (ptr = line; *ptr; ptr ++) { /* * Skip HTML stuff... */ if (*ptr == '<') { if (!strncmp(ptr, "<!--", 4)) { /* * Skip HTML comment... */ if ((text = strstr(ptr + 4, "-->")) == NULL) ptr += strlen(ptr) - 1; else ptr = text + 2; } else { /* * Skip HTML element... */ for (ptr ++; *ptr && *ptr != '>'; ptr ++) { if (*ptr == '\"' || *ptr == '\'') { for (quote = *ptr++; *ptr && *ptr != quote; ptr ++); if (!*ptr) ptr --; } } if (!*ptr) ptr --; } continue; } else if (*ptr == '&') { /* * Skip HTML entity... */ for (ptr ++; *ptr && *ptr != ';'; ptr ++); if (!*ptr) ptr --; continue; } else if (!isalnum(*ptr & 255)) continue; /* * Found the start of a word, search until we find the end... */ for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++); wordlen = ptr - text; memcpy(temp, text, wordlen); temp[wordlen] = '\0'; ptr --; if (wordlen > 1 && !bsearch(temp, help_common_words, (sizeof(help_common_words) / sizeof(help_common_words[0])), sizeof(help_common_words[0]), (int (*)(const void *, const void *)) _cups_strcasecmp)) help_add_word(node, temp); } } /* * Get the offset of the next line... */ offset = cupsFileTell(fp); } cupsFileClose(fp); if (node) node->length = offset - node->offset; return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int status = 0, /* Exit status */ i, /* Looping var */ num_dests; /* Number of destinations */ cups_dest_t *dests, /* Destinations */ *dest, /* Current destination */ *named_dest; /* Current named destination */ const char *ppdfile; /* PPD file */ ppd_file_t *ppd; /* PPD file data */ int num_jobs; /* Number of jobs for queue */ cups_job_t *jobs; /* Jobs for queue */ if (argc > 1) { if (!strcmp(argv[1], "enum")) { cups_ptype_t mask = CUPS_PRINTER_LOCAL, /* Printer type mask */ type = CUPS_PRINTER_LOCAL; /* Printer type */ int msec = 0; /* Timeout in milliseconds */ for (i = 2; i < argc; i ++) if (isdigit(argv[i][0] & 255) || argv[i][0] == '.') msec = (int)(atof(argv[i]) * 1000); else if (!_cups_strcasecmp(argv[i], "bw")) { mask |= CUPS_PRINTER_BW; type |= CUPS_PRINTER_BW; } else if (!_cups_strcasecmp(argv[i], "color")) { mask |= CUPS_PRINTER_COLOR; type |= CUPS_PRINTER_COLOR; } else if (!_cups_strcasecmp(argv[i], "mono")) { mask |= CUPS_PRINTER_COLOR; } else if (!_cups_strcasecmp(argv[i], "duplex")) { mask |= CUPS_PRINTER_DUPLEX; type |= CUPS_PRINTER_DUPLEX; } else if (!_cups_strcasecmp(argv[i], "simplex")) { mask |= CUPS_PRINTER_DUPLEX; } else if (!_cups_strcasecmp(argv[i], "staple")) { mask |= CUPS_PRINTER_STAPLE; type |= CUPS_PRINTER_STAPLE; } else if (!_cups_strcasecmp(argv[i], "copies")) { mask |= CUPS_PRINTER_COPIES; type |= CUPS_PRINTER_COPIES; } else if (!_cups_strcasecmp(argv[i], "collate")) { mask |= CUPS_PRINTER_COLLATE; type |= CUPS_PRINTER_COLLATE; } else if (!_cups_strcasecmp(argv[i], "punch")) { mask |= CUPS_PRINTER_PUNCH; type |= CUPS_PRINTER_PUNCH; } else if (!_cups_strcasecmp(argv[i], "cover")) { mask |= CUPS_PRINTER_COVER; type |= CUPS_PRINTER_COVER; } else if (!_cups_strcasecmp(argv[i], "bind")) { mask |= CUPS_PRINTER_BIND; type |= CUPS_PRINTER_BIND; } else if (!_cups_strcasecmp(argv[i], "sort")) { mask |= CUPS_PRINTER_SORT; type |= CUPS_PRINTER_SORT; } else if (!_cups_strcasecmp(argv[i], "mfp")) { mask |= CUPS_PRINTER_MFP; type |= CUPS_PRINTER_MFP; } else if (!_cups_strcasecmp(argv[i], "printer")) { mask |= CUPS_PRINTER_MFP; } else if (!_cups_strcasecmp(argv[i], "large")) { mask |= CUPS_PRINTER_LARGE; type |= CUPS_PRINTER_LARGE; } else if (!_cups_strcasecmp(argv[i], "medium")) { mask |= CUPS_PRINTER_MEDIUM; type |= CUPS_PRINTER_MEDIUM; } else if (!_cups_strcasecmp(argv[i], "small")) { mask |= CUPS_PRINTER_SMALL; type |= CUPS_PRINTER_SMALL; } else fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]); cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL); } else if (!strcmp(argv[1], "password")) { const char *pass = cupsGetPassword("Password:"******"Password entered: %s\n", pass); else puts("No password entered."); } else if (!strcmp(argv[1], "ppd") && argc == 3) { /* * ./testcups ppd printer */ http_status_t http_status; /* Status */ char buffer[1024]; /* PPD filename */ time_t modtime = 0; /* Last modified */ if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime, buffer, sizeof(buffer))) != HTTP_STATUS_OK) printf("Unable to get PPD: %d (%s)\n", (int)http_status, cupsLastErrorString()); else puts(buffer); } else if (!strcmp(argv[1], "print") && argc == 5) { /* * ./testcups print printer file interval */ int interval, /* Interval between writes */ job_id; /* Job ID */ cups_file_t *fp; /* Print file */ char buffer[16384]; /* Read/write buffer */ ssize_t bytes; /* Bytes read/written */ if ((fp = cupsFileOpen(argv[3], "r")) == NULL) { printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno)); return (1); } if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0, NULL)) <= 0) { printf("Unable to create print job on %s: %s\n", argv[1], cupsLastErrorString()); return (1); } interval = atoi(argv[4]); if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2], CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE) { puts("Unable to start document!"); return (1); } while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) { printf("Writing %d bytes...\n", (int)bytes); if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes) != HTTP_STATUS_CONTINUE) { puts("Unable to write bytes!"); return (1); } if (interval > 0) sleep(interval); } cupsFileClose(fp); if (cupsFinishDocument(CUPS_HTTP_DEFAULT, argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) { puts("Unable to finish document!"); return (1); } } else { puts("Usage:"); puts(""); puts("Run basic unit tests:"); puts(""); puts(" ./testcups"); puts(""); puts("Enumerate printers (for N seconds, -1 for indefinitely):"); puts(""); puts(" ./testcups enum [seconds]"); puts(""); puts("Ask for a password:"******""); puts(" ./testcups password"); puts(""); puts("Get the PPD file:"); puts(""); puts(" ./testcups ppd printer"); puts(""); puts("Print a file (interval controls delay between buffers in seconds):"); puts(""); puts(" ./testcups print printer file interval"); return (1); } return (0); } /* * cupsGetDests() */ fputs("cupsGetDests: ", stdout); fflush(stdout); num_dests = cupsGetDests(&dests); if (num_dests == 0) { puts("FAIL"); return (1); } else { printf("PASS (%d dests)\n", num_dests); for (i = num_dests, dest = dests; i > 0; i --, dest ++) { printf(" %s", dest->name); if (dest->instance) printf(" /%s", dest->instance); if (dest->is_default) puts(" ***DEFAULT***"); else putchar('\n'); } } /* * cupsGetDest(NULL) */ fputs("cupsGetDest(NULL): ", stdout); fflush(stdout); if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) { for (i = num_dests, dest = dests; i > 0; i --, dest ++) if (dest->is_default) break; if (i) { status = 1; puts("FAIL"); } else puts("PASS (no default)"); dest = NULL; } else printf("PASS (%s)\n", dest->name); /* * cupsGetNamedDest(NULL, NULL, NULL) */ fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout); fflush(stdout); if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL || !dests_equal(dest, named_dest)) { if (!dest) puts("PASS (no default)"); else if (named_dest) { puts("FAIL (different values)"); show_diffs(dest, named_dest); status = 1; } else { puts("FAIL (no default)"); status = 1; } } else printf("PASS (%s)\n", named_dest->name); if (named_dest) cupsFreeDests(1, named_dest); /* * cupsGetDest(printer) */ printf("cupsGetDest(\"%s\"): ", dests[num_dests / 2].name); fflush(stdout); if ((dest = cupsGetDest(dests[num_dests / 2].name, NULL, num_dests, dests)) == NULL) { puts("FAIL"); return (1); } else puts("PASS"); /* * cupsGetNamedDest(NULL, printer, instance) */ printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name, dest->instance ? dest->instance : "(null)"); fflush(stdout); if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL || !dests_equal(dest, named_dest)) { if (named_dest) { puts("FAIL (different values)"); show_diffs(dest, named_dest); } else puts("FAIL (no destination)"); status = 1; } else puts("PASS"); if (named_dest) cupsFreeDests(1, named_dest); /* * cupsPrintFile() */ fputs("cupsPrintFile: ", stdout); fflush(stdout); if (cupsPrintFile(dest->name, "../data/testprint", "Test Page", dest->num_options, dest->options) <= 0) { printf("FAIL (%s)\n", cupsLastErrorString()); return (1); } else puts("PASS"); /* * cupsGetPPD(printer) */ fputs("cupsGetPPD(): ", stdout); fflush(stdout); if ((ppdfile = cupsGetPPD(dest->name)) == NULL) { puts("FAIL"); } else { puts("PASS"); /* * ppdOpenFile() */ fputs("ppdOpenFile(): ", stdout); fflush(stdout); if ((ppd = ppdOpenFile(ppdfile)) == NULL) { puts("FAIL"); return (1); } else puts("PASS"); ppdClose(ppd); unlink(ppdfile); } /* * cupsGetJobs() */ fputs("cupsGetJobs: ", stdout); fflush(stdout); num_jobs = cupsGetJobs(&jobs, NULL, 0, -1); if (num_jobs == 0) { puts("FAIL"); return (1); } else puts("PASS"); cupsFreeJobs(num_jobs, jobs); cupsFreeDests(num_dests, dests); return (status); }
static void mime_load_types(mime_t *mime, /* I - MIME database */ const char *filename) /* I - Types file to load */ { cups_file_t *fp; /* Types file */ int linelen; /* Length of line */ char line[32768], /* Input line from file */ *lineptr, /* Current position in line */ super[MIME_MAX_SUPER], /* Super-type name */ type[MIME_MAX_TYPE], /* Type name */ *temp; /* Temporary pointer */ mime_type_t *typeptr; /* New MIME type */ DEBUG_printf(("2mime_load_types(mime=%p, filename=\"%s\")", mime, filename)); /* * First try to open the file... */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { DEBUG_printf(("3mime_load_types: Unable to open \"%s\": %s", filename, strerror(errno))); _mimeError(mime, "Unable to open \"%s\": %s", filename, strerror(errno)); return; } /* * Then read each line from the file, skipping any comments in the file... */ while (cupsFileGets(fp, line, sizeof(line)) != NULL) { /* * Skip blank lines and lines starting with a #... */ if (!line[0] || line[0] == '#') continue; /* * While the last character in the line is a backslash, continue on to the * next line (and the next, etc.) */ linelen = strlen(line); while (line[linelen - 1] == '\\') { linelen --; if (cupsFileGets(fp, line + linelen, sizeof(line) - linelen) == NULL) line[linelen] = '\0'; else linelen += strlen(line + linelen); } /* * Extract the super-type and type names from the beginning of the line. */ lineptr = line; temp = super; while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; if (*lineptr != '/') continue; lineptr ++; temp = type; while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) *temp++ = tolower(*lineptr++ & 255); *temp = '\0'; /* * Add the type and rules to the MIME database... */ typeptr = mimeAddType(mime, super, type); mimeAddTypeRule(typeptr, lineptr); } cupsFileClose(fp); }
static void read_snmp_conf(const char *address) /* I - Single address to probe */ { cups_file_t *fp; /* File pointer */ char filename[1024], /* Filename */ line[1024], /* Line from file */ *value; /* Value on line */ int linenum; /* Line number */ const char *cups_serverroot; /* CUPS_SERVERROOT env var */ const char *debug; /* CUPS_DEBUG_LEVEL env var */ const char *runtime; /* CUPS_MAX_RUN_TIME env var */ /* * Initialize the global address and community lists... */ Addresses = cupsArrayNew(NULL, NULL); Communities = cupsArrayNew(NULL, NULL); if (address) add_array(Addresses, address); if ((debug = getenv("CUPS_DEBUG_LEVEL")) != NULL) DebugLevel = atoi(debug); if ((runtime = getenv("CUPS_MAX_RUN_TIME")) != NULL) MaxRunTime = atoi(runtime); /* * Find the snmp.conf file... */ if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL) cups_serverroot = CUPS_SERVERROOT; snprintf(filename, sizeof(filename), "%s/snmp.conf", cups_serverroot); if ((fp = cupsFileOpen(filename, "r")) != NULL) { /* * Read the snmp.conf file... */ linenum = 0; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { if (!value) fprintf(stderr, "ERROR: Missing value on line %d of %s!\n", linenum, filename); else if (!_cups_strcasecmp(line, "Address")) { if (!address) add_array(Addresses, value); } else if (!_cups_strcasecmp(line, "Community")) add_array(Communities, value); else if (!_cups_strcasecmp(line, "DebugLevel")) DebugLevel = atoi(value); else if (!_cups_strcasecmp(line, "DeviceURI")) { if (*value != '\"') fprintf(stderr, "ERROR: Missing double quote for regular expression on " "line %d of %s!\n", linenum, filename); else add_device_uri(value); } else if (!_cups_strcasecmp(line, "HostNameLookups")) HostNameLookups = !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "double"); else if (!_cups_strcasecmp(line, "MaxRunTime")) MaxRunTime = atoi(value); else fprintf(stderr, "ERROR: Unknown directive %s on line %d of %s!\n", line, linenum, filename); } cupsFileClose(fp); } /* * Use defaults if parameters are undefined... */ if (cupsArrayCount(Addresses) == 0) { /* * If we have no addresses, exit immediately... */ fprintf(stderr, "DEBUG: No address specified and no Address line in %s...\n", filename); exit(0); } if (cupsArrayCount(Communities) == 0) { fputs("INFO: Using default SNMP Community public\n", stderr); add_array(Communities, "public"); } }