static void list_options(cups_dest_t *dest) /* I - Destination to list */ { int i; /* Looping var */ const char *filename; /* PPD filename */ ppd_file_t *ppd; /* PPD data */ ppd_group_t *group; /* Current group */ if ((filename = cupsGetPPD(dest->name)) == NULL) { _cupsLangPrintf(stderr, _("lpoptions: Unable to get PPD file for %s: %s"), dest->name, cupsLastErrorString()); return; } if ((ppd = ppdOpenFile(filename)) == NULL) { unlink(filename); _cupsLangPrintf(stderr, _("lpoptions: Unable to open PPD file for %s."), dest->name); return; } ppdMarkDefaults(ppd); cupsMarkOptions(ppd, dest->num_options, dest->options); for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) list_group(ppd, group); ppdClose(ppd); unlink(filename); }
static void usage(const char *opt) /* I - Option character/string */ { if (opt) { if (*opt == '-') _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"%s\"!\n"), opt); else _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"-%c\"!\n"), *opt); } _cupsLangPuts(stdout, _("Usage: cupsctl [options] [param=value ... paramN=valueN]\n" "\n" "Options:\n" "\n" " -E Enable encryption\n" " -U username Specify username\n" " -h server[:port] Specify server address\n" "\n" " --[no-]debug-logging Turn debug logging on/off\n" " --[no-]remote-admin Turn remote administration " "on/off\n" " --[no-]remote-any Allow/prevent access from the " "Internet\n" " --[no-]remote-printers Show/hide remote printers\n" " --[no-]share-printers Turn printer sharing on/off\n" " --[no-]user-cancel-any Allow/prevent users to cancel " "any job\n")); exit(1); }
static void usage(const char *opt) /* I - Incorrect option, if any */ { if (opt) _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), "cupsfilter", *opt); _cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] [ -- ] filename")); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _(" --list-filters List filters that will be used.")); _cupsLangPuts(stdout, _(" -D Remove the input file when finished.")); _cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -U username Specify username.")); _cupsLangPuts(stdout, _(" -c cups-files.conf Set cups-files.conf file to use.")); _cupsLangPuts(stdout, _(" -d printer Use the named printer.")); _cupsLangPuts(stdout, _(" -e Use every filter from the PPD file.")); _cupsLangPuts(stdout, _(" -i mime/type Set input MIME type (otherwise auto-typed).")); _cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the specified job (default is file 1).")); _cupsLangPuts(stdout, _(" -m mime/type Set output MIME type (otherwise application/pdf).")); _cupsLangPuts(stdout, _(" -n copies Set number of copies.")); _cupsLangPuts(stdout, _(" -o name=value Set option(s).")); _cupsLangPuts(stdout, _(" -p filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -t title Set title.")); _cupsLangPuts(stdout, _(" -u Remove the PPD file when finished.")); exit(1); }
static mime_type_t * /* O - Printer type or NULL on error */ add_printer_filters( const char *command, /* I - Command name */ mime_t *mime, /* I - MIME database */ const char *printer, /* I - Printer name */ const char *ppdfile, /* I - PPD file */ mime_type_t **prefilter_type) /* O - Prefilter type */ { ppd_file_t *ppd; /* PPD file data */ _ppd_cache_t *pc; /* Cache data for PPD */ const char *value; /* Filter definition value */ mime_type_t *printer_type; /* Printer filter type */ if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_NONE)) == NULL) { ppd_status_t status; /* PPD load status */ int linenum; /* Line number */ status = ppdLastError(&linenum); _cupsLangPrintf(stderr, _("%s: Unable to open PPD file: %s on line %d."), command, ppdErrorString(status), linenum); return (NULL); } pc = _ppdCacheCreateWithPPD(ppd); if (!pc) return (NULL); printer_type = mimeAddType(mime, "printer", printer); *prefilter_type = NULL; if (pc->filters) { for (value = (const char *)cupsArrayFirst(pc->filters); value; value = (const char *)cupsArrayNext(pc->filters)) add_printer_filter(command, mime, printer_type, value); } else { add_printer_filter(command, mime, printer_type, "application/vnd.cups-raw 0 -"); add_printer_filter(command, mime, printer_type, "application/vnd.cups-postscript 0 -"); } if (pc->prefilters) { *prefilter_type = mimeAddType(mime, "prefilter", printer); for (value = (const char *)cupsArrayFirst(pc->prefilters); value; value = (const char *)cupsArrayNext(pc->prefilters)) add_printer_filter(command, mime, *prefilter_type, value); } return (printer_type); }
static void show_help(const char *command) /* I - Command to describe or NULL */ { if (!command) { _cupsLangPrintf(stdout, _("Commands may be abbreviated. Commands are:\n" "\n" "exit help quit status ?")); } else if (!compare_strings(command, "help", 1) || !strcmp(command, "?")) _cupsLangPrintf(stdout, _("help\t\tGet help on commands.")); else if (!compare_strings(command, "status", 4)) _cupsLangPrintf(stdout, _("status\t\tShow status of daemon and queue.")); else _cupsLangPrintf(stdout, _("?Invalid help command unknown.")); }
static void list_options(cups_dest_t *dest) /* I - Destination to list */ { http_t *http; /* Connection to destination */ char resource[1024]; /* Resource path */ int i; /* Looping var */ const char *filename; /* PPD filename */ ppd_file_t *ppd; /* PPD data */ ppd_group_t *group; /* Current group */ if ((http = cupsConnectDest(dest, CUPS_DEST_FLAGS_NONE, 30000, NULL, resource, sizeof(resource), NULL, NULL)) == NULL) { _cupsLangPrintf(stderr, _("lpoptions: Unable to get PPD file for %s: %s"), dest->name, cupsLastErrorString()); return; } if ((filename = cupsGetPPD2(http, dest->name)) == NULL) { httpClose(http); _cupsLangPrintf(stderr, _("lpoptions: Unable to get PPD file for %s: %s"), dest->name, cupsLastErrorString()); return; } httpClose(http); if ((ppd = ppdOpenFile(filename)) == NULL) { unlink(filename); _cupsLangPrintf(stderr, _("lpoptions: Unable to open PPD file for %s."), dest->name); return; } ppdMarkDefaults(ppd); cupsMarkOptions(ppd, dest->num_options, dest->options); for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) list_group(ppd, group); ppdClose(ppd); unlink(filename); }
static void check_cb(void *context, /* I - Context (command name) */ _cups_fc_result_t result, /* I - Result of check */ const char *message) /* I - Localized message */ { (void)result; _cupsLangPrintf(stderr, _("%s: %s"), (char *)context, message); }
int /* O - 0 on success, non-zero on error */ export_dest(http_t *http, /* I - Connection to server */ const char *dest) /* I - Destination to export */ { int status; /* Status of export */ char ppdfile[1024], /* PPD file for printer drivers */ prompt[1024]; /* Password prompt */ int tries; /* Number of tries */ /* * Get the Windows PPD file for the printer... */ if (!cupsAdminCreateWindowsPPD(http, dest, ppdfile, sizeof(ppdfile))) { _cupsLangPrintf(stderr, _("cupsaddsmb: No PPD file for printer \"%s\" - %s"), dest, cupsLastErrorString()); return (1); } /* * Try to export it... */ for (status = 0, tries = 0; !status && tries < 3; tries ++) { /* * Get the password, as needed... */ if (!SAMBAPassword) { snprintf(prompt, sizeof(prompt), _cupsLangString(cupsLangDefault(), _("Password for %s required to access %s via " "SAMBA: ")), SAMBAUser, SAMBAServer); if ((SAMBAPassword = cupsGetPassword(prompt)) == NULL) break; } status = cupsAdminExportSamba(dest, ppdfile, SAMBAServer, SAMBAUser, SAMBAPassword, Verbosity ? stderr : NULL); if (!status && cupsLastError() == IPP_NOT_FOUND) break; } unlink(ppdfile); return (!status); }
static int /* O - 0 on success, 1 on fail */ enable_printer(http_t *http, /* I - Server connection */ char *printer) /* I - Printer to enable */ { ipp_t *request; /* IPP Request */ char uri[HTTP_MAX_URI]; /* URI for printer/class */ DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer)); /* * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which * require the following attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name * printer-state * printer-is-accepting-jobs */ if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE); ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1); /* * Do the request and get back a response... */ ippDelete(cupsDoRequest(http, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); return (1); } else return (0); }
static void do_command(http_t *http, /* I - HTTP connection to server */ const char *command, /* I - Command string */ const char *params) /* I - Parameters for command */ { if (!compare_strings(command, "status", 4)) show_status(http, params); else if (!compare_strings(command, "help", 1) || !strcmp(command, "?")) show_help(params); else _cupsLangPrintf(stdout, _("%s is not implemented by the CUPS version of lpc."), command); }
static void usage(const char *opt) /* I - Option character/string */ { if (opt) { if (*opt == '-') _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"%s\""), opt); else _cupsLangPrintf(stderr, _("cupsctl: Unknown option \"-%c\""), *opt); } _cupsLangPuts(stdout, _("Usage: cupsctl [options] [param=value ... paramN=valueN]")); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); _cupsLangPuts(stdout, _("-U username Specify username to use for authentication")); _cupsLangPuts(stdout, _("--[no-]debug-logging Turn debug logging on/off")); _cupsLangPuts(stdout, _("--[no-]remote-admin Turn remote administration on/off")); _cupsLangPuts(stdout, _("--[no-]remote-any Allow/prevent access from the Internet")); _cupsLangPuts(stdout, _("--[no-]share-printers Turn printer sharing on/off")); _cupsLangPuts(stdout, _("--[no-]user-cancel-any Allow/prevent users to cancel any job")); exit(1); }
static void usage(const char *command) /* I - Command name */ { _cupsLangPrintf(stdout, _("Usage: %s [options] destination(s)"), command); _cupsLangPuts(stdout, _("Options:")); _cupsLangPuts(stdout, _("-E Encrypt the connection to the server")); _cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port")); _cupsLangPuts(stdout, _("-r reason Specify a reason message that others can see")); _cupsLangPuts(stdout, _("-U username Specify the username to use for authentication")); if (!strcmp(command, "cupsdisable")) _cupsLangPuts(stdout, _("--hold Hold new jobs")); if (!strcmp(command, "cupsenable")) _cupsLangPuts(stdout, _("--release Release previously held jobs")); exit(1); }
static int /* O - 0 on success, 1 on fail */ delete_printer_option(http_t *http, /* I - Server connection */ char *printer, /* I - Printer */ char *option) /* I - Option to delete */ { ipp_t *request; /* IPP request */ char uri[HTTP_MAX_URI]; /* URI for printer/class */ /* * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which * requires the following attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name * option with deleteAttr tag */ if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0); /* * Do the request and get back a response... */ ippDelete(cupsDoRequest(http, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); return (1); } else return (0); }
static int /* O - 0 on success, 1 on fail */ default_printer(http_t *http, /* I - Server connection */ char *printer) /* I - Printer name */ { ipp_t *request; /* IPP Request */ char uri[HTTP_MAX_URI]; /* URI for printer/class */ DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer)); /* * Build a CUPS_SET_DEFAULT request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri * requesting-user-name */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer); request = ippNewRequest(CUPS_SET_DEFAULT); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); /* * Do the request and get back a response... */ ippDelete(cupsDoRequest(http, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString()); return (1); } else return (0); }
static http_t * /* O - New HTTP connection */ connect_server(const char *command, /* I - Command name */ http_t *http) /* I - Current HTTP connection */ { if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to connect to server."), command); exit(1); } } return (http); }
static void usage(const char *command, /* I - Command name */ const char *opt) /* I - Incorrect option, if any */ { if (opt) _cupsLangPrintf(stderr, _("%s: Unknown option '%c'!\n"), command, *opt); if (!strcmp(command, "cupsfilter")) _cupsLangPuts(stdout, _("Usage: cupsfilter -m mime/type [ options ] filename\n" "\n" "Options:\n" "\n" " -c cupsd.conf Set cupsd.conf file to use\n" " -n copies Set number of copies\n" " -o name=value Set option(s)\n" " -p filename.ppd Set PPD file\n" " -t title Set title\n")); else _cupsLangPuts(stdout, _("Usage: convert [ options ]\n" "\n" "Options:\n" "\n" " -f filename Set file to be converted (otherwise stdin)\n" " -o filename Set file to be generated (otherwise stdout)\n" " -i mime/type Set input MIME type (otherwise auto-typed)\n" " -j mime/type Set output MIME type (otherwise application/pdf)\n" " -P filename.ppd Set PPD file\n" " -a 'name=value ...' Set option(s)\n" " -U username Set username for job\n" " -J title Set title\n" " -c copies Set number of copies\n" " -u Remove the PPD file when finished\n" " -D Remove the input file when finished\n")); exit(1); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { FILE *fp; /* File to print */ int copies; /* Number of copies left */ char line[1024]; /* Line/buffer from stream/file */ size_t linelen; /* Length of line */ ppd_file_t *ppd; /* PPD file */ /* * Check command-line... */ if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (1); } if (argc == 6) { copies = 1; fp = stdin; } else { copies = atoi(argv[4]); fp = fopen(argv[6], "rb"); if (!fp) { perror(argv[6]); return (1); } } /* * Open the PPD file as needed... */ ppd = ppdOpenFile(getenv("PPD")); /* * Copy the print file to stdout... */ while (copies > 0) { copies --; if (ppd && ppd->jcl_begin) fputs(ppd->jcl_begin, stdout); if (ppd && ppd->jcl_ps) fputs(ppd->jcl_ps, stdout); if (!ppd || ppd->language_level == 1) { /* * Use setsoftwareiomode for BCP mode... */ puts("%!PS-Adobe-3.0 ExitServer"); puts("%%Title: (BCP - Level 1)"); puts("%%EndComments"); puts("%%BeginExitServer: 0"); puts("serverdict begin 0 exitserver"); puts("%%EndExitServer"); puts("statusdict begin"); puts("/setsoftwareiomode known {100 setsoftwareiomode}"); puts("end"); puts("%EOF"); } else { /* * Use setdevparams for BCP mode... */ puts("%!PS-Adobe-3.0"); puts("%%Title: (BCP - Level 2)"); puts("%%EndComments"); puts("currentsysparams"); puts("/CurInputDevice 2 copy known {"); puts("get"); puts("<</Protocol /Binary>> setdevparams"); puts("}{"); puts("pop pop"); puts("} ifelse"); puts("%EOF"); } if (ppd && ppd->jcl_end) fputs(ppd->jcl_end, stdout); else if (!ppd || ppd->num_filters == 0) putchar(0x04); /* * Loop until we see end-of-file... */ do { linelen = sizeof(line); if (psgets(line, &linelen, fp) == NULL) break; } while (pswrite(line, linelen) > 0); fflush(stdout); } return (0); }
int /* O - Exit status */ print_device(const char *uri, /* I - Device URI */ const char *hostname, /* I - Hostname/manufacturer */ const char *resource, /* I - Resource/modelname */ char *options, /* I - Device options/serial number */ int print_fd, /* I - File descriptor to print */ int copies, /* I - Copies to print */ int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { int use_bc; /* Use backchannel path? */ int device_fd; /* USB device */ size_t tbytes; /* Total number of bytes written */ struct termios opts; /* Parallel port options */ (void)argc; (void)argv; /* * Open the USB port device... */ fputs("STATE: +connecting-to-device\n", stderr); do { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) /* * *BSD's ulpt driver currently does not support the * back-channel, incorrectly returns data ready on a select(), * and locks up on read()... */ use_bc = 0; #else /* * Disable backchannel data when printing to Brother, Canon, or * Minolta USB printers - apparently these printers will return * the IEEE-1284 device ID over and over and over when they get * a read request... */ use_bc = strcasecmp(hostname, "Brother") && strcasecmp(hostname, "Canon") && strncasecmp(hostname, "Konica", 6) && strncasecmp(hostname, "Minolta", 7); #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */ if ((device_fd = open_device(uri, &use_bc)) == -1) { if (getenv("CLASS") != NULL) { /* * If the CLASS environment variable is set, the job was submitted * to a class and not to a specific queue. In this case, we want * to abort immediately so that the job can be requeued on the next * available printer in the class. */ _cupsLangPuts(stderr, _("INFO: Unable to contact printer, queuing on next " "printer in class...\n")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... */ sleep(5); return (CUPS_BACKEND_FAILED); } if (errno == EBUSY) { _cupsLangPuts(stderr, _("INFO: Printer busy; will retry in 10 seconds...\n")); sleep(10); } else if (errno == ENXIO || errno == EIO || errno == ENOENT || errno == ENODEV) { _cupsLangPuts(stderr, _("INFO: Printer not connected; will retry in 30 " "seconds...\n")); sleep(30); } else { _cupsLangPrintf(stderr, _("ERROR: Unable to open device file \"%s\": %s\n"), resource, strerror(errno)); return (CUPS_BACKEND_FAILED); } } } while (device_fd < 0); fputs("STATE: -connecting-to-device\n", stderr); /* * Set any options provided... */ tcgetattr(device_fd, &opts); opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ /**** No options supported yet ****/ tcsetattr(device_fd, TCSANOW, &opts); /* * Finally, send the print file... */ tbytes = 0; while (copies > 0 && tbytes >= 0) { copies --; if (print_fd != 0) { fputs("PAGE: 1 1\n", stderr); lseek(print_fd, 0, SEEK_SET); } tbytes = backendRunLoop(print_fd, device_fd, use_bc, side_cb); if (print_fd != 0 && tbytes >= 0) _cupsLangPrintf(stderr, #ifdef HAVE_LONG_LONG _("INFO: Sent print file, %lld bytes...\n"), #else _("INFO: Sent print file, %ld bytes...\n"), #endif /* HAVE_LONG_LONG */ CUPS_LLCAST tbytes); } /* * Close the USB port and return... */ close(device_fd); return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK); }
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); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { char method[255], /* Method in URI */ hostname[1024], /* Hostname */ username[255], /* Username info (not used) */ resource[1024], /* Resource info (device and options) */ *options; /* Pointer to options */ int port; /* Port number (not used) */ int fp; /* Print file */ int copies; /* Number of copies to print */ int status; /* Exit status */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE signals... */ #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); #else signal(SIGPIPE, SIG_IGN); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc == 1) { list_devices(); return (CUPS_BACKEND_OK); } else if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]\n"), argv[0]); return (CUPS_BACKEND_FAILED); } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, send stdin instead... */ if (argc == 6) { fp = 0; copies = 1; } else { /* * Try to open the print file... */ if ((fp = open(argv[6], O_RDONLY)) < 0) { perror("ERROR: unable to open print file"); return (CUPS_BACKEND_FAILED); } copies = atoi(argv[4]); } /* * Extract the device name and options from the URI... */ httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv), method, sizeof(method), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); /* * See if there are any options... */ if ((options = strchr(resource, '?')) != NULL) { /* * Yup, terminate the device name string and move to the first * character of the options... */ *options++ = '\0'; } /* * Finally, send the print file... */ status = print_device(resource, fp, copies); /* * Close input file and return... */ if (fp != 0) close(fp); return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ char *command, /* Command to do */ *opt, /* Option pointer */ uri[1024], /* Printer URI */ *reason; /* Reason for reject/disable */ ipp_t *request; /* IPP request */ ipp_op_t op; /* Operation */ int cancel; /* Cancel jobs? */ _cupsSetLocale(argv); /* * See what operation we're supposed to do... */ if ((command = strrchr(argv[0], '/')) != NULL) command ++; else command = argv[0]; cancel = 0; if (!strcmp(command, "cupsaccept")) op = CUPS_ACCEPT_JOBS; else if (!strcmp(command, "cupsreject")) op = CUPS_REJECT_JOBS; else if (!strcmp(command, "cupsdisable")) op = IPP_PAUSE_PRINTER; else if (!strcmp(command, "cupsenable")) op = IPP_RESUME_PRINTER; else { _cupsLangPrintf(stderr, _("%s: Don't know what to do."), command); return (1); } reason = NULL; /* * Process command-line arguments... */ for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) usage(command); else if (!strcmp(argv[i], "--hold")) op = IPP_HOLD_NEW_JOBS; else if (!strcmp(argv[i], "--release")) op = IPP_RELEASE_HELD_NEW_JOBS; else if (argv[i][0] == '-') { for (opt = argv[i] + 1; *opt; opt ++) { switch (*opt) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), command); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (opt[1] != '\0') { cupsSetUser(opt + 1); opt += strlen(opt) - 1; } else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), command); usage(command); } cupsSetUser(argv[i]); } break; case 'c' : /* Cancel jobs */ cancel = 1; break; case 'h' : /* Connect to host */ if (opt[1] != '\0') { cupsSetServer(opt + 1); opt += strlen(opt) - 1; } else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), command); usage(command); } cupsSetServer(argv[i]); } break; case 'r' : /* Reason for cancellation */ if (opt[1] != '\0') { reason = opt + 1; opt += strlen(opt) - 1; } else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected reason text after \"-r\" option."), command); usage(command); } reason = argv[i]; } break; default : _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), command, *opt); usage(command); } } } else { /* * Accept/disable/enable/reject a destination... */ request = ippNewRequest(op); httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", argv[i]); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (reason != NULL) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "printer-state-message", NULL, reason); /* * Do the request and get back a response... */ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: Operation failed: %s"), command, ippErrorString(cupsLastError())); return (1); } /* * Cancel all jobs if requested... */ if (cancel) { /* * Build an IPP_PURGE_JOBS request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri */ request = ippNewRequest(IPP_PURGE_JOBS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/")); if (cupsLastError() > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); return (1); } } } } return (0); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { http_t *http; /* HTTP connection to server */ int i; /* Looping var */ int job_id; /* Job ID */ int num_dests; /* Number of destinations */ cups_dest_t *dests; /* Destinations */ char *dest, /* Destination printer */ *job, /* Job ID pointer */ *user; /* Cancel jobs for a user */ int purge; /* Purge or cancel jobs? */ char uri[1024]; /* Printer or job URI */ ipp_t *request; /* IPP request */ ipp_t *response; /* IPP response */ ipp_op_t op; /* Operation */ _cupsSetLocale(argv); /* * Setup to cancel individual print jobs... */ op = IPP_CANCEL_JOB; purge = 0; dest = NULL; user = NULL; http = NULL; num_dests = 0; dests = NULL; /* * Process command-line arguments... */ for (i = 1; i < argc; i ++) if (argv[i][0] == '-' && argv[i][1]) switch (argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support compiled in!\n"), argv[0]); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\'-U\' option!\n"), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'a' : /* Cancel all jobs */ purge = 1; op = IPP_PURGE_JOBS; break; case 'h' : /* Connect to host */ if (http != NULL) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\'-h\' option!\n"), argv[0]); return (1); } else cupsSetServer(argv[i]); } break; case 'u' : /* Username */ op = IPP_PURGE_JOBS; if (argv[i][2] != '\0') user = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\'-u\' option!\n"), argv[0]); return (1); } else user = argv[i]; } break; default : _cupsLangPrintf(stderr, _("%s: Error - unknown option \'%c\'!\n"), argv[0], argv[i][1]); return (1); } else { /* * Cancel a job or printer... */ if (num_dests == 0) num_dests = cupsGetDests(&dests); if (!strcmp(argv[i], "-")) { /* * Delete the current job... */ dest = ""; job_id = 0; } else if (cupsGetDest(argv[i], NULL, num_dests, dests) != NULL) { /* * Delete the current job on the named destination... */ dest = argv[i]; job_id = 0; } else if ((job = strrchr(argv[i], '-')) != NULL && isdigit(job[1] & 255)) { /* * Delete the specified job ID. */ dest = NULL; op = IPP_CANCEL_JOB; job_id = atoi(job + 1); } else if (isdigit(argv[i][0] & 255)) { /* * Delete the specified job ID. */ dest = NULL; op = IPP_CANCEL_JOB; job_id = atoi(argv[i]); } else { /* * Bad printer name! */ _cupsLangPrintf(stderr, _("%s: Error - unknown destination \"%s\"!\n"), argv[0], argv[i]); return (1); } /* * For Solaris LP compatibility, ignore a destination name after * cancelling a specific job ID... */ if (job_id && (i + 1) < argc && cupsGetDest(argv[i + 1], NULL, num_dests, dests) != NULL) i ++; /* * Open a connection to the server... */ if (http == NULL) if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to contact server!\n"), argv[0]); return (1); } /* * Build an IPP request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri + job-id *or* job-uri * [requesting-user-name] */ request = ippNewRequest(op); if (dest) { 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); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); } else { sprintf(uri, "ipp://localhost/jobs/%d", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); } if (user) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); if (op == IPP_PURGE_JOBS) ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge); /* * Do the request and get back a response... */ if (op == IPP_PURGE_JOBS && (!user || strcasecmp(user, cupsUser()))) response = cupsDoRequest(http, request, "/admin/"); else response = cupsDoRequest(http, request, "/jobs/"); if (response == NULL || response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0], op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", cupsLastErrorString()); if (response) ippDelete(response); return (1); } ippDelete(response); } if (num_dests == 0 && op == IPP_PURGE_JOBS) { /* * Open a connection to the server... */ if (http == NULL) if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { _cupsLangPrintf(stderr, _("%s: Unable to contact server!\n"), argv[0]); return (1); } /* * Build an IPP request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri + job-id *or* job-uri * [requesting-user-name] */ request = ippNewRequest(op); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/"); if (user) { ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1); } else ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge); /* * Do the request and get back a response... */ response = cupsDoRequest(http, request, "/admin/"); if (response == NULL || response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0], op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job", cupsLastErrorString()); if (response) ippDelete(response); return (1); } ippDelete(response); } 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 */ 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 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); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { const char *device_uri; /* Device URI */ char scheme[255], /* Scheme in URI */ hostname[1024], /* Hostname */ username[255], /* Username info */ resource[1024], /* Resource info (printer name) */ *options, /* Pointer to options */ *name, /* Name of option */ *value, /* Value of option */ sep, /* Separator character */ *filename, /* File to print */ title[256]; /* Title string */ int port; /* Port number */ char portname[256]; /* Port name (string) */ http_addrlist_t *addrlist; /* List of addresses for printer */ int snmp_enabled = 1; /* Is SNMP enabled? */ int snmp_fd; /* SNMP socket */ int fd; /* Print file */ int status; /* Status of LPD job */ int mode; /* Print mode */ int banner; /* Print banner page? */ int format; /* Print format */ int order; /* Order of control/data files */ int reserve; /* Reserve priviledged port? */ int sanitize_title; /* Sanitize title string? */ int manual_copies, /* Do manual copies? */ timeout, /* Timeout */ contimeout, /* Connection timeout */ copies; /* Number of copies */ ssize_t bytes = 0; /* Initial bytes read */ char buffer[16384]; /* Initial print buffer */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ int num_jobopts; /* Number of job options */ cups_option_t *jobopts = NULL; /* Job options */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE and catch SIGTERM signals... */ #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc == 1) { printf("network lpd \"Unknown\" \"%s\"\n", _cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer"))); return (CUPS_BACKEND_OK); } else if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (CUPS_BACKEND_FAILED); } num_jobopts = cupsParseOptions(argv[5], 0, &jobopts); /* * Extract the hostname and printer name from the URI... */ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer.")); sleep(10); if (getenv("CLASS") != NULL) return (CUPS_BACKEND_FAILED); } httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (!port) port = 515; /* Default to port 515 */ if (!username[0]) { /* * If no username is in the device URI, then use the print job user... */ strlcpy(username, argv[2], sizeof(username)); } /* * See if there are any options... */ mode = MODE_STANDARD; banner = 0; format = 'l'; order = ORDER_CONTROL_DATA; reserve = RESERVE_ANY; manual_copies = 1; timeout = 300; contimeout = 7 * 24 * 60 * 60; #ifdef __APPLE__ /* * We want to pass UTF-8 characters by default, not re-map them (3071945) */ sanitize_title = 0; #else /* * Otherwise we want to re-map UTF-8 to "safe" characters by default... */ sanitize_title = 1; #endif /* __APPLE__ */ if ((options = strchr(resource, '?')) != NULL) { /* * Yup, terminate the device name string and move to the first * character of the options... */ *options++ = '\0'; /* * Parse options... */ while (*options) { /* * Get the name... */ name = options; while (*options && *options != '=' && *options != '+' && *options != '&') options ++; if ((sep = *options) != '\0') *options++ = '\0'; if (sep == '=') { /* * Get the value... */ value = options; while (*options && *options != '+' && *options != '&') options ++; if (*options) *options++ = '\0'; } else value = (char *)""; /* * Process the option... */ if (!_cups_strcasecmp(name, "banner")) { /* * Set the banner... */ banner = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "format") && value[0]) { /* * Set output format... */ if (strchr("cdfglnoprtv", value[0])) format = value[0]; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown format character: \"%c\"."), value[0]); } else if (!_cups_strcasecmp(name, "mode") && value[0]) { /* * Set control/data order... */ if (!_cups_strcasecmp(value, "standard")) mode = MODE_STANDARD; else if (!_cups_strcasecmp(value, "stream")) mode = MODE_STREAM; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown print mode: \"%s\"."), value); } else if (!_cups_strcasecmp(name, "order") && value[0]) { /* * Set control/data order... */ if (!_cups_strcasecmp(value, "control,data")) order = ORDER_CONTROL_DATA; else if (!_cups_strcasecmp(value, "data,control")) order = ORDER_DATA_CONTROL; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown file order: \"%s\"."), value); } else if (!_cups_strcasecmp(name, "reserve")) { /* * Set port reservation mode... */ if (!value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "rfc1179")) reserve = RESERVE_RFC1179; else if (!_cups_strcasecmp(value, "any")) reserve = RESERVE_ANY; else reserve = RESERVE_NONE; } else if (!_cups_strcasecmp(name, "manual_copies")) { /* * Set manual copies... */ manual_copies = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "sanitize_title")) { /* * Set sanitize title... */ sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "snmp")) { /* * Enable/disable SNMP stuff... */ snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || _cups_strcasecmp(value, "yes") || _cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "timeout")) { /* * Set the timeout... */ if (atoi(value) > 0) timeout = atoi(value); } else if (!_cups_strcasecmp(name, "contimeout")) { /* * Set the connection timeout... */ if (atoi(value) > 0) contimeout = atoi(value); } } } if (mode == MODE_STREAM) order = ORDER_CONTROL_DATA; /* * Find the printer... */ snprintf(portname, sizeof(portname), "%d", port); fputs("STATE: +connecting-to-device\n", stderr); fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname); while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer \"%s\"."), hostname); sleep(10); if (getenv("CLASS") != NULL) { fputs("STATE: -connecting-to-device\n", stderr); exit(CUPS_BACKEND_FAILED); } } if (snmp_enabled) snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); else snmp_fd = -1; /* * Wait for data from the filter... */ if (argc == 6) { if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB)) return (CUPS_BACKEND_OK); else if (mode == MODE_STANDARD && (bytes = read(0, buffer, sizeof(buffer))) <= 0) return (CUPS_BACKEND_OK); } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, copy stdin to a temporary file and print the temporary * file. */ if (argc == 6 && mode == MODE_STANDARD) { /* * Copy stdin to a temporary file... */ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0) { perror("DEBUG: Unable to create temporary file"); return (CUPS_BACKEND_FAILED); } _cupsLangPrintFilter(stderr, "INFO", _("Copying print data.")); if (bytes > 0) write(fd, buffer, bytes); backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0, backendNetworkSideCB); } else if (argc == 6) { /* * Stream from stdin... */ filename = NULL; fd = 0; } else { filename = argv[6]; fd = open(filename, O_RDONLY); if (fd == -1) { _cupsLangPrintError("ERROR", _("Unable to open print file")); return (CUPS_BACKEND_FAILED); } } /* * Sanitize the document title... */ strlcpy(title, argv[3], sizeof(title)); if (sanitize_title) { /* * Sanitize the title string so that we don't cause problems on * the remote end... */ char *ptr; for (ptr = title; *ptr; ptr ++) if (!isalnum(*ptr & 255) && !isspace(*ptr & 255)) *ptr = '_'; } /* * Queue the job... */ if (argc > 6) { if (manual_copies) { manual_copies = atoi(argv[4]); copies = 1; } else { manual_copies = 1; copies = atoi(argv[4]); } status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, username, title, copies, banner, format, order, reserve, manual_copies, timeout, contimeout, cupsGetOption("job-originating-host-name", num_jobopts, jobopts)); if (!status) fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); } else status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, username, title, 1, banner, format, order, reserve, 1, timeout, contimeout, cupsGetOption("job-originating-host-name", num_jobopts, jobopts)); /* * Remove the temporary file if necessary... */ if (tmpfilename[0]) unlink(tmpfilename); if (fd) close(fd); if (snmp_fd >= 0) _cupsSNMPClose(snmp_fd); /* * Return the queue status... */ return (status); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { FILE *fp; /* File to print */ int copies; /* Number of copies left */ char line[1024]; /* Line/buffer from stream/file */ size_t linelen; /* Length of line */ /* * Check command-line... */ if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (1); } if (argc == 6) { copies = 1; fp = stdin; } else { copies = atoi(argv[4]); fp = fopen(argv[6], "rb"); if (!fp) { perror(argv[6]); return (1); } } /* * Copy the print file to stdout... */ while (copies > 0) { copies --; /* * Read the first line... */ linelen = sizeof(line); if (!psgets(line, &linelen, fp)) break; /* * Handle leading PJL fun... */ if (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5)) { /* * Yup, we have leading PJL fun, so copy it until we hit a line * with "ENTER LANGUAGE"... */ while (strstr(line, "ENTER LANGUAGE") == NULL) { fwrite(line, 1, linelen, stdout); linelen = sizeof(line); if (psgets(line, &linelen, fp) == NULL) break; } } else { /* * No PJL stuff, just add the UEL... */ fputs("\033%-12345X", stdout); } /* * Switch to TBCP mode... */ fputs("\001M", stdout); /* * Loop until we see end-of-file... */ while (pswrite(line, linelen, stdout) > 0) { linelen = sizeof(line); if (psgets(line, &linelen, fp) == NULL) break; } fflush(stdout); } return (0); }
static void show_printer(const char *command, /* I - Command name */ http_t *http, /* I - HTTP connection to server */ const char *dest) /* I - Destination */ { ipp_t *request, /* IPP Request */ *response; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ ipp_pstate_t state; /* Printer state */ char uri[HTTP_MAX_URI]; /* Printer URI */ if (http == NULL) return; /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * * attributes-charset * attributes-natural-language * printer-uri */ 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); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if (response->request.status.status_code > IPP_OK_CONFLICT) { _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); ippDelete(response); return; } if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) state = (ipp_pstate_t)attr->values[0].integer; else state = IPP_PRINTER_STOPPED; switch (state) { case IPP_PRINTER_IDLE : _cupsLangPrintf(stdout, _("%s is ready"), dest); break; case IPP_PRINTER_PROCESSING : _cupsLangPrintf(stdout, _("%s is ready and printing"), dest); break; case IPP_PRINTER_STOPPED : _cupsLangPrintf(stdout, _("%s is not ready"), dest); break; } ippDelete(response); } else _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString()); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { const char *device_uri; /* Device URI */ char scheme[255], /* Scheme in URI */ hostname[1024], /* Hostname */ username[255], /* Username info (not used) */ resource[1024], /* Resource info (not used) */ *options, /* Pointer to options */ *name, /* Name of option */ *value, /* Value of option */ sep; /* Option separator */ int print_fd; /* Print file */ int copies; /* Number of copies to print */ time_t start_time; /* Time of first connect */ #ifdef __APPLE__ time_t current_time, /* Current time */ wait_time; /* Time to wait before shutting down socket */ #endif /* __APPLE__ */ int contimeout; /* Connection timeout */ int waiteof; /* Wait for end-of-file? */ int port; /* Port number */ char portname[255]; /* Port name */ int delay; /* Delay for retries... */ int device_fd; /* AppSocket */ int error; /* Error code (if any) */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Connected address */ char addrname[256]; /* Address name */ int snmp_fd, /* SNMP socket */ start_count, /* Page count via SNMP at start */ page_count, /* Page count via SNMP */ have_supplies; /* Printer supports supply levels? */ ssize_t bytes = 0, /* Initial bytes read */ tbytes; /* Total number of bytes written */ char buffer[1024]; /* Initial print buffer */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE signals... */ #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_IGN); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); #else signal(SIGPIPE, SIG_IGN); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc == 1) { printf("network socket \"Unknown\" \"%s\"\n", _cupsLangString(cupsLangDefault(), _("AppSocket/HP JetDirect"))); return (CUPS_BACKEND_OK); } else if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (CUPS_BACKEND_FAILED); } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, send stdin instead... */ if (argc == 6) { print_fd = 0; copies = 1; } else { /* * Try to open the print file... */ if ((print_fd = open(argv[6], O_RDONLY)) < 0) { _cupsLangPrintError("ERROR", _("Unable to open print file")); return (CUPS_BACKEND_FAILED); } copies = atoi(argv[4]); } /* * Extract the hostname and port number from the URI... */ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer.")); sleep(10); if (getenv("CLASS") != NULL) return (CUPS_BACKEND_FAILED); } httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (port == 0) port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */ /* * Get options, if any... */ waiteof = 1; contimeout = 7 * 24 * 60 * 60; if ((options = strchr(resource, '?')) != NULL) { /* * Yup, terminate the device name string and move to the first * character of the options... */ *options++ = '\0'; /* * Parse options... */ while (*options) { /* * Get the name... */ name = options; while (*options && *options != '=' && *options != '+' && *options != '&') options ++; if ((sep = *options) != '\0') *options++ = '\0'; if (sep == '=') { /* * Get the value... */ value = options; while (*options && *options != '+' && *options != '&') options ++; if (*options) *options++ = '\0'; } else value = (char *)""; /* * Process the option... */ if (!_cups_strcasecmp(name, "waiteof")) { /* * Set the wait-for-eof value... */ waiteof = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "contimeout")) { /* * Set the connection timeout... */ if (atoi(value) > 0) contimeout = atoi(value); } } } /* * Then try finding the remote host... */ start_time = time(NULL); sprintf(portname, "%d", port); fputs("STATE: +connecting-to-device\n", stderr); fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname); while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer \"%s\"."), hostname); sleep(10); if (getenv("CLASS") != NULL) { fputs("STATE: -connecting-to-device\n", stderr); return (CUPS_BACKEND_STOP); } } /* * See if the printer supports SNMP... */ if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0) { have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &start_count, NULL); } else have_supplies = start_count = 0; /* * Wait for data from the filter... */ if (print_fd == 0) { if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB)) return (CUPS_BACKEND_OK); else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0) return (CUPS_BACKEND_OK); } /* * Connect to the printer... */ fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port); _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer.")); for (delay = 5;;) { if ((addr = httpAddrConnect(addrlist, &device_fd)) == NULL) { error = errno; device_fd = -1; if (getenv("CLASS") != NULL) { /* * If the CLASS environment variable is set, the job was submitted * to a class and not to a specific queue. In this case, we want * to abort immediately so that the job can be requeued on the next * available printer in the class. */ _cupsLangPrintFilter(stderr, "INFO", _("Unable to contact printer, queuing on next " "printer in class.")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... */ sleep(5); return (CUPS_BACKEND_FAILED); } fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error)); if (error == ECONNREFUSED || error == EHOSTDOWN || error == EHOSTUNREACH) { if (contimeout && (time(NULL) - start_time) > contimeout) { _cupsLangPrintFilter(stderr, "ERROR", _("The printer is not responding.")); return (CUPS_BACKEND_FAILED); } switch (error) { case EHOSTDOWN : _cupsLangPrintFilter(stderr, "WARNING", _("The printer may not exist or " "is unavailable at this time.")); break; case EHOSTUNREACH : _cupsLangPrintFilter(stderr, "WARNING", _("The printer is unreachable at this " "time.")); break; case ECONNREFUSED : default : _cupsLangPrintFilter(stderr, "WARNING", _("The printer is in use.")); break; } sleep(delay); if (delay < 30) delay += 5; } else { _cupsLangPrintFilter(stderr, "ERROR", _("The printer is not responding.")); sleep(30); } } else break; } fputs("STATE: -connecting-to-device\n", stderr); _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer.")); fprintf(stderr, "DEBUG: Connected to %s:%d...\n", httpAddrString(&(addr->addr), addrname, sizeof(addrname)), _httpAddrPort(&(addr->addr))); /* * Print everything... */ tbytes = 0; if (bytes > 0) tbytes += write(device_fd, buffer, bytes); while (copies > 0 && tbytes >= 0) { copies --; if (print_fd != 0) { fputs("PAGE: 1 1\n", stderr); lseek(print_fd, 0, SEEK_SET); } tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1, 0, backendNetworkSideCB); if (print_fd != 0 && tbytes >= 0) _cupsLangPrintFilter(stderr, "INFO", _("Print file sent.")); } #ifdef __APPLE__ /* * Wait up to 5 seconds to get any pending back-channel data... */ wait_time = time(NULL) + 5; while (wait_time >= time(¤t_time)) if (wait_bc(device_fd, wait_time - current_time) <= 0) break; #endif /* __APPLE__ */ if (waiteof) { /* * Shutdown the socket and wait for the other end to finish... */ _cupsLangPrintFilter(stderr, "INFO", _("Waiting for printer to finish.")); shutdown(device_fd, 1); while (wait_bc(device_fd, 90) > 0); } /* * Collect the final page count as needed... */ if (have_supplies && !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) && page_count > start_count) fprintf(stderr, "PAGE: total %d\n", page_count - start_count); /* * Close the socket connection... */ close(device_fd); httpAddrFreeList(addrlist); /* * Close the input file and return... */ if (print_fd != 0) close(print_fd); return (CUPS_BACKEND_OK); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { const char *name; /* Backend name */ cups_array_t *devices; /* Device array */ cups_device_t *device; /* Current device */ char uriName[1024]; /* Unquoted fullName for URI */ #ifdef HAVE_DNSSD int fd; /* Main file descriptor */ fd_set input; /* Input set for select() */ struct timeval timeout; /* Timeout for select() */ DNSServiceRef main_ref, /* Main service reference */ fax_ipp_ref, /* IPP fax service reference */ ipp_ref, /* IPP service reference */ ipp_tls_ref, /* IPP w/TLS service reference */ ipps_ref, /* IPP service reference */ local_fax_ipp_ref, /* Local IPP fax service reference */ local_ipp_ref, /* Local IPP service reference */ local_ipp_tls_ref, /* Local IPP w/TLS service reference */ local_ipps_ref, /* Local IPP service reference */ local_printer_ref, /* Local LPD service reference */ pdl_datastream_ref, /* AppSocket service reference */ printer_ref, /* LPD service reference */ riousbprint_ref; /* Remote IO service reference */ #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI AvahiClient *client; /* Client information */ int error; /* Error code, if any */ #endif /* HAVE_AVAHI */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Don't buffer stderr, and catch SIGTERM... */ setbuf(stderr, NULL); #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc >= 6) exec_backend(argv); else if (argc != 1) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (1); } /* * Only do discovery when run as "dnssd"... */ if ((name = strrchr(argv[0], '/')) != NULL) name ++; else name = argv[0]; if (strcmp(name, "dnssd")) return (0); /* * Create an array to track devices... */ devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL); /* * Browse for different kinds of printers... */ #ifdef HAVE_DNSSD if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError) { perror("ERROR: Unable to create service connection"); return (1); } fd = DNSServiceRefSockFD(main_ref); fax_ipp_ref = main_ref; DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0, "_fax-ipp._tcp", NULL, browse_callback, devices); ipp_ref = main_ref; DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0, "_ipp._tcp", NULL, browse_callback, devices); ipp_tls_ref = main_ref; DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0, "_ipp-tls._tcp", NULL, browse_callback, devices); ipps_ref = main_ref; DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0, "_ipps._tcp", NULL, browse_callback, devices); local_fax_ipp_ref = main_ref; DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_fax-ipp._tcp", NULL, browse_local_callback, devices); local_ipp_ref = main_ref; DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp._tcp", NULL, browse_local_callback, devices); local_ipp_tls_ref = main_ref; DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp-tls._tcp", NULL, browse_local_callback, devices); local_ipps_ref = main_ref; DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipps._tcp", NULL, browse_local_callback, devices); local_printer_ref = main_ref; DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_printer._tcp", NULL, browse_local_callback, devices); pdl_datastream_ref = main_ref; DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0, "_pdl-datastream._tcp", NULL, browse_callback, devices); printer_ref = main_ref; DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0, "_printer._tcp", NULL, browse_callback, devices); riousbprint_ref = main_ref; DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0, "_riousbprint._tcp", NULL, browse_callback, devices); #endif /* HAVE_DNSSD */ #ifdef HAVE_AVAHI if ((simple_poll = avahi_simple_poll_new()) == NULL) { fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr); return (0); } avahi_simple_poll_set_func(simple_poll, poll_callback, NULL); client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, simple_poll, &error); if (!client) { fputs("DEBUG: Unable to create Avahi client.\n", stderr); return (0); } browsers = 6; avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_fax-ipp._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp-tls._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_pdl-datastream._tcp", NULL, 0, browse_callback, devices); avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_printer._tcp", NULL, 0, browse_callback, devices); #endif /* HAVE_AVAHI */ /* * Loop until we are killed... */ while (!job_canceled) { int announce = 0; /* Announce printers? */ #ifdef HAVE_DNSSD FD_ZERO(&input); FD_SET(fd, &input); timeout.tv_sec = 0; timeout.tv_usec = 500000; if (select(fd + 1, &input, NULL, NULL, &timeout) < 0) continue; if (FD_ISSET(fd, &input)) { /* * Process results of our browsing... */ DNSServiceProcessResult(main_ref); } else announce = 1; #elif defined(HAVE_AVAHI) got_data = 0; if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0) { /* * We've been told to exit the loop. Perhaps the connection to * Avahi failed. */ break; } if (!got_data) announce = 1; #endif /* HAVE_DNSSD */ /* fprintf(stderr, "DEBUG: announce=%d\n", announce);*/ if (announce) { /* * Announce any devices we've found... */ #ifdef HAVE_DNSSD DNSServiceErrorType status; /* DNS query status */ #endif /* HAVE_DNSSD */ cups_device_t *best; /* Best matching device */ char device_uri[1024]; /* Device URI */ int count; /* Number of queries */ int sent; /* Number of sent */ for (device = (cups_device_t *)cupsArrayFirst(devices), best = NULL, count = 0, sent = 0; device; device = (cups_device_t *)cupsArrayNext(devices)) { if (device->sent) sent ++; if (device->ref) count ++; if (!device->ref && !device->sent) { /* * Found the device, now get the TXT record(s) for it... */ if (count < 50) { fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName); #ifdef HAVE_DNSSD device->ref = main_ref; status = DNSServiceQueryRecord(&(device->ref), kDNSServiceFlagsShareConnection, 0, device->fullName, kDNSServiceType_TXT, kDNSServiceClass_IN, query_callback, device); if (status != kDNSServiceErr_NoError) fprintf(stderr, "ERROR: Unable to query \"%s\" for TXT records: %d\n", device->fullName, status); /* Users never see this */ else count ++; #else if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, device->fullName, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, query_callback, device)) == NULL) fprintf(stderr, "ERROR: Unable to query \"%s\" for TXT records: %s\n", device->fullName, avahi_strerror(avahi_client_errno(client))); /* Users never see this */ else count ++; #endif /* HAVE_AVAHI */ } } else if (!device->sent) { #ifdef HAVE_DNSSD /* * Got the TXT records, now report the device... */ DNSServiceRefDeallocate(device->ref); #else avahi_record_browser_free(device->ref); #endif /* HAVE_DNSSD */ device->ref = NULL; if (!best) best = device; else if (_cups_strcasecmp(best->name, device->name) || _cups_strcasecmp(best->domain, device->domain)) { unquote(uriName, best->fullName, sizeof(uriName)); if (best->uuid) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s", best->uuid); else httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups" : "/"); cupsBackendReport("network", device_uri, best->make_and_model, best->name, best->device_id, NULL); best->sent = 1; best = device; sent ++; } else if (best->priority > device->priority || (best->priority == device->priority && best->type < device->type)) { best->sent = 1; best = device; sent ++; } else { device->sent = 1; sent ++; } } } if (best) { unquote(uriName, best->fullName, sizeof(uriName)); if (best->uuid) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s", best->uuid); else httpAssembleURI(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "dnssd", NULL, uriName, 0, best->cups_shared ? "/cups" : "/"); cupsBackendReport("network", device_uri, best->make_and_model, best->name, best->device_id, NULL); best->sent = 1; sent ++; } fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count); #ifdef HAVE_AVAHI if (sent == cupsArrayCount(devices) && browsers == 0) #else if (sent == cupsArrayCount(devices)) #endif /* HAVE_AVAHI */ break; } } return (CUPS_BACKEND_OK); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* Connection to server */ const char *dest, /* Desired printer */ *user, /* Desired user */ *val; /* Environment variable name */ char *instance; /* Printer instance */ int id, /* Desired job ID */ all, /* All printers */ interval, /* Reporting interval */ longstatus; /* Show file details */ cups_dest_t *named_dest; /* Named destination */ _cupsSetLocale(argv); /* * Check for command-line options... */ http = NULL; dest = NULL; user = NULL; id = 0; interval = 0; longstatus = 0; all = 0; for (i = 1; i < argc; i ++) if (argv[i][0] == '+') interval = atoi(argv[i] + 1); else if (argv[i][0] == '-') { switch (argv[i][1]) { case 'E' : /* Encrypt */ #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'P' : /* Printer */ if (argv[i][2]) dest = argv[i] + 2; else { i ++; if (i >= argc) { httpClose(http); usage(); } dest = argv[i]; } if ((instance = strchr(dest, '/')) != NULL) *instance++ = '\0'; http = connect_server(argv[0], http); if ((named_dest = cupsGetNamedDest(http, dest, instance)) == NULL) { if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server " "name."), argv[0]); else if (instance) _cupsLangPrintf(stderr, _("%s: Error - unknown destination \"%s/%s\"."), argv[0], dest, instance); else _cupsLangPrintf(stderr, _("%s: Unknown destination \"%s\"."), argv[0], dest); return (1); } cupsFreeDests(1, named_dest); break; case 'a' : /* All printers */ all = 1; break; case 'h' : /* Connect to host */ if (http) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected hostname after " "\"-h\" option."), argv[0]); return (1); } else cupsSetServer(argv[i]); } break; case 'l' : /* Long status */ longstatus = 1; break; default : httpClose(http); usage(); break; } } else if (isdigit(argv[i][0] & 255)) id = atoi(argv[i]); else user = argv[i]; http = connect_server(argv[0], http); if (dest == NULL && !all) { if ((named_dest = cupsGetNamedDest(http, NULL, NULL)) == NULL) { if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) { _cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]); return (1); } val = NULL; if ((dest = getenv("LPDEST")) == NULL) { if ((dest = getenv("PRINTER")) != NULL) { if (!strcmp(dest, "lp")) dest = NULL; else val = "PRINTER"; } } else val = "LPDEST"; if (dest && val) _cupsLangPrintf(stderr, _("%s: Error - %s environment variable names " "non-existent destination \"%s\"."), argv[0], val, dest); else _cupsLangPrintf(stderr, _("%s: Error - no default destination available."), argv[0]); httpClose(http); return (1); } dest = named_dest->name; } /* * Show the status in a loop... */ for (;;) { if (dest) show_printer(argv[0], http, dest); i = show_jobs(argv[0], http, dest, user, id, longstatus); if (i && interval) { fflush(stdout); sleep(interval); } else break; } /* * Close the connection to the server and return... */ httpClose(http); return (0); }