static char * /* O - End of string */ cups_scan_strings(char *buffer) /* I - Start of string */ { char *bufptr; /* Pointer into string */ for (bufptr = buffer + 1; *bufptr && *bufptr != '\"'; bufptr ++) { if (*bufptr == '\\') { if (bufptr[1] >= '0' && bufptr[1] <= '3' && bufptr[2] >= '0' && bufptr[2] <= '7' && bufptr[3] >= '0' && bufptr[3] <= '7') { /* * Decode \nnn octal escape... */ *bufptr = ((((bufptr[1] - '0') << 3) | (bufptr[2] - '0')) << 3) | (bufptr[3] - '0'); _cups_strcpy(bufptr + 1, bufptr + 4); } else { /* * Decode \C escape... */ _cups_strcpy(bufptr, bufptr + 1); if (*bufptr == 'n') *bufptr = '\n'; else if (*bufptr == 'r') *bufptr = '\r'; else if (*bufptr == 't') *bufptr = '\t'; } } } return (bufptr); }
static device_uri_t * /* O - Device URI */ add_device_uri(char *value) /* I - Value from snmp.conf */ { device_uri_t *device_uri; /* Device URI */ char *start; /* Start of value */ /* * Allocate memory as needed... */ if (!DeviceURIs) DeviceURIs = cupsArrayNew(NULL, NULL); if (!DeviceURIs) return (NULL); if ((device_uri = calloc(1, sizeof(device_uri_t))) == NULL) return (NULL); if ((device_uri->uris = cupsArrayNew(NULL, NULL)) == NULL) { free(device_uri); return (NULL); } /* * Scan the value string for the regular expression and URI(s)... */ value ++; /* Skip leading " */ for (start = value; *value && *value != '\"'; value ++) if (*value == '\\' && value[1]) _cups_strcpy(value, value + 1); if (!*value) { fputs("ERROR: Missing end quote for DeviceURI!\n", stderr); cupsArrayDelete(device_uri->uris); free(device_uri); return (NULL); } *value++ = '\0'; if (regcomp(&(device_uri->re), start, REG_EXTENDED | REG_ICASE)) { fputs("ERROR: Bad regular expression for DeviceURI!\n", stderr); cupsArrayDelete(device_uri->uris); free(device_uri); return (NULL); } while (*value) { while (isspace(*value & 255)) value ++; if (!*value) break; for (start = value; *value && !isspace(*value & 255); value ++); if (*value) *value++ = '\0'; cupsArrayAdd(device_uri->uris, strdup(start)); } /* * Add the device URI to the list and return it... */ cupsArrayAdd(DeviceURIs, device_uri); return (device_uri); }
int /* O - Number of options found */ cupsParseOptions( const char *arg, /* I - Argument to parse */ int num_options, /* I - Number of options */ cups_option_t **options) /* O - Options found */ { char *copyarg, /* Copy of input string */ *ptr, /* Pointer into string */ *name, /* Pointer to name */ *value, /* Pointer to value */ sep, /* Separator character */ quote; /* Quote character */ DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options)); /* * Range check input... */ if (!arg) { DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (!options || num_options < 0) { DEBUG_puts("1cupsParseOptions: Returning 0"); return (0); } /* * Make a copy of the argument string and then divide it up... */ if ((copyarg = strdup(arg)) == NULL) { DEBUG_puts("1cupsParseOptions: Unable to copy arg string"); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (*copyarg == '{') { /* * Remove surrounding {} so we can parse "{name=value ... name=value}"... */ if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}') { *ptr = '\0'; ptr = copyarg + 1; } else ptr = copyarg; } else ptr = copyarg; /* * Skip leading spaces... */ while (_cups_isspace(*ptr)) ptr ++; /* * Loop through the string... */ while (*ptr != '\0') { /* * Get the name up to a SPACE, =, or end-of-string... */ name = ptr; while (!strchr("\f\n\r\t\v =", *ptr) && *ptr) ptr ++; /* * Avoid an empty name... */ if (ptr == name) break; /* * Skip trailing spaces... */ while (_cups_isspace(*ptr)) *ptr++ = '\0'; if ((sep = *ptr) == '=') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name)); if (sep != '=') { /* * Boolean option... */ if (!_cups_strncasecmp(name, "no", 2)) num_options = cupsAddOption(name + 2, "false", num_options, options); else num_options = cupsAddOption(name, "true", num_options, options); continue; } /* * Remove = and parse the value... */ value = ptr; while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == ',') ptr ++; else if (*ptr == '\'' || *ptr == '\"') { /* * Quoted string constant... */ quote = *ptr; _cups_strcpy(ptr, ptr + 1); while (*ptr != quote && *ptr) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } if (*ptr) _cups_strcpy(ptr, ptr + 1); } else if (*ptr == '{') { /* * Collection value... */ int depth; for (depth = 0; *ptr; ptr ++) { if (*ptr == '{') depth ++; else if (*ptr == '}') { depth --; if (!depth) { ptr ++; break; } } else if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } } else { /* * Normal space-delimited string... */ while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } } } if (*ptr != '\0') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value)); /* * Skip trailing whitespace... */ while (_cups_isspace(*ptr)) ptr ++; /* * Add the string value... */ num_options = cupsAddOption(name, value, num_options, options); } /* * Free the copy of the argument we made and return the number of options * found. */ free(copyarg); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); }
char * /* O - Line from buffer, "", or NULL */ cupsdStatBufUpdate(cupsd_statbuf_t *sb, /* I - Status buffer */ int *loglevel, /* O - Log level */ char *line, /* I - Line buffer */ int linelen) /* I - Size of line buffer */ { int bytes; /* Number of bytes read */ char *lineptr, /* Pointer to end of line in buffer */ *message; /* Pointer to message text */ /* * Check if the buffer already contains a full line... */ if ((lineptr = strchr(sb->buffer, '\n')) == NULL) { /* * No, read more data... */ if ((bytes = read(sb->fd, sb->buffer + sb->bufused, CUPSD_SB_BUFFER_SIZE - sb->bufused - 1)) > 0) { sb->bufused += bytes; sb->buffer[sb->bufused] = '\0'; /* * Guard against a line longer than the max buffer size... */ if ((lineptr = strchr(sb->buffer, '\n')) == NULL && sb->bufused == (CUPSD_SB_BUFFER_SIZE - 1)) lineptr = sb->buffer + sb->bufused; } else if (bytes < 0 && errno == EINTR) { /* * Return an empty line if we are interrupted... */ *loglevel = CUPSD_LOG_NONE; line[0] = '\0'; return (line); } else { /* * End-of-file, so use the whole buffer... */ lineptr = sb->buffer + sb->bufused; *lineptr = '\0'; } /* * Final check for end-of-file... */ if (sb->bufused == 0 && bytes == 0) lineptr = NULL; } if (!lineptr) { /* * End of file... */ *loglevel = CUPSD_LOG_NONE; line[0] = '\0'; return (NULL); } /* * Terminate the line and process it... */ *lineptr++ = '\0'; /* * Figure out the logging level... */ if (!strncmp(sb->buffer, "EMERG:", 6)) { *loglevel = CUPSD_LOG_EMERG; message = sb->buffer + 6; } else if (!strncmp(sb->buffer, "ALERT:", 6)) { *loglevel = CUPSD_LOG_ALERT; message = sb->buffer + 6; } else if (!strncmp(sb->buffer, "CRIT:", 5)) { *loglevel = CUPSD_LOG_CRIT; message = sb->buffer + 5; } else if (!strncmp(sb->buffer, "ERROR:", 6)) { *loglevel = CUPSD_LOG_ERROR; message = sb->buffer + 6; } else if (!strncmp(sb->buffer, "WARNING:", 8)) { *loglevel = CUPSD_LOG_WARN; message = sb->buffer + 8; } else if (!strncmp(sb->buffer, "NOTICE:", 7)) { *loglevel = CUPSD_LOG_NOTICE; message = sb->buffer + 7; } else if (!strncmp(sb->buffer, "INFO:", 5)) { *loglevel = CUPSD_LOG_INFO; message = sb->buffer + 5; } else if (!strncmp(sb->buffer, "DEBUG:", 6)) { *loglevel = CUPSD_LOG_DEBUG; message = sb->buffer + 6; } else if (!strncmp(sb->buffer, "DEBUG2:", 7)) { *loglevel = CUPSD_LOG_DEBUG2; message = sb->buffer + 7; } else if (!strncmp(sb->buffer, "PAGE:", 5)) { *loglevel = CUPSD_LOG_PAGE; message = sb->buffer + 5; } else if (!strncmp(sb->buffer, "STATE:", 6)) { *loglevel = CUPSD_LOG_STATE; message = sb->buffer + 6; } else if (!strncmp(sb->buffer, "ATTR:", 5)) { *loglevel = CUPSD_LOG_ATTR; message = sb->buffer + 5; } else { *loglevel = CUPSD_LOG_DEBUG; message = sb->buffer; } /* * Skip leading whitespace in the message... */ while (isspace(*message & 255)) message ++; /* * Send it to the log file as needed... */ if (*loglevel > CUPSD_LOG_NONE && (*loglevel != CUPSD_LOG_INFO || LogLevel == CUPSD_LOG_DEBUG2)) { /* * General status message; send it to the error_log file... */ if (message[0] == '[') cupsdLogMessage(*loglevel, "%s", message); else cupsdLogMessage(*loglevel, "%s %s", sb->prefix, message); } else if (*loglevel < CUPSD_LOG_NONE && LogLevel == CUPSD_LOG_DEBUG2) cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s %s", sb->prefix, sb->buffer); /* * Copy the message to the line buffer... */ strlcpy(line, message, linelen); /* * Copy over the buffer data we've used up... */ if (lineptr < sb->buffer + sb->bufused) _cups_strcpy(sb->buffer, lineptr); sb->bufused -= lineptr - sb->buffer; if (sb->bufused < 0) sb->bufused = 0; return (line); }
static int /* O - Exit status */ auto_configure(ppd_file_t *ppd, /* I - PPD file */ const char *user) /* I - Printing user */ { int status = 0; /* Exit status */ ppd_option_t *option; /* Current option in PPD */ ppd_attr_t *attr; /* Query command attribute */ const char *valptr; /* Pointer into attribute value */ char buffer[1024], /* String buffer */ *bufptr; /* Pointer into buffer */ ssize_t bytes; /* Number of bytes read */ int datalen; /* Side-channel data length */ /* * See if the backend supports bidirectional I/O... */ datalen = 1; if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer, &datalen, 30.0) != CUPS_SC_STATUS_OK || buffer[0] != CUPS_SC_BIDI_SUPPORTED) { fputs("DEBUG: Unable to auto-configure PostScript Printer - no " "bidirectional I/O available!\n", stderr); return (1); } /* * Put the printer in PostScript mode... */ begin_ps(ppd, user); /* * (STR #4028) * * As a lot of PPDs contain bad PostScript query code, we need to prevent one * bad query sequence from affecting all auto-configuration. The following * error handler allows us to log PostScript errors to cupsd. */ puts("/cups_handleerror {\n" " $error /newerror false put\n" " (:PostScript error in \") print cups_query_keyword print (\": ) " "print\n" " $error /errorname get 128 string cvs print\n" " (; offending command:) print $error /command get 128 string cvs " "print (\n) print flush\n" "} bind def\n" "errordict /timeout {} put\n" "/cups_query_keyword (?Unknown) def\n"); fflush(stdout); /* * Wait for the printer to become connected... */ do { sleep(1); datalen = 1; } while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED, buffer, &datalen, 5.0) == CUPS_SC_STATUS_OK && !buffer[0]); /* * Then loop through every option in the PPD file and ask for the current * value... */ fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr); for (option = ppdFirstOption(ppd); option; option = ppdNextOption(ppd)) { /* * See if we have a query command for this option... */ snprintf(buffer, sizeof(buffer), "?%s", option->keyword); if ((attr = ppdFindAttr(ppd, buffer, NULL)) == NULL || !attr->value) { fprintf(stderr, "DEBUG: Skipping %s option...\n", option->keyword); continue; } /* * Send the query code to the printer... */ fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword); for (bufptr = buffer, valptr = attr->value; *valptr; valptr ++) { /* * Log the query code, breaking at newlines... */ if (*valptr == '\n') { *bufptr = '\0'; fprintf(stderr, "DEBUG: %s\\n\n", buffer); bufptr = buffer; } else if (*valptr < ' ') { if (bufptr >= (buffer + sizeof(buffer) - 4)) { *bufptr = '\0'; fprintf(stderr, "DEBUG: %s\n", buffer); bufptr = buffer; } if (*valptr == '\r') { *bufptr++ = '\\'; *bufptr++ = 'r'; } else if (*valptr == '\t') { *bufptr++ = '\\'; *bufptr++ = 't'; } else { *bufptr++ = '\\'; *bufptr++ = '0' + ((*valptr / 64) & 7); *bufptr++ = '0' + ((*valptr / 8) & 7); *bufptr++ = '0' + (*valptr & 7); } } else { if (bufptr >= (buffer + sizeof(buffer) - 1)) { *bufptr = '\0'; fprintf(stderr, "DEBUG: %s\n", buffer); bufptr = buffer; } *bufptr++ = *valptr; } } if (bufptr > buffer) { *bufptr = '\0'; fprintf(stderr, "DEBUG: %s\n", buffer); } printf("/cups_query_keyword (?%s) def\n", option->keyword); /* Set keyword for error reporting */ fputs("{ (", stdout); for (valptr = attr->value; *valptr; valptr ++) { if (*valptr == '(' || *valptr == ')' || *valptr == '\\') putchar('\\'); putchar(*valptr); } fputs(") cvx exec } stopped { cups_handleerror } if clear\n", stdout); /* Send query code */ fflush(stdout); datalen = 0; cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer, &datalen, 5.0); /* * Read the response data... */ bufptr = buffer; buffer[0] = '\0'; while ((bytes = cupsBackChannelRead(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer) - 1, 10.0)) > 0) { /* * No newline at the end? Go on reading ... */ bufptr += bytes; *bufptr = '\0'; if (bytes == 0 || (bufptr > buffer && bufptr[-1] != '\r' && bufptr[-1] != '\n')) continue; /* * Trim whitespace and control characters from both ends... */ bytes = bufptr - buffer; for (bufptr --; bufptr >= buffer; bufptr --) if (isspace(*bufptr & 255) || iscntrl(*bufptr & 255)) *bufptr = '\0'; else break; for (bufptr = buffer; isspace(*bufptr & 255) || iscntrl(*bufptr & 255); bufptr ++); if (bufptr > buffer) { _cups_strcpy(buffer, bufptr); bufptr = buffer; } fprintf(stderr, "DEBUG: Got %d bytes.\n", (int)bytes); /* * Skip blank lines... */ if (!buffer[0]) continue; /* * Check the response... */ if ((bufptr = strchr(buffer, ':')) != NULL) { /* * PostScript code for this option in the PPD is broken; show the * interpreter's error message that came back... */ fprintf(stderr, "DEBUG%s\n", bufptr); break; } /* * Verify the result is a valid option choice... */ if (!ppdFindChoice(option, buffer)) { if (!strcasecmp(buffer, "Unknown")) break; bufptr = buffer; buffer[0] = '\0'; continue; } /* * Write out the result and move on to the next option... */ fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, buffer); break; } /* * Printer did not answer this option's query */ if (bytes <= 0) { fprintf(stderr, "DEBUG: No answer to query for option %s within 10 seconds.\n", option->keyword); status = 1; } } /* * Finish the job... */ fflush(stdout); end_ps(ppd); /* * Return... */ if (status) _cupsLangPrintFilter(stderr, "WARNING", _("Unable to configure printer options.")); return (0); }
int /* O - Process ID or 0 */ cupsdStartProcess( const char *command, /* I - Full path to command */ char *argv[], /* I - Command-line arguments */ char *envp[], /* I - Environment */ int infd, /* I - Standard input file descriptor */ int outfd, /* I - Standard output file descriptor */ int errfd, /* I - Standard error file descriptor */ int backfd, /* I - Backchannel file descriptor */ int sidefd, /* I - Sidechannel file descriptor */ int root, /* I - Run as root? */ void *profile, /* I - Security profile to use */ cupsd_job_t *job, /* I - Job associated with process */ int *pid) /* O - Process ID */ { int i; /* Looping var */ const char *exec_path = command; /* Command to be exec'd */ char *real_argv[110], /* Real command-line arguments */ cups_exec[1024], /* Path to "cups-exec" program */ user_str[16], /* User string */ group_str[16], /* Group string */ nice_str[16]; /* FilterNice string */ uid_t user; /* Command UID */ cupsd_proc_t *proc; /* New process record */ #if USE_POSIX_SPAWN posix_spawn_file_actions_t actions; /* Spawn file actions */ posix_spawnattr_t attrs; /* Spawn attributes */ sigset_t defsignals; /* Default signals */ #elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* POSIX signal handler */ #endif /* USE_POSIX_SPAWN */ #if defined(__APPLE__) char processPath[1024], /* CFProcessPath environment variable */ linkpath[1024]; /* Link path for symlinks... */ int linkbytes; /* Bytes for link path */ #endif /* __APPLE__ */ *pid = 0; /* * Figure out the UID for the child process... */ if (RunUser) user = RunUser; else if (root) user = 0; else user = User; /* * Check the permissions of the command we are running... */ if (_cupsFileCheck(command, _CUPS_FILE_CHECK_PROGRAM, !RunUser, cupsdLogFCMessage, job ? job->printer : NULL)) return (0); #if defined(__APPLE__) if (envp) { /* * Add special voodoo magic for OS X - this allows OS X programs to access * their bundle resources properly... */ if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0) { /* * Yes, this is a symlink to the actual program, nul-terminate and * use it... */ linkpath[linkbytes] = '\0'; if (linkpath[0] == '/') snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", linkpath); else snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s", dirname((char *)command), linkpath); } else snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command); envp[0] = processPath; /* Replace <CFProcessPath> string */ } #endif /* __APPLE__ */ /* * Use helper program when we have a sandbox profile... */ #if !USE_POSIX_SPAWN if (profile) #endif /* !USE_POSIX_SPAWN */ { snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin); snprintf(user_str, sizeof(user_str), "%d", user); snprintf(group_str, sizeof(group_str), "%d", Group); snprintf(nice_str, sizeof(nice_str), "%d", FilterNice); real_argv[0] = cups_exec; real_argv[1] = (char *)"-g"; real_argv[2] = group_str; real_argv[3] = (char *)"-n"; real_argv[4] = nice_str; real_argv[5] = (char *)"-u"; real_argv[6] = user_str; real_argv[7] = profile ? profile : "none"; real_argv[8] = (char *)command; for (i = 0; i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 10) && argv[i]; i ++) real_argv[i + 9] = argv[i]; real_argv[i + 9] = NULL; argv = real_argv; exec_path = cups_exec; } if (LogLevel == CUPSD_LOG_DEBUG2) { cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Preparing to start \"%s\", arguments:", command); for (i = 0; argv[i]; i ++) cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]); } #if USE_POSIX_SPAWN /* * Setup attributes and file actions for the spawn... */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes."); sigemptyset(&defsignals); sigaddset(&defsignals, SIGTERM); sigaddset(&defsignals, SIGCHLD); sigaddset(&defsignals, SIGPIPE); posix_spawnattr_init(&attrs); posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF); posix_spawnattr_setpgroup(&attrs, 0); posix_spawnattr_setsigdefault(&attrs, &defsignals); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting file actions."); posix_spawn_file_actions_init(&actions); if (infd != 0) { if (infd < 0) posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDONLY, 0); else posix_spawn_file_actions_adddup2(&actions, infd, 0); } if (outfd != 1) { if (outfd < 0) posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_WRONLY, 0); else posix_spawn_file_actions_adddup2(&actions, outfd, 1); } if (errfd != 2) { if (errfd < 0) posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_WRONLY, 0); else posix_spawn_file_actions_adddup2(&actions, errfd, 2); } if (backfd != 3 && backfd >= 0) posix_spawn_file_actions_adddup2(&actions, backfd, 3); if (sidefd != 4 && sidefd >= 0) posix_spawn_file_actions_adddup2(&actions, sidefd, 4); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Calling posix_spawn."); if (posix_spawn(pid, exec_path, &actions, &attrs, argv, envp ? envp : environ)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno)); *pid = 0; } else cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: pid=%d", (int)*pid); posix_spawn_file_actions_destroy(&actions); posix_spawnattr_destroy(&attrs); #else /* * Block signals before forking... */ cupsdHoldSignals(); if ((*pid = fork()) == 0) { /* * Child process goes here; update stderr as needed... */ if (errfd != 2) { if (errfd < 0) errfd = open("/dev/null", O_WRONLY); if (errfd != 2) { dup2(errfd, 2); close(errfd); } } /* * Put this process in its own process group so that we can kill any child * processes it creates. */ # ifdef HAVE_SETPGID if (!RunUser && setpgid(0, 0)) exit(errno + 100); # else if (!RunUser && setpgrp()) exit(errno + 100); # endif /* HAVE_SETPGID */ /* * Update the remaining file descriptors as needed... */ if (infd != 0) { if (infd < 0) infd = open("/dev/null", O_RDONLY); if (infd != 0) { dup2(infd, 0); close(infd); } } if (outfd != 1) { if (outfd < 0) outfd = open("/dev/null", O_WRONLY); if (outfd != 1) { dup2(outfd, 1); close(outfd); } } if (backfd != 3 && backfd >= 0) { dup2(backfd, 3); close(backfd); fcntl(3, F_SETFL, O_NDELAY); } if (sidefd != 4 && sidefd >= 0) { dup2(sidefd, 4); close(sidefd); fcntl(4, F_SETFL, O_NDELAY); } /* * Change the priority of the process based on the FilterNice setting. * (this is not done for root processes...) */ if (!root) nice(FilterNice); /* * Reset group membership to just the main one we belong to. */ if (!RunUser && setgid(Group)) exit(errno + 100); if (!RunUser && setgroups(1, &Group)) exit(errno + 100); /* * Change user to something "safe"... */ if (!RunUser && user && setuid(user)) exit(errno + 100); /* * Change umask to restrict permissions on created files... */ umask(077); /* * Unblock signals before doing the exec... */ # ifdef HAVE_SIGSET sigset(SIGTERM, SIG_DFL); sigset(SIGCHLD, SIG_DFL); sigset(SIGPIPE, SIG_DFL); # elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); action.sa_handler = SIG_DFL; sigaction(SIGTERM, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigaction(SIGPIPE, &action, NULL); # else signal(SIGTERM, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGPIPE, SIG_DFL); # endif /* HAVE_SIGSET */ cupsdReleaseSignals(); /* * Execute the command; if for some reason this doesn't work, log an error * exit with a non-zero value... */ if (envp) execve(exec_path, argv, envp); else execv(exec_path, argv); exit(errno + 100); } else if (*pid < 0) { /* * Error - couldn't fork a new process! */ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno)); *pid = 0; } cupsdReleaseSignals(); #endif /* USE_POSIX_SPAWN */ if (*pid) { if (!process_array) process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL); if (process_array) { if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL) { proc->pid = *pid; proc->job_id = job ? job->id : 0; _cups_strcpy(proc->name, command); cupsArrayAdd(process_array, proc); } } } cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, " "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, " "profile=%p, job=%p(%d), pid=%p) = %d", command, argv, envp, infd, outfd, errfd, backfd, sidefd, root, profile, job, job ? job->id : 0, pid, *pid); return (*pid); }
int /* O - 1 on success, 0 on error */ translate_messages(cups_array_t *cat, /* I - Message catalog */ const char *lang) /* I - Output language... */ { /* * Google provides a simple translation/language tool for translating * from one language to another. It is far from perfect, however it * can be used to get a basic translation done or update an existing * translation when no other resources are available. * * Translation requests are sent as HTTP POSTs to * "http://translate.google.com/translate_t" with the following form * variables: * * Name Description Value * -------- ---------------------------------- ---------------- * hl Help language? "en" * ie Input encoding "UTF8" * langpair Language pair "en|" + language * oe Output encoding "UTF8" * text Text to translate translation string */ int ret; /* Return value */ _cups_message_t *m; /* Current message */ int tries; /* Number of tries... */ http_t *http; /* HTTP connection */ http_status_t status; /* Status of POST request */ char *idptr, /* Pointer into msgid */ buffer[65536], /* Input/output buffer */ *bufptr, /* Pointer into buffer */ *bufend, /* Pointer to end of buffer */ length[16]; /* Content length */ int bytes; /* Number of bytes read */ /* * Connect to translate.google.com... */ puts("Connecting to translate.google.com..."); if ((http = httpConnect("translate.google.com", 80)) == NULL) { perror("Unable to connect to translate.google.com"); return (0); } /* * Scan the current messages, requesting a translation of any untranslated * messages... */ for (m = (_cups_message_t *)cupsArrayFirst(cat), ret = 1; m; m = (_cups_message_t *)cupsArrayNext(cat)) { /* * Skip messages that are already translated... */ if (m->str && m->str[0]) continue; /* * Encode the form data into the buffer... */ snprintf(buffer, sizeof(buffer), "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", lang); bufptr = buffer + strlen(buffer); bufend = buffer + sizeof(buffer) - 5; for (idptr = m->id; *idptr && bufptr < bufend; idptr ++) if (*idptr == ' ') *bufptr++ = '+'; else if (*idptr < ' ' || *idptr == '%') { sprintf(bufptr, "%%%02X", *idptr & 255); bufptr += 3; } else if (*idptr != '&') *bufptr++ = *idptr; *bufptr++ = '&'; *bufptr = '\0'; sprintf(length, "%d", (int)(bufptr - buffer)); /* * Send the request... */ printf("\"%s\" = ", m->id); fflush(stdout); tries = 0; do { httpClearFields(http); httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/x-www-form-urlencoded"); httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length); if (httpPost(http, "/translate_t")) { httpReconnect(http); httpPost(http, "/translate_t"); } httpWrite2(http, buffer, bufptr - buffer); while ((status = httpUpdate(http)) == HTTP_CONTINUE); if (status != HTTP_OK && status != HTTP_ERROR) httpFlush(http); tries ++; } while (status == HTTP_ERROR && tries < 10); if (status == HTTP_OK) { /* * OK, read the translation back... */ bufptr = buffer; bufend = buffer + sizeof(buffer) - 1; while ((bytes = httpRead2(http, bufptr, bufend - bufptr)) > 0) bufptr += bytes; if (bytes < 0) { /* * Read error, abort! */ puts("READ ERROR!"); ret = 0; break; } *bufptr = '\0'; /* * Find the div containing translation */ if ((bufptr = strstr(buffer, "<div id=result_box")) == NULL) { /* * No textarea, abort! */ puts("NO div id=result_box!"); ret = 0; break; } if ((bufptr = strchr(bufptr, '>')) == NULL) { /* * textarea doesn't end, abort! */ puts("DIV SHORT DATA!"); ret = 0; break; } bufptr ++; if ((bufend = strstr(bufptr, "</div>")) == NULL) { /* * textarea doesn't close, abort! */ puts("/DIV SHORT DATA!"); ret = 0; break; } *bufend = '\0'; /* * Copy the translation... */ m->str = strdup(bufptr); /* * Convert character entities to regular chars... */ for (bufptr = strchr(m->str, '&'); bufptr; bufptr = strchr(bufptr + 1, '&')) { if (!strncmp(bufptr, "<", 4)) { *bufptr = '<'; _cups_strcpy(bufptr + 1, bufptr + 4); } else if (!strncmp(bufptr, ">", 4)) { *bufptr = '>'; _cups_strcpy(bufptr + 1, bufptr + 4); } else if (!strncmp(bufptr, "&", 5)) _cups_strcpy(bufptr + 1, bufptr + 5); } printf("\"%s\"\n", m->str); } else if (status == HTTP_ERROR) { printf("NETWORK ERROR (%s)!\n", strerror(httpError(http))); ret = 0; break; } else { printf("HTTP ERROR %d!\n", status); ret = 0; break; } } httpClose(http); return (ret); }
ipp_t * /* O - Attributes */ serverLoadAttributes( const char *filename, /* I - File to load */ char **authtype, /* O - Authentication type, if any */ char **command, /* O - Command to run, if any */ char **device_uri, /* O - Device URI, if any */ char **make, /* O - Manufacturer */ char **model, /* O - Model */ char **proxy_user) /* O - Proxy user, if any */ { ipp_t *attrs; /* Attributes to return */ cups_file_t *fp; /* File */ int linenum = 0; /* Current line number */ char attr[128], /* Attribute name */ token[1024], /* Token from file */ *tokenptr; /* Pointer into token */ ipp_tag_t value; /* Current value type */ ipp_attribute_t *attrptr; /* Attribute pointer */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { serverLog(SERVER_LOGLEVEL_ERROR, "Unable to open \"%s\": %s", filename, strerror(errno)); return (NULL); } attrs = ippNew(); while (get_token(fp, token, sizeof(token), &linenum) != NULL) { if (!_cups_strcasecmp(token, "ATTR")) { /* * Attribute... */ if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value tag on line %d of \"%s\".", linenum, filename); goto load_error; } if ((value = ippTagValue(token)) == IPP_TAG_ZERO) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR value tag \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if (!get_token(fp, attr, sizeof(attr), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR name on line %d of \"%s\".", linenum, filename); goto load_error; } if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value on line %d of \"%s\".", linenum, filename); goto load_error; } attrptr = NULL; switch (value) { case IPP_TAG_BOOLEAN : if (!_cups_strcasecmp(token, "true")) attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, 1); else attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, (char)atoi(token)); break; case IPP_TAG_INTEGER : case IPP_TAG_ENUM : if (!strchr(token, ',')) attrptr = ippAddInteger(attrs, IPP_TAG_PRINTER, value, attr, (int)strtol(token, &tokenptr, 0)); else { int values[100], /* Values */ num_values = 1; /* Number of values */ values[0] = (int)strtol(token, &tokenptr, 10); while (tokenptr && *tokenptr && num_values < (int)(sizeof(values) / sizeof(values[0]))) { if (*tokenptr == ',') tokenptr ++; else if (!isdigit(*tokenptr & 255) && *tokenptr != '-') break; values[num_values] = (int)strtol(tokenptr, &tokenptr, 0); num_values ++; } attrptr = ippAddIntegers(attrs, IPP_TAG_PRINTER, value, attr, num_values, values); } if (!tokenptr || *tokenptr) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad %s value \"%s\" on line %d of \"%s\".", ippTagString(value), token, linenum, filename); goto load_error; } break; case IPP_TAG_RESOLUTION : { int xres, /* X resolution */ yres; /* Y resolution */ ipp_res_t units; /* Units */ char *start, /* Start of value */ *ptr, /* Pointer into value */ *next = NULL; /* Next value */ for (start = token; start; start = next) { xres = yres = (int)strtol(start, (char **)&ptr, 10); if (ptr > start && xres > 0) { if (*ptr == 'x') yres = (int)strtol(ptr + 1, (char **)&ptr, 10); } if (ptr && (next = strchr(ptr, ',')) != NULL) *next++ = '\0'; if (ptr <= start || xres <= 0 || yres <= 0 || !ptr || (_cups_strcasecmp(ptr, "dpi") && _cups_strcasecmp(ptr, "dpc") && _cups_strcasecmp(ptr, "dpcm") && _cups_strcasecmp(ptr, "other"))) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad resolution value \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if (!_cups_strcasecmp(ptr, "dpc") || !_cups_strcasecmp(ptr, "dpcm")) units = IPP_RES_PER_CM; else units = IPP_RES_PER_INCH; if (attrptr) ippSetResolution(attrs, &attrptr, ippGetCount(attrptr), units, xres, yres); else attrptr = ippAddResolution(attrs, IPP_TAG_PRINTER, attr, units, xres, yres); } } break; case IPP_TAG_RANGE : { int lowers[4], /* Lower value */ uppers[4], /* Upper values */ num_vals; /* Number of values */ num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d", lowers + 0, uppers + 0, lowers + 1, uppers + 1, lowers + 2, uppers + 2, lowers + 3, uppers + 3); if ((num_vals & 1) || num_vals == 0) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad rangeOfInteger value \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } attrptr = ippAddRanges(attrs, IPP_TAG_PRINTER, attr, num_vals / 2, lowers, uppers); } break; case IPP_TAG_BEGIN_COLLECTION : if (!strcmp(token, "{")) { ipp_t *col = get_collection(fp, filename, &linenum); /* Collection value */ if (col) { attrptr = ippAddCollection(attrs, IPP_TAG_PRINTER, attr, col); ippDelete(col); } else exit(1); } else { serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR collection value on line %d of \"%s\".", linenum, filename); goto load_error; } do { ipp_t *col; /* Collection value */ long pos = cupsFileTell(fp); /* Save position of file */ if (!get_token(fp, token, sizeof(token), &linenum)) break; if (strcmp(token, ",")) { cupsFileSeek(fp, pos); break; } if (!get_token(fp, token, sizeof(token), &linenum) || strcmp(token, "{")) { serverLog(SERVER_LOGLEVEL_ERROR, "Unexpected \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if ((col = get_collection(fp, filename, &linenum)) == NULL) break; ippSetCollection(attrs, &attrptr, ippGetCount(attrptr), col); } while (!strcmp(token, "{")); break; case IPP_TAG_STRING : attrptr = ippAddOctetString(attrs, IPP_TAG_PRINTER, attr, token, (int)strlen(token)); break; default : serverLog(SERVER_LOGLEVEL_ERROR, "Unsupported ATTR value tag %s on line %d of \"%s\".", ippTagString(value), linenum, filename); goto load_error; case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : case IPP_TAG_TEXT : case IPP_TAG_NAME : case IPP_TAG_KEYWORD : case IPP_TAG_URI : case IPP_TAG_URISCHEME : case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : if (!strchr(token, ',')) attrptr = ippAddString(attrs, IPP_TAG_PRINTER, value, attr, NULL, token); else { /* * Multiple string values... */ int num_values; /* Number of values */ char *values[100], /* Values */ *ptr; /* Pointer to next value */ values[0] = token; num_values = 1; for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ',')) { if (ptr > token && ptr[-1] == '\\') _cups_strcpy(ptr - 1, ptr); else { *ptr++ = '\0'; values[num_values] = ptr; num_values ++; if (num_values >= (int)(sizeof(values) / sizeof(values[0]))) break; } } attrptr = ippAddStrings(attrs, IPP_TAG_PRINTER, value, attr, num_values, NULL, (const char **)values); } break; } if (!attrptr) { serverLog(SERVER_LOGLEVEL_ERROR, "Unable to add attribute on line %d of \"%s\": %s", linenum, filename, cupsLastErrorString()); goto load_error; } } else if (!_cups_strcasecmp(token, "AUTHTYPE") && authtype) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing AUTHTYPE value on line %d of \"%s\".", linenum, filename); goto load_error; } *authtype = strdup(token); } else if (!_cups_strcasecmp(token, "COMMAND") && command) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing COMMAND value on line %d of \"%s\".", linenum, filename); goto load_error; } *command = strdup(token); } else if (!_cups_strcasecmp(token, "DEVICEURI") && device_uri) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing DEVICE-URI value on line %d of \"%s\".", linenum, filename); goto load_error; } *device_uri = strdup(token); } else if (!_cups_strcasecmp(token, "MAKE") && make) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing MAKE value on line %d of \"%s\".", linenum, filename); goto load_error; } *make = strdup(token); } else if (!_cups_strcasecmp(token, "MODEL") && model) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing MODEL value on line %d of \"%s\".", linenum, filename); goto load_error; } *model = strdup(token); } else if (!_cups_strcasecmp(token, "PROXYUSER") && proxy_user) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing PROXY-USER value on line %d of \"%s\".", linenum, filename); goto load_error; } *proxy_user = strdup(token); } else { serverLog(SERVER_LOGLEVEL_ERROR, "Unknown directive \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } } cupsFileClose(fp); return (attrs); /* * If we get here something bad happened... */ load_error: cupsFileClose(fp); ippDelete(attrs); return (NULL); }
char * /* O - Line read or @code NULL@ on end of file or error */ cupsFileGetConf(cups_file_t *fp, /* I - CUPS file */ char *buf, /* O - String buffer */ size_t buflen, /* I - Size of string buffer */ char **value, /* O - Pointer to value */ int *linenum) /* IO - Current line number */ { char *ptr; /* Pointer into line */ /* * Range check input... */ DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen, value, linenum)); if (!fp || (fp->mode != 'r' && fp->mode != 's') || !buf || buflen < 2 || !value) { if (value) *value = NULL; return (NULL); } /* * Read the next non-comment line... */ *value = NULL; while (cupsFileGets(fp, buf, buflen)) { (*linenum) ++; /* * Strip any comments... */ if ((ptr = strchr(buf, '#')) != NULL) { if (ptr > buf && ptr[-1] == '\\') { // Unquote the #... _cups_strcpy(ptr - 1, ptr); } else { // Strip the comment and any trailing whitespace... while (ptr > buf) { if (!_cups_isspace(ptr[-1])) break; ptr --; } *ptr = '\0'; } } /* * Strip leading whitespace... */ for (ptr = buf; _cups_isspace(*ptr); ptr ++); if (ptr > buf) _cups_strcpy(buf, ptr); /* * See if there is anything left... */ if (buf[0]) { /* * Yes, grab any value and return... */ for (ptr = buf; *ptr; ptr ++) if (_cups_isspace(*ptr)) break; if (*ptr) { /* * Have a value, skip any other spaces... */ while (_cups_isspace(*ptr)) *ptr++ = '\0'; if (*ptr) *value = ptr; /* * Strip trailing whitespace and > for lines that begin with <... */ ptr += strlen(ptr) - 1; if (buf[0] == '<' && *ptr == '>') *ptr-- = '\0'; else if (buf[0] == '<' && *ptr != '>') { /* * Syntax error... */ *value = NULL; return (buf); } while (ptr > *value && _cups_isspace(*ptr)) *ptr-- = '\0'; } /* * Return the line... */ return (buf); } } return (NULL); }
char * /* O - Normalized make-and-model string or NULL on error */ _ppdNormalizeMakeAndModel( const char *make_and_model, /* I - Original make-and-model string */ char *buffer, /* I - String buffer */ size_t bufsize) /* I - Size of string buffer */ { char *bufptr; /* Pointer into buffer */ if (!make_and_model || !buffer || bufsize < 1) { if (buffer) *buffer = '\0'; return (NULL); } /* * Skip leading whitespace... */ while (_cups_isspace(*make_and_model)) make_and_model ++; /* * Remove parenthesis and add manufacturers as needed... */ if (make_and_model[0] == '(') { strlcpy(buffer, make_and_model + 1, bufsize); if ((bufptr = strrchr(buffer, ')')) != NULL) *bufptr = '\0'; } else if (!_cups_strncasecmp(make_and_model, "XPrint", 6)) { /* * Xerox XPrint... */ snprintf(buffer, bufsize, "Xerox %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "Eastman", 7)) { /* * Kodak... */ snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7); } else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11)) { /* * Apple LaserWriter... */ snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11); } else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10)) { /* * Seiko... */ snprintf(buffer, bufsize, "Seiko %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "fiery", 5)) { /* * EFI... */ snprintf(buffer, bufsize, "EFI %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "ps ", 3) || !_cups_strncasecmp(make_and_model, "colorpass", 9)) { /* * Canon... */ snprintf(buffer, bufsize, "Canon %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "primera", 7)) { /* * Fargo... */ snprintf(buffer, bufsize, "Fargo %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "designjet", 9) || !_cups_strncasecmp(make_and_model, "deskjet", 7)) { /* * HP... */ snprintf(buffer, bufsize, "HP %s", make_and_model); } else strlcpy(buffer, make_and_model, bufsize); /* * Clean up the make... */ if (!_cups_strncasecmp(buffer, "agfa", 4)) { /* * Replace with AGFA (all uppercase)... */ buffer[0] = 'A'; buffer[1] = 'G'; buffer[2] = 'F'; buffer[3] = 'A'; } else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19)) { /* * Just put "HP" on the front... */ buffer[0] = 'H'; buffer[1] = 'P'; _cups_strcpy(buffer + 2, buffer + 18); } else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16)) { /* * Just put "HP" on the front... */ buffer[0] = 'H'; buffer[1] = 'P'; _cups_strcpy(buffer + 2, buffer + 15); } else if (!_cups_strncasecmp(buffer, "Lexmark International", 21)) { /* * Strip "International"... */ _cups_strcpy(buffer + 8, buffer + 21); } else if (!_cups_strncasecmp(buffer, "herk", 4)) { /* * Replace with LHAG... */ buffer[0] = 'L'; buffer[1] = 'H'; buffer[2] = 'A'; buffer[3] = 'G'; } else if (!_cups_strncasecmp(buffer, "linotype", 8)) { /* * Replace with LHAG... */ buffer[0] = 'L'; buffer[1] = 'H'; buffer[2] = 'A'; buffer[3] = 'G'; _cups_strcpy(buffer + 4, buffer + 8); } /* * Remove trailing whitespace and return... */ for (bufptr = buffer + strlen(buffer) - 1; bufptr >= buffer && _cups_isspace(*bufptr); bufptr --); bufptr[1] = '\0'; return (buffer[0] ? buffer : NULL); }
static int /* O - 0 on success, -1 on error */ get_device(cupsd_backend_t *backend) /* I - Backend to read from */ { char line[2048], /* Line from backend */ temp[2048], /* Copy of line */ *ptr, /* Pointer into line */ *dclass, /* Device class */ *uri, /* Device URI */ *make_model, /* Make and model */ *info, /* Device info */ *device_id, /* 1284 device ID */ *location; /* Physical location */ if (cupsFileGets(backend->pipe, line, sizeof(line))) { /* * Each line is of the form: * * class URI "make model" "name" ["1284 device ID"] ["location"] */ strlcpy(temp, line, sizeof(temp)); /* * device-class */ dclass = temp; for (ptr = temp; *ptr; ptr ++) if (isspace(*ptr & 255)) break; while (isspace(*ptr & 255)) *ptr++ = '\0'; /* * device-uri */ if (!*ptr) goto error; for (uri = ptr; *ptr; ptr ++) if (isspace(*ptr & 255)) break; while (isspace(*ptr & 255)) *ptr++ = '\0'; /* * device-make-and-model */ if (*ptr != '\"') goto error; for (ptr ++, make_model = ptr; *ptr && *ptr != '\"'; ptr ++) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } if (*ptr != '\"') goto error; for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0'); /* * device-info */ if (*ptr != '\"') goto error; for (ptr ++, info = ptr; *ptr && *ptr != '\"'; ptr ++) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } if (*ptr != '\"') goto error; for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0'); /* * device-id */ if (*ptr == '\"') { for (ptr ++, device_id = ptr; *ptr && *ptr != '\"'; ptr ++) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } if (*ptr != '\"') goto error; for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0'); /* * device-location */ if (*ptr == '\"') { for (ptr ++, location = ptr; *ptr && *ptr != '\"'; ptr ++) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } if (*ptr != '\"') goto error; *ptr = '\0'; } else location = NULL; } else { device_id = NULL; location = NULL; } /* * Add the device to the array of available devices... */ if (!add_device(dclass, make_model, info, uri, device_id, location)) fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri); return (0); } /* * End of file... */ cupsFileClose(backend->pipe); backend->pipe = NULL; return (-1); /* * Bad format; strip trailing newline and write an error message. */ error: if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n", backend->name, line); return (0); }
static void add_printer_filter( const char *command, /* I - Command name */ mime_t *mime, /* I - MIME database */ mime_type_t *filtertype, /* I - Printer or prefilter MIME type */ const char *filter) /* I - Filter to add */ { char super[MIME_MAX_SUPER], /* Super-type for filter */ type[MIME_MAX_TYPE], /* Type for filter */ dsuper[MIME_MAX_SUPER], /* Destination super-type for filter */ dtype[MIME_MAX_TYPE], /* Destination type for filter */ dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2], /* Destination super/type */ program[1024]; /* Program/filter name */ int cost; /* Cost of filter */ size_t maxsize = 0; /* Maximum supported file size */ mime_type_t *temptype, /* MIME type looping var */ *desttype; /* Destination MIME type */ mime_filter_t *filterptr; /* MIME filter */ /* * Parse the filter string; it should be in one of the following formats: * * source/type cost program * source/type cost maxsize(nnnn) program * source/type dest/type cost program * source/type dest/type cost maxsize(nnnn) program */ if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, dsuper, dtype, &cost, program) == 6) { snprintf(dest, sizeof(dest), "%s/%s/%s", filtertype->type, dsuper, dtype); if ((desttype = mimeType(mime, "printer", dest)) == NULL) desttype = mimeAddType(mime, "printer", dest); } else { if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost, program) == 4) { desttype = filtertype; } else { _cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"."), command, filter); return; } } if (!strncmp(program, "maxsize(", 8)) { char *ptr; /* Pointer into maxsize(nnnn) program */ maxsize = (size_t)strtoll(program + 8, &ptr, 10); if (*ptr != ')') { printf("testmime: Invalid filter string \"%s\".\n", filter); return; } ptr ++; while (_cups_isspace(*ptr)) ptr ++; _cups_strcpy(program, ptr); } /* * See if the filter program exists; if not, stop the printer and flag * the error! */ if (strcmp(program, "-")) { char filename[1024]; /* Full path to program */ if (program[0] == '/') strlcpy(filename, program, sizeof(filename)); else snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program); if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !geteuid(), check_cb, (void *)command)) return; } /* * Add the filter to the MIME database, supporting wildcards as needed... */ for (temptype = mimeFirstType(mime); temptype; temptype = mimeNextType(mime)) if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) || !_cups_strcasecmp(temptype->super, super)) && (type[0] == '*' || !_cups_strcasecmp(temptype->type, type))) { if (desttype != filtertype) { filterptr = mimeAddFilter(mime, temptype, desttype, cost, program); if (!mimeFilterLookup(mime, desttype, filtertype)) mimeAddFilter(mime, desttype, filtertype, 0, "-"); } else filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program); if (filterptr) filterptr->maxsize = maxsize; } }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { http_t *http; /* Connection to server */ char line[1024], /* Input line from user */ *params; /* Pointer to parameters */ _cupsSetLocale(argv); /* * Connect to the scheduler... */ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (argc > 1) { /* * Process a single command on the command-line... */ do_command(http, argv[1], argv[2]); } else { /* * Do the command prompt thing... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no-newline version */ while (fgets(line, sizeof(line), stdin) != NULL) { /* * Strip trailing whitespace... */ for (params = line + strlen(line) - 1; params >= line;) if (!isspace(*params & 255)) break; else *params-- = '\0'; /* * Strip leading whitespace... */ for (params = line; isspace(*params & 255); params ++); if (params > line) _cups_strcpy(line, params); if (!line[0]) { /* * Nothing left, just show a prompt... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ continue; } /* * Find any options in the string... */ for (params = line; *params != '\0'; params ++) if (isspace(*params & 255)) break; /* * Remove whitespace between the command and parameters... */ while (isspace(*params & 255)) *params++ = '\0'; /* * The "quit" and "exit" commands exit; otherwise, process as needed... */ if (!compare_strings(line, "quit", 1) || !compare_strings(line, "exit", 2)) break; if (*params == '\0') do_command(http, line, NULL); else do_command(http, line, params); /* * Put another prompt out to the user... */ _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ } } /* * Close the connection to the server and return... */ httpClose(http); return (0); }
static void fix_make_model( char *make_model, /* I - New make-and-model string */ const char *old_make_model, /* I - Old make-and-model string */ int make_model_size) /* I - Size of new string buffer */ { char *mmptr; /* Pointer into make-and-model string */ /* * Fix some common problems with the make-and-model string so * that printer driver detection works better... */ if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15)) { /* * Strip leading Hewlett-Packard and hp prefixes and replace * with a single HP manufacturer prefix... */ mmptr = (char *)old_make_model + 15; while (isspace(*mmptr & 255)) mmptr ++; if (!_cups_strncasecmp(mmptr, "hp", 2)) { mmptr += 2; while (isspace(*mmptr & 255)) mmptr ++; } make_model[0] = 'H'; make_model[1] = 'P'; make_model[2] = ' '; strlcpy(make_model + 3, mmptr, (size_t)make_model_size - 3); } else if (!_cups_strncasecmp(old_make_model, "deskjet", 7)) snprintf(make_model, (size_t)make_model_size, "HP DeskJet%s", old_make_model + 7); else if (!_cups_strncasecmp(old_make_model, "officejet", 9)) snprintf(make_model, (size_t)make_model_size, "HP OfficeJet%s", old_make_model + 9); else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11)) snprintf(make_model, (size_t)make_model_size, "EPSON Stylus Pro %s", old_make_model + 11); else strlcpy(make_model, old_make_model, (size_t)make_model_size); if ((mmptr = strstr(make_model, ", Inc.,")) != NULL) { /* * Strip inc. from name, e.g. "Tektronix, Inc., Phaser 560" * becomes "Tektronix Phaser 560"... */ _cups_strcpy(mmptr, mmptr + 7); } if ((mmptr = strstr(make_model, " Network")) != NULL) { /* * Drop unnecessary informational text, e.g. "Xerox DocuPrint N2025 * Network LaserJet - 2.12" becomes "Xerox DocuPrint N2025"... */ *mmptr = '\0'; } if ((mmptr = strchr(make_model, ',')) != NULL) { /* * Drop anything after a trailing comma... */ *mmptr = '\0'; } }
static void ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ { int i; /* Looping var */ ppd_const_t *oldconst; /* Current UIConstraints data */ ppd_attr_t *constattr; /* Current cupsUIConstraints attribute */ _ppd_cups_uiconsts_t *consts; /* Current cupsUIConstraints data */ _ppd_cups_uiconst_t *constptr; /* Current constraint */ ppd_group_t *installable; /* Installable options group */ const char *vptr; /* Pointer into constraint value */ char option[PPD_MAX_NAME], /* Option name/MainKeyword */ choice[PPD_MAX_NAME], /* Choice/OptionKeyword */ *ptr; /* Pointer into option or choice */ DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd)); /* * Create an array to hold the constraint data... */ ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL); /* * Find the installable options group if it exists... */ for (i = ppd->num_groups, installable = ppd->groups; i > 0; i --, installable ++) if (!_cups_strcasecmp(installable->name, "InstallableOptions")) break; if (i <= 0) installable = NULL; /* * Load old-style [Non]UIConstraints data... */ for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++) { /* * Weed out nearby duplicates, since the PPD spec requires that you * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"... */ if (i > 1 && !_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) && !_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) && !_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) && !_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1)) continue; /* * Allocate memory... */ if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL) { DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "UIConstraints!"); return; } if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL) { free(consts); DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "UIConstraints!"); return; } /* * Fill in the information... */ consts->num_constraints = 2; consts->constraints = constptr; if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) && !_cups_strcasecmp(oldconst->choice1, "True")) { constptr[0].option = ppdFindOption(ppd, oldconst->option1 + 6); constptr[0].choice = ppdFindChoice(constptr[0].option, "Custom"); constptr[0].installable = 0; } else { constptr[0].option = ppdFindOption(ppd, oldconst->option1); constptr[0].choice = ppdFindChoice(constptr[0].option, oldconst->choice1); constptr[0].installable = ppd_is_installable(installable, oldconst->option1); } if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", oldconst->option1, oldconst->choice1)); free(consts->constraints); free(consts); continue; } if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) && !_cups_strcasecmp(oldconst->choice2, "True")) { constptr[1].option = ppdFindOption(ppd, oldconst->option2 + 6); constptr[1].choice = ppdFindChoice(constptr[1].option, "Custom"); constptr[1].installable = 0; } else { constptr[1].option = ppdFindOption(ppd, oldconst->option2); constptr[1].choice = ppdFindChoice(constptr[1].option, oldconst->choice2); constptr[1].installable = ppd_is_installable(installable, oldconst->option2); } if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", oldconst->option2, oldconst->choice2)); free(consts->constraints); free(consts); continue; } consts->installable = constptr[0].installable || constptr[1].installable; /* * Add it to the constraints array... */ cupsArrayAdd(ppd->cups_uiconstraints, consts); } /* * Then load new-style constraints... */ for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL); constattr; constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL)) { if (!constattr->value) { DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!"); continue; } for (i = 0, vptr = strchr(constattr->value, '*'); vptr; i ++, vptr = strchr(vptr + 1, '*')); if (i == 0) { DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!"); continue; } if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL) { DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "cupsUIConstraints!"); return; } if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL) { free(consts); DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "cupsUIConstraints!"); return; } consts->num_constraints = i; consts->constraints = constptr; strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver)); for (i = 0, vptr = strchr(constattr->value, '*'); vptr; i ++, vptr = strchr(vptr, '*'), constptr ++) { /* * Extract "*Option Choice" or just "*Option"... */ for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++) if (ptr < (option + sizeof(option) - 1)) *ptr++ = *vptr; *ptr = '\0'; while (_cups_isspace(*vptr)) vptr ++; if (*vptr == '*') choice[0] = '\0'; else { for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++) if (ptr < (choice + sizeof(choice) - 1)) *ptr++ = *vptr; *ptr = '\0'; } if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True")) { _cups_strcpy(option, option + 6); strlcpy(choice, "Custom", sizeof(choice)); } constptr->option = ppdFindOption(ppd, option); constptr->choice = ppdFindChoice(constptr->option, choice); constptr->installable = ppd_is_installable(installable, option); consts->installable |= constptr->installable; if (!constptr->option || (!constptr->choice && choice[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", option, choice)); break; } } if (!vptr) cupsArrayAdd(ppd->cups_uiconstraints, consts); else { free(consts->constraints); free(consts); } } }
static void query_callback( DNSServiceRef sdRef, /* I - Service reference */ DNSServiceFlags flags, /* I - Data flags */ uint32_t interfaceIndex, /* I - Interface */ DNSServiceErrorType errorCode, /* I - Error, if any */ const char *fullName, /* I - Full service name */ uint16_t rrtype, /* I - Record type */ uint16_t rrclass, /* I - Record class */ uint16_t rdlen, /* I - Length of record data */ const void *rdata, /* I - Record data */ uint32_t ttl, /* I - Time-to-live */ void *context) /* I - Device */ { # else /* * 'query_callback()' - Process query data. */ static void query_callback( AvahiRecordBrowser *browser, /* I - Record browser */ AvahiIfIndex interfaceIndex, /* I - Interface index (unused) */ AvahiProtocol protocol, /* I - Network protocol (unused) */ AvahiBrowserEvent event, /* I - What happened? */ const char *fullName, /* I - Service name */ uint16_t rrclass, /* I - Record class */ uint16_t rrtype, /* I - Record type */ const void *rdata, /* I - TXT record */ size_t rdlen, /* I - Length of TXT record */ AvahiLookupResultFlags flags, /* I - Flags */ void *context) /* I - Device */ { AvahiClient *client = avahi_record_browser_get_client(browser); /* Client information */ # endif /* HAVE_DNSSD */ char *ptr; /* Pointer into string */ cups_device_t *device = (cups_device_t *)context; /* Device */ const uint8_t *data, /* Pointer into data */ *datanext, /* Next key/value pair */ *dataend; /* End of entire TXT record */ uint8_t datalen; /* Length of current key/value pair */ char key[256], /* Key string */ value[256], /* Value string */ make_and_model[512], /* Manufacturer and model */ model[256], /* Model */ pdl[256], /* PDL */ device_id[2048]; /* 1284 device ID */ # ifdef HAVE_DNSSD fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, " "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", " "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, " "context=%p)\n", sdRef, flags, interfaceIndex, errorCode, fullName, rrtype, rrclass, rdlen, rdata, ttl, context); /* * Only process "add" data... */ if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd)) return; # else fprintf(stderr, "DEBUG2: query_callback(browser=%p, interfaceIndex=%d, " "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, " "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)\n", browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context); /* * Only process "add" data... */ if (event != AVAHI_BROWSER_NEW) { if (event == AVAHI_BROWSER_FAILURE) fprintf(stderr, "ERROR: %s\n", avahi_strerror(avahi_client_errno(client))); return; } # endif /* HAVE_DNSSD */ /* * Pull out the priority and make and model from the TXT * record and save it... */ device_id[0] = '\0'; make_and_model[0] = '\0'; pdl[0] = '\0'; strlcpy(model, "Unknown", sizeof(model)); for (data = rdata, dataend = data + rdlen; data < dataend; data = datanext) { /* * Read a key/value pair starting with an 8-bit length. Since the * length is 8 bits and the size of the key/value buffers is 256, we * don't need to check for overflow... */ datalen = *data++; if (!datalen || (data + datalen) > dataend) break; datanext = data + datalen; for (ptr = key; data < datanext && *data != '='; data ++) *ptr++ = (char)*data; *ptr = '\0'; if (data < datanext && *data == '=') { data ++; if (data < datanext) memcpy(value, data, (size_t)(datanext - data)); value[datanext - data] = '\0'; fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n", key, value); } else { fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n", key); continue; } if (!_cups_strncasecmp(key, "usb_", 4)) { /* * Add USB device ID information... */ ptr = device_id + strlen(device_id); snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "%s:%s;", key + 4, value); } if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") || !_cups_strcasecmp(key, "usb_MANUFACTURER")) strlcpy(make_and_model, value, sizeof(make_and_model)); else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL")) strlcpy(model, value, sizeof(model)); else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript")) { if (value[0] == '(') { /* * Strip parenthesis... */ if ((ptr = value + strlen(value) - 1) > value && *ptr == ')') *ptr = '\0'; strlcpy(model, value + 1, sizeof(model)); } else strlcpy(model, value, sizeof(model)); } else if (!_cups_strcasecmp(key, "ty")) { strlcpy(model, value, sizeof(model)); if ((ptr = strchr(model, ',')) != NULL) *ptr = '\0'; } else if (!_cups_strcasecmp(key, "pdl")) strlcpy(pdl, value, sizeof(pdl)); else if (!_cups_strcasecmp(key, "priority")) device->priority = atoi(value); else if ((device->type == CUPS_DEVICE_IPP || device->type == CUPS_DEVICE_IPPS || device->type == CUPS_DEVICE_PRINTER) && !_cups_strcasecmp(key, "printer-type")) { /* * This is a CUPS printer! */ device->cups_shared = 1; if (device->type == CUPS_DEVICE_PRINTER) device->sent = 1; } else if (!_cups_strcasecmp(key, "UUID")) device->uuid = strdup(value); } if (device->device_id) free(device->device_id); if (!device_id[0] && strcmp(model, "Unknown")) { if (make_and_model[0]) snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", make_and_model, model); else if (!_cups_strncasecmp(model, "designjet ", 10)) snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", model + 10); else if (!_cups_strncasecmp(model, "stylus ", 7)) snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", model + 7); else if ((ptr = strchr(model, ' ')) != NULL) { /* * Assume the first word is the make... */ memcpy(make_and_model, model, (size_t)(ptr - model)); make_and_model[ptr - model] = '\0'; snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", make_and_model, ptr + 1); } } if (device_id[0] && !strstr(device_id, "CMD:") && !strstr(device_id, "COMMAND SET:") && (strstr(pdl, "application/pdf") || strstr(pdl, "application/postscript") || strstr(pdl, "application/vnd.hp-PCL") || strstr(pdl, "image/"))) { value[0] = '\0'; if (strstr(pdl, "application/pdf")) strlcat(value, ",PDF", sizeof(value)); if (strstr(pdl, "application/postscript")) strlcat(value, ",PS", sizeof(value)); if (strstr(pdl, "application/vnd.hp-PCL")) strlcat(value, ",PCL", sizeof(value)); for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/")) { char *valptr = value + strlen(value); /* Pointer into value */ if (valptr < (value + sizeof(value) - 1)) *valptr++ = ','; ptr += 6; while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.') { if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1)) *valptr++ = (char)toupper(*ptr++ & 255); else break; } *valptr = '\0'; } ptr = device_id + strlen(device_id); snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "CMD:%s;", value + 1); } if (device_id[0]) device->device_id = strdup(device_id); else device->device_id = NULL; if (device->make_and_model) free(device->make_and_model); if (make_and_model[0]) { strlcat(make_and_model, " ", sizeof(make_and_model)); strlcat(make_and_model, model, sizeof(make_and_model)); if (!_cups_strncasecmp(make_and_model, "EPSON EPSON ", 12)) _cups_strcpy(make_and_model, make_and_model + 6); else if (!_cups_strncasecmp(make_and_model, "HP HP ", 6)) _cups_strcpy(make_and_model, make_and_model + 3); else if (!_cups_strncasecmp(make_and_model, "Lexmark International Lexmark ", 30)) _cups_strcpy(make_and_model, make_and_model + 22); device->make_and_model = strdup(make_and_model); } else device->make_and_model = strdup(model); }
static void add_ppd_filter(mime_t *mime, /* I - MIME database */ mime_type_t *filtertype, /* I - Filter or prefilter MIME type */ const char *filter) /* I - Filter to add */ { char super[MIME_MAX_SUPER], /* Super-type for filter */ type[MIME_MAX_TYPE], /* Type for filter */ dsuper[MIME_MAX_SUPER], /* Destination super-type for filter */ dtype[MIME_MAX_TYPE], /* Destination type for filter */ dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2], /* Destination super/type */ program[1024]; /* Program/filter name */ int cost; /* Cost of filter */ size_t maxsize = 0; /* Maximum supported file size */ mime_type_t *temptype, /* MIME type looping var */ *desttype; /* Destination MIME type */ mime_filter_t *filterptr; /* MIME filter */ DEBUG_printf(("add_ppd_filter(mime=%p, filtertype=%p(%s/%s), filter=\"%s\")", mime, filtertype, filtertype->super, filtertype->type, filter)); /* * Parse the filter string; it should be in one of the following formats: * * source/type cost program * source/type cost maxsize(nnnn) program * source/type dest/type cost program * source/type dest/type cost maxsize(nnnn) program */ if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, dsuper, dtype, &cost, program) == 6) { snprintf(dest, sizeof(dest), "test/%s/%s", dsuper, dtype); if ((desttype = mimeType(mime, "printer", dest)) == NULL) desttype = mimeAddType(mime, "printer", dest); } else { if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost, program) == 4) { desttype = filtertype; } else { printf("testmime: Invalid filter string \"%s\".\n", filter); return; } } if (!strncmp(program, "maxsize(", 8)) { char *ptr; /* Pointer into maxsize(nnnn) program */ maxsize = strtoll(program + 8, &ptr, 10); if (*ptr != ')') { printf("testmime: Invalid filter string \"%s\".\n", filter); return; } ptr ++; while (_cups_isspace(*ptr)) ptr ++; _cups_strcpy(program, ptr); } /* * Add the filter to the MIME database, supporting wildcards as needed... */ for (temptype = mimeFirstType(mime); temptype; temptype = mimeNextType(mime)) if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) || !_cups_strcasecmp(temptype->super, super)) && (type[0] == '*' || !_cups_strcasecmp(temptype->type, type))) { if (desttype != filtertype) { DEBUG_printf(("add_ppd_filter: Adding filter %s/%s %s/%s %d %s", temptype->super, temptype->type, desttype->super, desttype->type, cost, program)); filterptr = mimeAddFilter(mime, temptype, desttype, cost, program); if (!mimeFilterLookup(mime, desttype, filtertype)) { DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s 0 -", desttype->super, desttype->type, filtertype->super, filtertype->type)); mimeAddFilter(mime, desttype, filtertype, 0, "-"); } } else { DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s %d %s", temptype->super, temptype->type, filtertype->super, filtertype->type, cost, program)); filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program); } if (filterptr) filterptr->maxsize = maxsize; } }