static int handle_boundary(struct mailinfo *mi, struct strbuf *line) { struct strbuf newline = STRBUF_INIT; strbuf_addch(&newline, '\n'); again: if (line->len >= (*(mi->content_top))->len + 2 && !memcmp(line->buf + (*(mi->content_top))->len, "--", 2)) { /* we hit an end boundary */ /* pop the current boundary off the stack */ strbuf_release(*(mi->content_top)); free(*(mi->content_top)); *(mi->content_top) = NULL; /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. */ if (--mi->content_top < mi->content) { error("Detected mismatched boundaries, can't recover"); mi->input_error = -1; mi->content_top = mi->content; return 0; } handle_filter(mi, &newline); strbuf_release(&newline); if (mi->input_error) return 0; /* skip to the next boundary */ if (!find_boundary(mi, line)) return 0; goto again; } /* set some defaults */ mi->transfer_encoding = TE_DONTCARE; strbuf_reset(&mi->charset); /* slurp in this section's info */ while (read_one_header_line(line, mi->input)) check_header(mi, line, mi->p_hdr_data, 0); strbuf_release(&newline); /* replenish line */ if (strbuf_getline_lf(line, mi->input)) return 0; strbuf_addch(line, '\n'); return 1; }
static int handle_boundary(void) { struct strbuf newline = STRBUF_INIT; strbuf_addch(&newline, '\n'); again: if (line.len >= (*content_top)->len + 2 && !memcmp(line.buf + (*content_top)->len, "--", 2)) { /* we hit an end boundary */ /* pop the current boundary off the stack */ strbuf_release(*content_top); free(*content_top); *content_top = NULL; /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. */ if (--content_top < content) { fprintf(stderr, "Detected mismatched boundaries, " "can't recover\n"); exit(1); } handle_filter(&newline); strbuf_release(&newline); /* skip to the next boundary */ if (!find_boundary()) return 0; goto again; } /* set some defaults */ transfer_encoding = TE_DONTCARE; strbuf_reset(&charset); message_type = TYPE_TEXT; /* slurp in this section's info */ while (read_one_header_line(&line, fin)) check_header(&line, p_hdr_data, 0); strbuf_release(&newline); /* replenish line */ if (strbuf_getline(&line, fin, '\n')) return 0; strbuf_addch(&line, '\n'); return 1; }
static int handle_boundary(void) { char newline[]="\n"; again: if (!memcmp(line+content_top->boundary_len, "--", 2)) { /* we hit an end boundary */ /* pop the current boundary off the stack */ free(content_top->boundary); /* technically won't happen as is_multipart_boundary() will fail first. But just in case.. */ if (content_top-- < content) { fprintf(stderr, "Detected mismatched boundaries, " "can't recover\n"); exit(1); } handle_filter(newline, sizeof(newline)); /* skip to the next boundary */ if (!find_boundary()) return 0; goto again; } /* set some defaults */ transfer_encoding = TE_DONTCARE; charset[0] = 0; message_type = TYPE_TEXT; /* slurp in this section's info */ while (read_one_header_line(line, sizeof(line), fin)) check_header(line, sizeof(line), p_hdr_data, 0); /* eat the blank line after section info */ return (fgets(line, sizeof(line), fin) != NULL); }
static void handle_body(void) { struct strbuf prev = STRBUF_INIT; /* Skip up to the first boundary */ if (*content_top) { if (!find_boundary()) goto handle_body_out; } do { /* process any boundary lines */ if (*content_top && is_multipart_boundary(&line)) { /* flush any leftover */ if (prev.len) { handle_filter(&prev); strbuf_reset(&prev); } if (!handle_boundary()) goto handle_body_out; } /* Unwrap transfer encoding */ decode_transfer_encoding(&line); switch (transfer_encoding) { case TE_BASE64: case TE_QP: { struct strbuf **lines, **it, *sb; /* Prepend any previous partial lines */ strbuf_insert(&line, 0, prev.buf, prev.len); strbuf_reset(&prev); /* binary data most likely doesn't have newlines */ if (message_type != TYPE_TEXT) { handle_filter(&line); break; } /* * This is a decoded line that may contain * multiple new lines. Pass only one chunk * at a time to handle_filter() */ lines = strbuf_split(&line, '\n'); for (it = lines; (sb = *it); it++) { if (*(it + 1) == NULL) /* The last line */ if (sb->buf[sb->len - 1] != '\n') { /* Partial line, save it for later. */ strbuf_addbuf(&prev, sb); break; } handle_filter(sb); } /* * The partial chunk is saved in "prev" and will be * appended by the next iteration of read_line_with_nul(). */ strbuf_list_free(lines); break; } default: handle_filter(&line); } } while (!strbuf_getwholeline(&line, fin, '\n')); handle_body_out: strbuf_release(&prev); }
static void handle_body(void) { int rc = 0; static char newline[2000]; static char *np = newline; /* Skip up to the first boundary */ if (content_top->boundary) { if (!find_boundary()) return; } do { /* process any boundary lines */ if (content_top->boundary && is_multipart_boundary(line)) { /* flush any leftover */ if ((transfer_encoding == TE_BASE64) && (np != newline)) { handle_filter(newline, sizeof(newline)); } if (!handle_boundary()) return; } /* Unwrap transfer encoding */ decode_transfer_encoding(line, sizeof(line)); switch (transfer_encoding) { case TE_BASE64: case TE_QP: { char *op = line; /* binary data most likely doesn't have newlines */ if (message_type != TYPE_TEXT) { rc = handle_filter(line, sizeof(newline)); break; } /* this is a decoded line that may contain * multiple new lines. Pass only one chunk * at a time to handle_filter() */ do { while (*op != '\n' && *op != 0) *np++ = *op++; *np = *op; if (*np != 0) { /* should be sitting on a new line */ *(++np) = 0; op++; rc = handle_filter(newline, sizeof(newline)); np = newline; } } while (*op != 0); /* the partial chunk is saved in newline and * will be appended by the next iteration of fgets */ break; } default: rc = handle_filter(line, sizeof(newline)); } if (rc) /* nothing left to filter */ break; } while (fgets(line, sizeof(line), fin)); return; }
int main(int argc, char **argv) { struct timespec timeout = {SELECT_TIMEOUT_SECONDS, 0}; struct sigaction sigact; sigset_t select_sigset; int exitval = EXIT_FAILURE; int syslog_options = LOG_ODELAY | LOG_PERROR; int settings_retval; parse_args(argc, argv); openlog(program_invocation_short_name, syslog_options, LOG_DAEMON); syslog(LOG_INFO, "starting"); memset(&sigact, 0, sizeof(struct sigaction)); sigact.sa_handler = &sigterm_handler; if (sigfillset(&sigact.sa_mask) == -1) { syslog(LOG_ERR, "sigfillset: %s", strerror(errno)); goto out; } if (sigaction(SIGTERM, &sigact, NULL) == -1) { syslog(LOG_ERR, "sigaction SIGTERM: %s", strerror(errno)); goto out; } if (!is_daemon && sigaction(SIGINT, &sigact, NULL) == -1) { syslog(LOG_ERR, "sigaction SIGINT: %s", strerror(errno)); goto out; } if (sigemptyset(&select_sigset) == -1) { syslog(LOG_ERR, "sigemptyset: %s", strerror(errno)); goto out; } if (sigaddset(&select_sigset, SIGTERM) == -1) { syslog(LOG_ERR, "sigaddset SIGTERM: %s", strerror(errno)); goto out; } if (!is_daemon && sigaddset(&select_sigset, SIGINT) == -1) { syslog(LOG_ERR, "sigaddset SIGINT: %s", strerror(errno)); goto out; } settings_retval = settings_read(&settings); switch (settings_retval) { case 0: break; case -1: syslog(LOG_ERR, "settings_read: %s", strerror(errno)); goto out; default: syslog(LOG_ERR, "settings_read: %s", settings_strerror(settings_retval)); goto out; } if ((monitor_fd = open_evdev_by_name(settings.monitor_name)) == -1) { syslog(LOG_ERR, "open monitor %s: %s", settings.monitor_name, strerror(errno)); goto out; } if ((filter_fd = open_evdev_by_name(settings.filter_name)) == -1) { syslog(LOG_ERR, "open filter %s: %s", settings.filter_name, strerror(errno)); goto out; } if (ioctl(filter_fd, EVIOCGRAB, 1) == -1) { syslog(LOG_ERR, "grab filter: %s", strerror(errno)); goto out; } if ((clone_fd = clone_evdev(filter_fd, &settings.clone_id, settings.clone_name)) == -1) { syslog(LOG_ERR, "clone_evdev: %s", strerror(errno)); goto out; } if (is_daemon && daemonize() == -1) { syslog(LOG_ERR, "daemonize: %s", strerror(errno)); goto out; } syslog(LOG_INFO, "started"); while (is_running) { fd_set rfds; FD_ZERO(&rfds); FD_SET(monitor_fd, &rfds); FD_SET(filter_fd, &rfds); switch (pselect(filter_fd + 1, &rfds, NULL, NULL, &timeout, &select_sigset)) { case 0: break; case -1: syslog(LOG_ERR, "select: %s", strerror(errno)); goto out; default: if (FD_ISSET(filter_fd, &rfds)) { if (handle_filter() == -1) { goto out; } } else if (FD_ISSET(monitor_fd, &rfds)) { if (handle_monitor() == -1) { goto out; } } break; } } syslog(LOG_INFO, "stopped"); syslog(LOG_INFO, "terminating"); exitval = EXIT_SUCCESS; out: settings_free(&settings); if (clone_fd != -1) { if (ioctl(clone_fd, UI_DEV_DESTROY) == -1) { syslog(LOG_ERR, "destroy clone: %s", strerror(errno)); exitval = EXIT_FAILURE; } if (close(clone_fd) == -1) { syslog(LOG_ERR, "close clone: %s", strerror(errno)); exitval = EXIT_FAILURE; } } if (filter_fd != -1) { if (ioctl(filter_fd, EVIOCGRAB, 0) == -1) { syslog(LOG_ERR, "release filter: %s", strerror(errno)); exitval = EXIT_FAILURE; } if (close(filter_fd) == -1) { syslog(LOG_ERR, "close filter: %s", strerror(errno)); exitval = EXIT_FAILURE; } } if (monitor_fd != -1) { if (close(monitor_fd) == -1) { syslog(LOG_ERR, "close monitor: %s", strerror(errno)); exitval = EXIT_FAILURE; } } syslog(LOG_INFO, "terminated"); return exitval; }