/* Get the top item on the stack. */ struct paste_buffer * paste_get_top(struct paste_stack *ps) { if (ARRAY_LENGTH(ps) == 0) return (NULL); return (ARRAY_FIRST(ps)); }
/* * Add an item onto the tail of the stack, freeing the bottom if at limit. Note * that the caller is responsible for allocating data. */ void paste_add_tail(struct paste_stack *ps, char *data, size_t size, u_int limit) { struct paste_buffer *pb; if (size == 0) return; while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); xfree(pb->data); xfree(pb); ARRAY_TRUNC(ps, 1); } pb = xmalloc(sizeof *pb); if (ARRAY_LENGTH(ps) > 0) { ARRAY_ADD(ps, ARRAY_FIRST(ps)); ARRAY_SET(ps, 0, pb); } else { ARRAY_ADD(ps, pb); } // ARRAY_INSERT(ps, 0, pb); pb->data = data; pb->size = size; }
/* Body state. */ int imap_state_body(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; struct mail *m = fctx->mail; struct fetch_imap_mail *aux; char *line, *ptr; u_int n; if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); if (sscanf(line, "* %u FETCH (", &n) != 1) return (imap_invalid(a, line)); if ((ptr = strstr(line, "BODY[] {")) == NULL) return (imap_invalid(a, line)); if (sscanf(ptr, "BODY[] {%zu}", &data->size) != 1) return (imap_invalid(a, line)); data->lines = 0; /* Fill in local data. */ aux = xcalloc(1, sizeof *aux); aux->uid = ARRAY_FIRST(&data->wanted); m->auxdata = aux; m->auxfree = imap_free; ARRAY_REMOVE(&data->wanted, 0); /* Open the mail. */ if (mail_open(m, data->size) != 0) { log_warnx("%s: failed to create mail", a->name); return (FETCH_ERROR); } m->size = 0; /* Tag mail. */ default_tags(&m->tags, data->src); if (data->server.host != NULL) { add_tag(&m->tags, "server", "%s", data->server.host); add_tag(&m->tags, "port", "%s", data->server.port); } add_tag(&m->tags, "server_uid", "%u", aux->uid); add_tag(&m->tags, "folder", "%s", ARRAY_ITEM(data->folders, data->folder)); /* If we already know the mail is oversize, start off flushing it. */ data->flushing = data->size > conf.max_size; fctx->state = imap_state_line; return (FETCH_AGAIN); }
/* Free the top item on the stack. */ int paste_free_top(struct paste_stack *ps) { struct paste_buffer *pb; if (ARRAY_LENGTH(ps) == 0) return (-1); pb = ARRAY_FIRST(ps); ARRAY_REMOVE(ps, 0); xfree(pb->data); xfree(pb); return (0); }
// wp_next struct window_pane *wp_next( struct window_pane *cur_wp, int dir, bool (*filt)(struct window_pane *, struct window_pane *), int (*sort)(const void *a, const void *b)) { struct window_pane *wp; struct window_pane *tar_wp; ARRAY_INIT(&panes); TAILQ_FOREACH(wp, &cur_wp->window->panes, entry) if (filt(cur_wp, wp)) ARRAY_ADD(&panes, wp); // bypass filter if (ARRAY_LENGTH(&panes) == 0) TAILQ_FOREACH(wp, &cur_wp->window->panes, entry) switch(dir) { case WP_L: if (wp->xoff < cur_wp->xoff) ARRAY_ADD(&panes, wp); break; case WP_R: if (wp->xoff > cur_wp->xoff) ARRAY_ADD(&panes, wp); break; case WP_U: if (wp->yoff < cur_wp->yoff) ARRAY_ADD(&panes, wp); break; case WP_D: if (wp->yoff > cur_wp->yoff) ARRAY_ADD(&panes, wp); break; } if (ARRAY_LENGTH(&panes) > 0) qsort(ARRAY_DATA(&panes), ARRAY_LENGTH(&panes), sizeof(struct window_pane *), sort); if (ARRAY_LENGTH(&panes) > 0) tar_wp = ARRAY_FIRST(&panes); ARRAY_FREE(&panes); return tar_wp; }
/* * Next state. Get next mail. This is also the idle state when completed, so * check for finished mail, exiting, and so on. */ int imap_state_next(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; /* Handle dropped and kept mail. */ if (!ARRAY_EMPTY(&data->dropped)) { if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT (\\Deleted)", ++data->tag, ARRAY_FIRST(&data->dropped)) != 0) return (FETCH_ERROR); ARRAY_REMOVE(&data->dropped, 0); fctx->state = imap_state_commit; return (FETCH_BLOCK); } if (!ARRAY_EMPTY(&data->kept)) { /* * GMail is broken and does not set the \Seen flag after mail * is fetched, so set it explicitly for kept mail. */ if (imap_putln(a, "%u UID STORE %u +FLAGS.SILENT (\\Seen)", ++data->tag, ARRAY_FIRST(&data->kept)) != 0) return (FETCH_ERROR); ARRAY_REMOVE(&data->kept, 0); fctx->state = imap_state_commit; return (FETCH_BLOCK); } /* Need to purge, switch to purge state. */ if (fctx->flags & FETCH_PURGE) { /* * If can't purge now, loop through this state until there is * no mail on the dropped queue and FETCH_EMPTY is set. Can't * have a seperate state to loop through without returning * here: mail could potentially be added to the dropped list * while in that state. */ if (fctx->flags & FETCH_EMPTY) { fctx->flags &= ~FETCH_PURGE; if (imap_putln(a, "%u EXPUNGE", ++data->tag) != 0) return (FETCH_ERROR); fctx->state = imap_state_expunge; return (FETCH_BLOCK); } /* * Must be waiting for delivery, so permit blocking even though * we (fetch) aren't waiting for any data. */ return (FETCH_BLOCK); } /* If last mail, wait for everything to be committed then close down. */ if (ARRAY_EMPTY(&data->wanted)) { if (data->committed != data->total) return (FETCH_BLOCK); if (imap_putln(a, "%u CLOSE", ++data->tag) != 0) return (FETCH_ERROR); fctx->state = imap_state_close; return (FETCH_BLOCK); } /* Fetch the next mail. */ if (imap_putln(a, "%u " "UID FETCH %u BODY[]",++data->tag, ARRAY_FIRST(&data->wanted)) != 0) return (FETCH_ERROR); fctx->state = imap_state_body; return (FETCH_BLOCK); }