void cmd_resequence (char *cp) { Line *line; count = 0; /* If no range given, resequence the whole current buffer */ if (*cp == 0) { for (line = buffer_first_line (cur_position.buffer); line != NULL; line = line_next (line)) { line_reseq (line); count ++; } } /* Otherwise, process the requested lines */ else if (range_multiple (cp, &cp, resequence_range, NULL) >= 0) eoltest (cp); /* Either way, print out summary */ if (count == 0) outerr (0, "no lines resequenced\n"); else outerr (12, "%u line%s resequenced\n", count, (count == 1) ? "" : "s"); }
bool singleFitness(int individual) { int sOnes, rOnes, sZeroes, rZeroes; int i; init_line(population + individual); line_count(&sOnes, &sZeroes); if (sZeroes > sOnes) { sZeroes = sZeroes + sOnes; sOnes = 0; } else { sOnes = sZeroes + sOnes; sZeroes = 0; } for (i=0; i<STEPS_PER_FITNESS; i++) { if (!line_is_stable()) { line_next(); #ifdef FITNESS_DEBUG line_print(); #endif } else { break; } } line_count(&rOnes, &rZeroes); bool success = sZeroes == rZeroes && sOnes == rOnes; #ifdef FITNESS_DEBUG printf("Success: %s\n\n", success? "true" : "false"); #endif return success; }
static int delete_range (void *dummy, Buffer *buffer, Line *line) { /* Don't even try to delete the [EOB] line */ if (line == NULL) return (0); /* Set current position to beginning of next line after first line deleted */ if (first) { first = 0; if (buffer != cur_position.buffer) { *buffer_savpos (cur_position.buffer) = cur_position; cur_position.buffer = buffer; } cur_position.line = line; cur_position.offset = 0; buffer_dirty (buffer, 1); } if (cur_position.line == line) cur_position.line = line_next (line); /* Delete the line (and your little string, too!) */ string_delete (line_remove (line)); count ++; /* Keep going */ return (0); }
int relposition (Position *p1, Position *p2) { int firstimethru, p1relp2; Line *linebwd, *linefwd; p1relp2 = 0; if ((p1 -> buffer == p2 -> buffer) && ((p1 -> line != p2 -> line) || (p1 -> offset != p2 -> offset))) { if (p1 -> line != p2 -> line) { firstimethru = 1; for (linebwd = linefwd = p2 -> line; (linebwd != p1 -> line) && (linefwd != p1 -> line);) { if (linebwd != NULL) linebwd = line_prev (linebwd); else if (firstimethru) linebwd = buffer_last_line (p2 -> buffer); if (linefwd != NULL) linefwd = line_next (linefwd); if ((linefwd == NULL) && (linebwd == NULL)) break; firstimethru = 0; } if (p1 -> line == linebwd) p1relp2 = -1; if (p1 -> line == linefwd) p1relp2 = 1; } else { p1relp2 = (p1 -> offset > p2 -> offset) * 2 - 1; } } return (p1relp2); }
static off_t search_by_time(int fd, const char *fmt, time_t t, off_t off_m, off_t off_n) { int rval; time_t val_p; off_t off_p; #ifdef LOGCUT_DEBUG char buf0[256], buf1[256]; #endif while (off_m < off_n) { off_p = line_head(fd, (off_m + off_n) / 2); do { rval = read_time(fd, fmt, &val_p); if (off_p > 1 && rval == 0) { off_p = line_head(fd, off_p - 1); continue; } break; } while (1); if (t <= val_p) { LOGCUT_DBG((stderr, "n %10lld => %10lld %s <= %s\n", off_n, off_p, my_ctime(&t, buf0, sizeof(buf0)), my_ctime(&val_p, buf1, sizeof(buf1)))); off_n = off_p; } else { off_p = line_next(fd, (off_m + off_n) / 2); do { rval = read_time(fd, fmt, &val_p); if (rval == 0) { off_p = line_next(fd, off_p); continue; } break; } while (off_p < off_n); LOGCUT_DBG((stderr, "m %10lld => %10lld %s > %s\n", off_n, off_p, my_ctime(&t, buf0, sizeof(buf0)), my_ctime(&val_p, buf1, sizeof(buf1)))); off_m = off_p; } } return (off_m); }
/* * Find offset of body. The body is the offset of the first octet after the * separator (\n\n), or zero. */ size_t find_body(struct mail *m) { size_t len; char *ptr; line_init(m, &ptr, &len); while (ptr != NULL) { if (len == 1 && *ptr == '\n') { line_next(m, &ptr, &len); /* If no next line, body is end of mail. */ if (ptr == NULL) return (m->size); /* Otherwise, body is start of line after separator. */ return (ptr - m->data); } line_next(m, &ptr, &len); } return (0); }
/* Match a header. Same as find_header but uses fnmatch. */ char * match_header(struct mail *m, const char *patt, size_t *len, int value) { char *ptr, *last, *hdr; size_t hdrlen; line_init(m, &ptr, len); while (ptr != NULL) { if (ptr >= m->data + m->body) return (NULL); if ((last = memchr(ptr, ':', *len)) != NULL) { hdrlen = last - ptr; hdr = xmalloc(hdrlen + 1); strlcpy(hdr, ptr, hdrlen + 1); if (fnmatch(patt, hdr, FNM_CASEFOLD) == 0) break; xfree(hdr); } line_next(m, &ptr, len); } if (ptr == NULL) return (NULL); xfree(hdr); /* If the entire header is wanted, return it. */ if (!value) return (ptr); /* Include the : in the length. */ hdrlen++; /* Otherwise skip the header and following spaces. */ ptr += hdrlen; *len -= hdrlen; while (*len > 0 && isspace((u_char) *ptr)) { ptr++; (*len)--; } /* And trim newlines. */ while (*len > 0 && ptr[*len - 1] == '\n') (*len)--; if (len == 0) return (NULL); return (ptr); }
int printRuleTest(int rule, int n) { if (n<0) exit(-1); int i,j; for (i=0; i<n; i++) { init_line(population+rule); for (j=0; j<STEPS_PER_FITNESS; j++) { line_print(); printf("\n"); if (!line_is_stable()) { line_next(); } else { break; } } line_print(); printf("\nSucess: %s\n\n", (singleFitness(rule)? "true" : "false")); } }
/* * Find a header. If value is set, only the header value is returned, with EOL * stripped */ char * find_header(struct mail *m, const char *hdr, size_t *len, int value) { char *ptr; size_t hdrlen; hdrlen = strlen(hdr) + 1; /* include : */ if (m->body < hdrlen || m->size < hdrlen) return (NULL); line_init(m, &ptr, len); while (ptr != NULL) { if (ptr >= m->data + m->body) return (NULL); if (*len >= hdrlen && ptr[hdrlen - 1] == ':') { if (strncasecmp(ptr, hdr, hdrlen - 1) == 0) break; } line_next(m, &ptr, len); } if (ptr == NULL) return (NULL); /* If the entire header is wanted, return it. */ if (!value) return (ptr); /* Otherwise skip the header and following spaces. */ ptr += hdrlen; *len -= hdrlen; while (*len > 0 && isspace((u_char) *ptr)) { ptr++; (*len)--; } /* And trim newlines. */ while (*len > 0 && ptr[*len - 1] == '\n') (*len)--; if (len == 0) return (NULL); return (ptr); }
/* Count mail lines. */ void count_lines(struct mail *m, u_int *total, u_int *body) { size_t len; char *ptr; int flag; flag = 0; *total = *body = 0; line_init(m, &ptr, &len); while (ptr != NULL) { if (flag) (*body)++; if (len == 1 && *ptr == '\n') flag = 1; (*total)++; line_next(m, &ptr, &len); } }
void cmd_write (char *cp) { int rc; Line *line; Position beg_write, end_write; out_file = NULL; linecount = 0; /* Get filename */ out_name = cp; cp = uptospace (cp); if (*cp != 0) { *(cp ++) = 0; cp = skipspaces (cp); } /* Get optional range. If not specified, use the whole current buffer. */ if (*cp != 0) { rc = range_multiple (cp, &cp, write_range, out_name); if (rc == 0) eoltest (cp); } else { for (line = buffer_first_line (cur_position.buffer); line != NULL; line = line_next (line)) { rc = write_range (out_name, cur_position.buffer, line); if (rc != 0) break; } } /* Close output file */ if (out_file == NULL) outerr (0, "no file created\n"); else { if (linecount == 0) outerr (strlen (out_name), "no lines written to %s\n", out_name); else outerr (12 + strlen (out_name), "%u line%s written to %s\n", linecount, (linecount == 1) ? "" : "s", out_name); if (fclose (out_file) < 0) outerr (strlen (out_name) + strlen (strerror (errno)), "error closing file %s: %s\n", out_name, strerror (errno)); out_file = NULL; } }
int deliver_mbox_deliver(struct deliver_ctx *dctx, struct actitem *ti) { struct account *a = dctx->account; struct mail *m = dctx->mail; struct deliver_mbox_data *data = ti->data; char *path, *ptr, *lptr, *from = NULL; const char *msg; size_t len, llen; int fd, saved_errno; FILE *f; gzFile gzf; long long used; sigset_t set, oset; struct stat sb; f = gzf = NULL; fd = -1; path = replacepath(&data->path, m->tags, m, &m->rml, dctx->udata->home); if (path == NULL || *path == '\0') { log_warnx("%s: empty path", a->name); goto error; } if (data->compress) { len = strlen(path); if (len < 3 || strcmp(path + len - 3, ".gz") != 0) { path = xrealloc(path, 1, len + 4); strlcat(path, ".gz", len + 4); } } log_debug2("%s: saving to mbox %s", a->name, path); /* Save the mbox path. */ add_tag(&m->tags, "mbox_file", "%s", path); /* Check permissions and ownership. */ if (stat(path, &sb) != 0) { if (conf.no_create || errno != ENOENT) goto error_log; log_debug2("%s: creating %s", a->name, xdirname(path)); if (xmkpath(xdirname(path), -1, conf.file_group, DIRMODE) != 0) goto error_log; } else { if ((msg = checkmode(&sb, UMASK(FILEMODE))) != NULL) log_warnx("%s: %s: %s", a->name, path, msg); if ((msg = checkowner(&sb, -1)) != NULL) log_warnx("%s: %s: %s", a->name, path, msg); if ((msg = checkgroup(&sb, conf.file_group)) != NULL) log_warnx("%s: %s: %s", a->name, path, msg); } /* Create or open the mbox. */ used = 0; do { if (conf.no_create) fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types); else { fd = createlock(path, O_WRONLY|O_APPEND, -1, conf.file_group, FILEMODE, conf.lock_types); } if (fd == -1 && errno == EEXIST) fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types); if (fd == -1) { if (errno == EAGAIN) { if (locksleep(a->name, path, &used) != 0) goto error; continue; } goto error_log; } } while (fd < 0); /* Open gzFile or FILE * for writing. */ if (data->compress) { if ((gzf = gzdopen(fd, "a")) == NULL) { errno = ENOMEM; goto error_log; } } else { if ((f = fdopen(fd, "a")) == NULL) goto error_log; } /* * mboxes are a pain: if we are interrupted after this we risk * having written a partial mail. So, block SIGTERM until we're * done. */ sigemptyset(&set); sigaddset(&set, SIGTERM); if (sigprocmask(SIG_BLOCK, &set, &oset) < 0) fatal("sigprocmask failed"); /* Write the from line. */ from = make_from(m, dctx->udata->name); if (deliver_mbox_write(f, gzf, from, strlen(from)) < 0) { xfree(from); goto error_unblock; } if (deliver_mbox_write(f, gzf, "\n", 1) < 0) { xfree(from); goto error_unblock; } log_debug3("%s: using from line: %s", a->name, from); xfree(from); /* Write the mail, escaping from lines. */ line_init(m, &ptr, &len); while (ptr != NULL) { if (ptr != m->data) { /* Skip leading >s. */ lptr = ptr; llen = len; while (*lptr == '>' && llen > 0) { lptr++; llen--; } if (llen >= 5 && strncmp(lptr, "From ", 5) == 0) { log_debug2("%s: quoting from line: %.*s", a->name, (int) len - 1, ptr); if (deliver_mbox_write(f, gzf, ">", 1) < 0) goto error_unblock; } } if (deliver_mbox_write(f, gzf, ptr, len) < 0) goto error_unblock; line_next(m, &ptr, &len); } /* Append newlines. */ if (m->data[m->size - 1] == '\n') { if (deliver_mbox_write(f, gzf, "\n", 1) < 0) goto error_unblock; } else { if (deliver_mbox_write(f, gzf, "\n\n", 2) < 0) goto error_unblock; } /* Flush buffers and sync. */ if (gzf == NULL) { if (fflush(f) != 0) goto error_unblock; } else { if (gzflush(gzf, Z_FINISH) != Z_OK) { errno = EIO; goto error_unblock; } } if (fsync(fd) != 0) goto error_unblock; if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) fatal("sigprocmask failed"); if (gzf != NULL) gzclose(gzf); if (f != NULL) fclose(f); closelock(fd, path, conf.lock_types); xfree(path); return (DELIVER_SUCCESS); error_unblock: saved_errno = errno; if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0) fatal("sigprocmask failed"); errno = saved_errno; error_log: log_warn("%s: %s", a->name, path); error: if (gzf != NULL) gzclose(gzf); if (f != NULL) fclose(f); if (fd != -1) closelock(fd, path, conf.lock_types); if (path != NULL) xfree(path); return (DELIVER_FAILURE); }
int deliver_smtp_deliver(struct deliver_ctx *dctx, struct actitem *ti) { struct account *a = dctx->account; struct mail *m = dctx->mail; struct deliver_smtp_data *data = ti->data; int done, code; struct io *io; char *cause, *to, *from, *line, *ptr, *lbuf; enum deliver_smtp_state state; size_t len, llen; io = connectproxy(&data->server, conf.verify_certs, conf.proxy, IO_CRLF, conf.timeout, &cause); if (io == NULL) { log_warnx("%s: %s", a->name, cause); xfree(cause); return (DELIVER_FAILURE); } if (conf.debug > 3 && !conf.syslog) io->dup_fd = STDOUT_FILENO; llen = IO_LINESIZE; lbuf = xmalloc(llen); if (conf.host_fqdn != NULL) xasprintf(&ptr, "%s@%s", dctx->udata->name, conf.host_fqdn); else xasprintf(&ptr, "%s@%s", dctx->udata->name, conf.host_name); if (data->to.str == NULL) to = xstrdup(ptr); else { to = replacestr(&data->to, m->tags, m, &m->rml); if (to == NULL || *to == '\0') { xasprintf(&cause, "%s: empty to", a->name); from = NULL; goto error; } } if (data->from.str == NULL) from = xstrdup(ptr); else { from = replacestr(&data->from, m->tags, m, &m->rml); if (from == NULL || *from == '\0') { xasprintf(&cause, "%s: empty from", a->name); goto error; } } xfree(ptr); state = SMTP_CONNECTING; line = NULL; done = 0; do { switch (io_pollline2(io, &line, &lbuf, &llen, conf.timeout, &cause)) { case 0: cause = xstrdup("connection unexpectedly closed"); goto error; case -1: goto error; } code = deliver_smtp_code(line); cause = NULL; switch (state) { case SMTP_CONNECTING: if (code != 220) goto error; state = SMTP_HELO; if (conf.host_fqdn != NULL) io_writeline(io, "HELO %s", conf.host_fqdn); else io_writeline(io, "HELO %s", conf.host_name); break; case SMTP_HELO: if (code != 250) goto error; state = SMTP_FROM; io_writeline(io, "MAIL FROM:<%s>", from); break; case SMTP_FROM: if (code != 250) goto error; state = SMTP_TO; io_writeline(io, "RCPT TO:<%s>", to); break; case SMTP_TO: if (code != 250) goto error; state = SMTP_DATA; io_writeline(io, "DATA"); break; case SMTP_DATA: if (code != 354) goto error; line_init(m, &ptr, &len); while (ptr != NULL) { if (len > 1) { if (*ptr == '.') io_write(io, ".", 1); io_write(io, ptr, len - 1); } io_writeline(io, NULL); /* Update if necessary. */ if (io_update(io, conf.timeout, &cause) != 1) goto error; line_next(m, &ptr, &len); } state = SMTP_DONE; io_writeline(io, "."); io_flush(io, conf.timeout, NULL); break; case SMTP_DONE: if (code != 250) goto error; state = SMTP_QUIT; io_writeline(io, "QUIT"); break; case SMTP_QUIT: /* * Exchange sometimes refuses to accept QUIT as a valid * command, but since we got a 250 the mail has been * accepted. So, allow 500 here too. */ if (code != 500 && code != 221) goto error; done = 1; break; } } while (!done); xfree(lbuf); xfree(from); xfree(to); io_close(io); io_free(io); return (DELIVER_SUCCESS); error: if (cause != NULL) { log_warnx("%s: %s", a->name, cause); xfree(cause); } else log_warnx("%s: unexpected response: %s", a->name, line); io_writeline(io, "QUIT"); io_flush(io, conf.timeout, NULL); xfree(lbuf); if (from != NULL) xfree(from); if (to != NULL) xfree(to); io_close(io); io_free(io); return (DELIVER_FAILURE); }
struct attach * attach_get(struct mail *m, char **ptr, size_t *len, const char *b, int *last) { struct attach *atr, *at; char *name = NULL, *b2 = NULL; size_t bl, bl2; int last2; u_int n; bl = strlen(b); atr = xmalloc(sizeof *atr); memset(atr, 0, sizeof *atr); TAILQ_INIT(&atr->children); atr->data = *ptr - m->data; while (*ptr != NULL) { if (*len >= 13 && strncasecmp(*ptr, "content-type:", 13) == 0) break; line_next(m, ptr, len); } if (*ptr == NULL) goto error; atr->type = attach_type(m, *ptr, "name", &name); if (atr->type == NULL) { if (name != NULL) xfree(name); goto error; } atr->name = name; if (strncasecmp(atr->type, "multipart/", 10) != 0) { /* Skip the remaining headers. */ while (*ptr != NULL && *len > 1) line_next(m, ptr, len); if (*ptr == NULL) goto error; atr->body = *ptr - m->data; for (;;) { line_next(m, ptr, len); if (*ptr == NULL) break; if (*len < 3 || (*ptr)[0] != '-' || (*ptr)[1] != '-') continue; if (*len - 5 == bl && strncmp(*ptr + 2, b, bl) == 0 && strncmp(*ptr + bl + 2, "--", 2) == 0) { *last = 1; break; } if (*len - 3 == bl && strncmp(*ptr + 2, b, bl) == 0) break; } if (*ptr == NULL) goto error; atr->size = *ptr - m->data - atr->data; } else { /* XXX avoid doing this twice. */ xfree(atr->type); atr->type = attach_type(m, *ptr, "boundary", &b2); if (b2 == NULL) goto error; bl2 = strlen(b2); /* Find the first boundary. */ while (*ptr != NULL) { if ((*ptr)[0] == '-' && (*ptr)[1] == '-') { if (*len - 3 == bl2 && strncmp(*ptr + 2, b2, bl2) == 0) break; } line_next(m, ptr, len); } if (ptr == NULL) goto error; /* Now iterate over the rest. */ last2 = 0; n = 0; while (*ptr != NULL && !last2) { at = attach_get(m, ptr, len, b2, &last2); if (at == NULL) goto error; at->idx = n++; at->parent = atr; TAILQ_INSERT_TAIL(&atr->children, at, entry); } /* And skip on to the end of the multipart. */ while (*ptr != NULL) { if ((*ptr)[0] == '-' && (*ptr)[1] == '-') { if (*len - 5 == bl2 && strncmp(*ptr + 2, b2, bl2) == 0) break; } line_next(m, ptr, len); } if (*ptr == NULL) goto error; line_next(m, ptr, len); xfree(b2); } return (atr); error: if (b2 != NULL) xfree(b2); attach_free(atr); return (NULL); }
struct attach * attach_build(struct mail *m) { struct attach *atr = NULL, *at; char *hdr, *ptr, *b = NULL, *type; size_t len, bl; int last; u_int n; hdr = find_header(m, "content-type", &len, 0); if (hdr == NULL) return (NULL); type = attach_type(m, hdr, "boundary", &b); if (type == NULL || b == NULL) { if (type != NULL) xfree(type); goto error; } if (strncasecmp(type, "multipart/", 10) != 0) { xfree(type); goto error; } bl = strlen(b); atr = xmalloc(sizeof *atr); memset(atr, 0, sizeof *atr); TAILQ_INIT(&atr->children); atr->type = type; /* Find the first boundary. */ line_init(m, &ptr, &len); while (ptr != NULL) { if (ptr[0] == '-' && ptr[1] == '-') { if (len - 3 == bl && strncmp(ptr + 2, b, bl) == 0) break; } line_next(m, &ptr, &len); } if (ptr == NULL) goto error; /* Now iterate over the rest. */ last = 0; n = 0; while (ptr != NULL && !last) { if (ptr[0] == '-' && ptr[1] == '-') { if (len - 5 == bl && strncmp(ptr + 2, b, bl) == 0) break; } at = attach_get(m, &ptr, &len, b, &last); if (at == NULL) goto error; at->idx = n++; at->parent = atr; TAILQ_INSERT_TAIL(&atr->children, at, entry); } if (ptr == NULL) goto error; xfree(b); return (atr); error: if (atr != NULL) attach_free(atr); if (b != NULL) xfree(b); return (NULL); }
int deliver_imap_deliver(struct deliver_ctx *dctx, struct actitem *ti) { struct account *a = dctx->account; struct mail *m = dctx->mail; struct deliver_imap_data *data = ti->data; struct io *io; struct fetch_ctx fctx; struct fetch_imap_data fdata; char *cause, *folder, *ptr, *line; size_t len, maillen; u_int total, body; /* Connect to the IMAP server. */ io = connectproxy(&data->server, conf.verify_certs, conf.proxy, IO_CRLF, conf.timeout, &cause); if (io == NULL) { log_warnx("%s: %s", a->name, cause); xfree(cause); return (DELIVER_FAILURE); } if (conf.debug > 3 && !conf.syslog) io->dup_fd = STDOUT_FILENO; /* Work out the folder name. */ folder = replacestr(&data->folder, m->tags, m, &m->rml); if (folder == NULL || *folder == '\0') { log_warnx("%s: empty folder", a->name); goto error; } /* Fake up the fetch context for the fetch code. */ memset(&fdata, 0, sizeof fdata); fdata.user = data->user; fdata.pass = data->pass; fdata.nocrammd5 = data->nocrammd5; fdata.nologin = data->nologin; memcpy(&fdata.server, &data->server, sizeof fdata.server); fdata.io = io; fdata.only = FETCH_ONLY_ALL; a->data = &fdata; fetch_imap_state_init(a, &fctx); fctx.state = imap_state_connected; fctx.llen = IO_LINESIZE; fctx.lbuf = xmalloc(fctx.llen); /* Use the fetch code until the select1 state is reached. */ if (deliver_imap_pollto(imap_state_select1, a, io, &fctx) != 0) goto error; retry: /* Send an append command. */ if (imap_putln(a, "%u APPEND {%zu}", ++fdata.tag, strlen(folder)) != 0) goto error; switch (deliver_imap_waitappend(a, &fctx, io, &line)) { case IMAP_TAG_ERROR: if (line != NULL) imap_invalid(a, line); goto error; case IMAP_TAG_CONTINUE: break; default: if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL) goto try_create; imap_invalid(a, line); goto error; } /* * Send the mail size, not forgetting lines are CRLF terminated. The * Google IMAP server is written strangely, so send the size as if * every CRLF was a CR if the server has XYZZY. */ count_lines(m, &total, &body); maillen = m->size + total - 1; if (fdata.capa & IMAP_CAPA_XYZZY) { log_debug2("%s: adjusting size: actual %zu", a->name, maillen); maillen = m->size; } if (fdata.capa & IMAP_CAPA_NOSPACE) { if (imap_putln(a, "%s{%zu}", folder, maillen) != 0) goto error; } else { if (imap_putln(a, "%s {%zu}", folder, maillen) != 0) goto error; } switch (deliver_imap_waitappend(a, &fctx, io, &line)) { case IMAP_TAG_ERROR: if (line != NULL) imap_invalid(a, line); goto error; case IMAP_TAG_CONTINUE: break; default: if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL) goto try_create; imap_invalid(a, line); goto error; } /* Send the mail data. */ line_init(m, &ptr, &len); while (ptr != NULL) { if (len > 1) io_write(io, ptr, len - 1); io_writeline(io, NULL); /* Update if necessary. */ if (io_update(io, conf.timeout, &cause) != 1) { log_warnx("%s: %s", a->name, cause); xfree(cause); goto error; } line_next(m, &ptr, &len); } /* Wait for an okay from the server. */ switch (deliver_imap_waitappend(a, &fctx, io, &line)) { case IMAP_TAG_ERROR: case IMAP_TAG_CONTINUE: if (line != NULL) imap_invalid(a, line); goto error; default: if (imap_okay(line)) break; if (strstr(line, "[TRYCREATE]") != NULL) goto try_create; imap_invalid(a, line); goto error; } xfree(fctx.lbuf); xfree(folder); if (imap_putln(a, "%u LOGOUT", ++fdata.tag) != 0) goto error; if (deliver_imap_waitokay(a, &fctx, io, &line) != 0) goto error; fdata.disconnect(a); return (DELIVER_SUCCESS); try_create: /* XXX function? */ /* Try to create the folder. */ if (imap_putln(a, "%u CREATE {%zu}", ++fdata.tag, strlen(folder)) != 0) goto error; if (deliver_imap_waitcontinue(a, &fctx, io, &line) != 0) goto error; if (imap_putln(a, "%s", folder) != 0) goto error; if (deliver_imap_waitokay(a, &fctx, io, &line) != 0) goto error; goto retry; error: io_writeline(io, "QUIT"); io_flush(io, conf.timeout, NULL); xfree(fctx.lbuf); if (folder != NULL) xfree(folder); fdata.disconnect(a); return (DELIVER_FAILURE); }