int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ ipp_t *msg; /* Event message from scheduler */ ipp_state_t state; /* IPP event state */ char *subject, /* Subject for notification message */ *text; /* Text for notification message */ cups_lang_t *lang; /* Language info */ char temp[1024]; /* Temporary string */ int templen; /* Length of temporary string */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* POSIX sigaction data */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* * Don't buffer stderr... */ 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 */ /* * Validate command-line options... */ if (argc != 3) { fputs("Usage: mailto mailto:[email protected] notify-user-data\n", stderr); return (1); } if (strncmp(argv[1], "mailto:", 7)) { fprintf(stderr, "ERROR: Bad recipient \"%s\"!\n", argv[1]); return (1); } fprintf(stderr, "DEBUG: argc=%d\n", argc); for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); /* * Load configuration data... */ if ((lang = cupsLangDefault()) == NULL) return (1); if (!load_configuration()) return (1); /* * Get the reply-to address... */ templen = sizeof(temp); httpDecode64_2(temp, &templen, argv[2]); if (!strncmp(temp, "mailto:", 7)) strlcpy(mailtoReplyTo, temp + 7, sizeof(mailtoReplyTo)); else if (temp[0]) fprintf(stderr, "WARNING: Bad notify-user-data value (%d bytes) ignored!\n", templen); /* * Loop forever until we run out of events... */ for (;;) { /* * Get the next event... */ msg = ippNew(); while ((state = ippReadFile(0, msg)) != IPP_DATA) { if (state <= IPP_IDLE) break; } fprintf(stderr, "DEBUG: state=%d\n", state); if (state == IPP_ERROR) fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); if (state <= IPP_IDLE) { /* * Out of messages, free memory and then exit... */ ippDelete(msg); return (0); } /* * Get the subject and text for the message, then email it... */ subject = cupsNotifySubject(lang, msg); text = cupsNotifyText(lang, msg); fprintf(stderr, "DEBUG: subject=\"%s\"\n", subject); fprintf(stderr, "DEBUG: text=\"%s\"\n", text); if (subject && text) email_message(argv[1] + 7, subject, text); else { fputs("ERROR: Missing attributes in event notification!\n", stderr); print_attributes(msg, 4); } /* * Free the memory used for this event... */ if (subject) free(subject); if (text) free(text); ippDelete(msg); } }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ ipp_t *event; /* Event from scheduler */ ipp_state_t state; /* IPP event state */ char scheme[32], /* URI scheme ("rss") */ username[256], /* Username for remote RSS */ host[1024], /* Hostname for remote RSS */ resource[1024], /* RSS file */ *options; /* Options */ int port, /* Port number for remote RSS */ max_events; /* Maximum number of events */ http_t *http; /* Connection to remote server */ http_status_t status; /* HTTP GET/PUT status code */ char filename[1024], /* Local filename */ newname[1024]; /* filename.N */ cups_lang_t *language; /* Language information */ ipp_attribute_t *printer_up_time, /* Timestamp on event */ *notify_sequence_number,/* Sequence number */ *notify_printer_uri; /* Printer URI */ char *subject, /* Subject for notification message */ *text, /* Text for notification message */ link_url[1024], /* Link to printer */ link_scheme[32], /* Scheme for link */ link_username[256], /* Username for link */ link_host[1024], /* Host for link */ link_resource[1024]; /* Resource for link */ int link_port; /* Link port */ cups_array_t *rss; /* RSS message array */ _cups_rss_t *msg; /* RSS message */ char baseurl[1024]; /* Base URL */ fd_set input; /* Input set for select() */ struct timeval timeout; /* Timeout for select() */ int changed; /* Has the RSS data changed? */ int exit_status; /* Exit status */ fprintf(stderr, "DEBUG: argc=%d\n", argc); for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); /* * See whether we are publishing this RSS feed locally or remotely... */ if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), username, sizeof(username), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_OK) { fprintf(stderr, "ERROR: Bad RSS URI \"%s\"!\n", argv[1]); return (1); } max_events = 20; if ((options = strchr(resource, '?')) != NULL) { *options++ = '\0'; if (!strncmp(options, "max_events=", 11)) { max_events = atoi(options + 11); if (max_events <= 0) max_events = 20; } } rss = cupsArrayNew((cups_array_func_t)compare_rss, NULL); if (host[0]) { /* * Remote feed, see if we can get the current file... */ int fd; /* Temporary file */ if ((rss_password = strchr(username, ':')) != NULL) *rss_password++ = '\0'; cupsSetPasswordCB(password_cb); cupsSetUser(username); if ((fd = cupsTempFd(filename, sizeof(filename))) < 0) { fprintf(stderr, "ERROR: Unable to create temporary file: %s\n", strerror(errno)); return (1); } if ((http = httpConnect(host, port)) == NULL) { fprintf(stderr, "ERROR: Unable to connect to %s on port %d: %s\n", host, port, strerror(errno)); close(fd); unlink(filename); return (1); } status = cupsGetFd(http, resource, fd); close(fd); if (status != HTTP_OK && status != HTTP_NOT_FOUND) { fprintf(stderr, "ERROR: Unable to GET %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); httpClose(http); unlink(filename); return (1); } strlcpy(newname, filename, sizeof(newname)); httpAssembleURI(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, host, port, resource); } else { const char *cachedir, /* CUPS_CACHEDIR */ *server_name, /* SERVER_NAME */ *server_port; /* SERVER_PORT */ http = NULL; if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL) cachedir = CUPS_CACHEDIR; if ((server_name = getenv("SERVER_NAME")) == NULL) server_name = "localhost"; if ((server_port = getenv("SERVER_PORT")) == NULL) server_port = "631"; snprintf(filename, sizeof(filename), "%s/rss%s", cachedir, resource); snprintf(newname, sizeof(newname), "%s.N", filename); httpAssembleURIf(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http", NULL, server_name, atoi(server_port), "/rss%s", resource); } /* * Load the previous RSS file, if any... */ load_rss(rss, filename); changed = cupsArrayCount(rss) == 0; /* * Localize for the user's chosen language... */ language = cupsLangDefault(); /* * Read events and update the RSS file until we are out of events. */ for (exit_status = 0, event = NULL;;) { if (changed) { /* * Save the messages to the file again, uploading as needed... */ if (save_rss(rss, newname, baseurl)) { if (http) { /* * Upload the RSS file... */ if ((status = cupsPutFile(http, resource, filename)) != HTTP_CREATED) fprintf(stderr, "ERROR: Unable to PUT %s from %s on port %d: %d %s\n", resource, host, port, status, httpStatus(status)); } else { /* * Move the new RSS file over top the old one... */ if (rename(newname, filename)) fprintf(stderr, "ERROR: Unable to rename %s to %s: %s\n", newname, filename, strerror(errno)); } changed = 0; } } /* * Wait up to 30 seconds for an event... */ timeout.tv_sec = 30; timeout.tv_usec = 0; FD_ZERO(&input); FD_SET(0, &input); if (select(1, &input, NULL, NULL, &timeout) < 0) continue; else if (!FD_ISSET(0, &input)) { fprintf(stderr, "DEBUG: %s is bored, exiting...\n", argv[1]); break; } /* * Read the next event... */ event = ippNew(); while ((state = ippReadFile(0, event)) != IPP_DATA) { if (state <= IPP_IDLE) break; } if (state == IPP_ERROR) fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr); if (state <= IPP_IDLE) break; /* * Collect the info from the event... */ printer_up_time = ippFindAttribute(event, "printer-up-time", IPP_TAG_INTEGER); notify_sequence_number = ippFindAttribute(event, "notify-sequence-number", IPP_TAG_INTEGER); notify_printer_uri = ippFindAttribute(event, "notify-printer-uri", IPP_TAG_URI); subject = cupsNotifySubject(language, event); text = cupsNotifyText(language, event); if (printer_up_time && notify_sequence_number && subject && text) { /* * Create a new RSS message... */ if (notify_printer_uri) { httpSeparateURI(HTTP_URI_CODING_ALL, notify_printer_uri->values[0].string.text, link_scheme, sizeof(link_scheme), link_username, sizeof(link_username), link_host, sizeof(link_host), &link_port, link_resource, sizeof(link_resource)); httpAssembleURI(HTTP_URI_CODING_ALL, link_url, sizeof(link_url), "http", link_username, link_host, link_port, link_resource); } msg = new_message(notify_sequence_number->values[0].integer, xml_escape(subject), xml_escape(text), notify_printer_uri ? xml_escape(link_url) : NULL, printer_up_time->values[0].integer); if (!msg) { fprintf(stderr, "ERROR: Unable to create message: %s\n", strerror(errno)); exit_status = 1; break; } /* * Add it to the array... */ cupsArrayAdd(rss, msg); changed = 1; /* * Trim the array as needed... */ while (cupsArrayCount(rss) > max_events) { msg = cupsArrayFirst(rss); cupsArrayRemove(rss, msg); delete_message(msg); } } if (subject) free(subject); if (text) free(text); ippDelete(event); event = NULL; } /* * We only get here when idle or error... */ ippDelete(event); if (http) { unlink(filename); httpClose(http); } return (exit_status); }