// 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; }
void printflike2 cfg_add_cause(struct causelist *causes, const char *fmt, ...) { char *cause; va_list ap; va_start(ap, fmt); xvasprintf(&cause, fmt, ap); va_end(ap); ARRAY_ADD(causes, cause); }
void keywords_load_from_char(char *kw) { char *p, *last = NULL; keywords_clear(); for ((p = strtok_r(kw, " ", &last)); p; (p = strtok_r(NULL, " ", &last))) { ARRAY_ADD(&keywords, strdup(p)); } }
void keywords_load_from_argv(char **av) { char **kw = av; keywords_clear(); while (*kw != NULL) { ARRAY_ADD(&keywords, strdup(*kw)); kw++; } }
void cfg_add_cause(const char* fmt, ...) { va_list ap; char* msg; va_start(ap, fmt); xvasprintf(&msg, fmt, ap); va_end (ap); ARRAY_ADD(&cfg_causes, msg); }
/* Make an array of all the mboxes to visit. */ int fetch_mbox_make(struct account *a) { struct fetch_mbox_data *data = a->data; struct fetch_mbox_mbox *fmbox; char *path; u_int i, j; glob_t g; ARRAY_INIT(&data->fmboxes); for (i = 0; i < ARRAY_LENGTH(data->mboxes); i++) { path = ARRAY_ITEM(data->mboxes, i); if (glob(path, GLOB_BRACE|GLOB_NOCHECK, NULL, &g) != 0) { log_warn("%s: glob(\"%s\")", a->name, path); goto error; } if (g.gl_pathc < 1) fatalx("glob returned garbage"); for (j = 0; j < (u_int) g.gl_pathc; j++) { fmbox = xcalloc(1, sizeof *fmbox); fmbox->path = xstrdup(g.gl_pathv[j]); fmbox->fd = -1; fmbox->base = NULL; ARRAY_ADD(&data->fmboxes, fmbox); } globfree(&g); } return (0); error: for (i = 0; i < ARRAY_LENGTH(&data->fmboxes); i++) { fmbox = ARRAY_ITEM(&data->fmboxes, i); xfree(fmbox->path); xfree(fmbox); } ARRAY_FREE(&data->fmboxes); return (-1); }
void window_more_vadd(struct window_pane *wp, const char *fmt, va_list ap) { struct window_more_mode_data *data = wp->modedata; struct screen *s = &data->screen; struct screen_write_ctx ctx; char *msg; u_int size; xvasprintf(&msg, fmt, ap); ARRAY_ADD(&data->list, msg); screen_write_start(&ctx, wp, NULL); size = ARRAY_LENGTH(&data->list) - 1; if (size >= data->top && size <= data->top + screen_size_y(s) - 1) { window_more_write_line(wp, &ctx, size - data->top); if (size != data->top) window_more_write_line(wp, &ctx, 0); } else window_more_write_line(wp, &ctx, 0); screen_write_stop(&ctx); }
/* Search state 2. */ int imap_state_search2(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; char *line, *ptr; u_int uid; if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); /* Skip the header. */ if (strncasecmp(line, "* SEARCH", 8) != 0) return (imap_bad(a, line)); line += 8; /* Read each UID and save it. */ do { while (isspace((u_char) *line)) line++; ptr = strchr(line, ' '); if (ptr == NULL) ptr = strchr(line, '\0'); if (ptr == line) break; if (sscanf(line, "%u", &uid) != 1) return (imap_bad(a, line)); ARRAY_ADD(&data->wanted, uid); log_debug3("%s: fetching UID: %u", a->name, uid); line = ptr; } while (*line == ' '); fctx->state = imap_state_search3; return (FETCH_AGAIN); }
/* * Sometimes mail has wrapped header lines, this undoubtedly looks neat but * makes them a pain to match using regexps. We build a list of the newlines * in all the wrapped headers in m->wrapped, and can then quickly unwrap them * for regexp matching and wrap them again for delivery. */ u_int fill_wrapped(struct mail *m) { char *ptr; size_t end, off; u_int n; if (!ARRAY_EMPTY(&m->wrapped)) fatalx("already wrapped"); ARRAY_INIT(&m->wrapped); m->wrapchar = '\0'; end = m->body; ptr = m->data; n = 0; for (;;) { ptr = memchr(ptr, '\n', m->size - (ptr - m->data)); if (ptr == NULL) break; ptr++; off = ptr - m->data; if (off >= end) break; /* Check if the line starts with whitespace. */ if (!isblank((u_char) *ptr)) continue; /* Save the position. */ ARRAY_ADD(&m->wrapped, off - 1); n++; } return (n); }
int main(int argc, char **argv) { struct passwd *pw; struct keylist *keylist; char *s, *path, *label, *home, **var; int opt, flags, quiet, keys; #if defined(DEBUG) && defined(__OpenBSD__) malloc_options = (char *) "AFGJPX"; #endif quiet = flags = 0; label = path = NULL; login_shell = (**argv == '-'); while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUvV")) != -1) { switch (opt) { case '2': flags |= IDENTIFY_256COLOURS; flags &= ~IDENTIFY_88COLOURS; break; case '8': flags |= IDENTIFY_88COLOURS; flags &= ~IDENTIFY_256COLOURS; break; case 'c': if (shell_cmd != NULL) xfree(shell_cmd); shell_cmd = xstrdup(optarg); break; case 'V': printf("%s %s\n", __progname, VERSION); exit(0); case 'f': if (cfg_file != NULL) xfree(cfg_file); cfg_file = xstrdup(optarg); break; case 'l': login_shell = 1; break; case 'L': if (label != NULL) xfree(label); label = xstrdup(optarg); break; case 'q': quiet = 1; break; case 'S': if (path != NULL) xfree(path); path = xstrdup(optarg); break; case 'u': flags |= IDENTIFY_UTF8; break; case 'v': debug_level++; break; default: usage(); } } argc -= optind; argv += optind; if (shell_cmd != NULL && argc != 0) usage(); log_open_tty(debug_level); if (!(flags & IDENTIFY_UTF8)) { /* * If the user has set whichever of LC_ALL, LC_CTYPE or LANG * exist (in that order) to contain UTF-8, it is a safe * assumption that either they are using a UTF-8 terminal, or * if not they know that output from UTF-8-capable programs may * be wrong. */ if ((s = getenv("LC_ALL")) == NULL) { if ((s = getenv("LC_CTYPE")) == NULL) s = getenv("LANG"); } if (s != NULL && (strcasestr(s, "UTF-8") != NULL || strcasestr(s, "UTF8") != NULL)) flags |= IDENTIFY_UTF8; } environ_init(&global_environ); for (var = environ; *var != NULL; var++) environ_put(&global_environ, *var); options_init(&global_options, NULL); options_table_populate_tree(server_options_table, &global_options); options_set_number(&global_options, "quiet", quiet); options_init(&global_s_options, NULL); options_table_populate_tree(session_options_table, &global_s_options); options_set_string(&global_s_options, "default-shell", "%s", getshell()); options_init(&global_w_options, NULL); options_table_populate_tree(window_options_table, &global_w_options); /* Set the prefix option (its a list, so not in the table). */ keylist = xmalloc(sizeof *keylist); ARRAY_INIT(keylist); ARRAY_ADD(keylist, '\002'); options_set_data(&global_s_options, "prefix", keylist, xfree); /* Enable UTF-8 if the first client is on UTF-8 terminal. */ if (flags & IDENTIFY_UTF8) { options_set_number(&global_s_options, "status-utf8", 1); options_set_number(&global_s_options, "mouse-utf8", 1); options_set_number(&global_w_options, "utf8", 1); } /* Override keys to vi if VISUAL or EDITOR are set. */ if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) { if (strrchr(s, '/') != NULL) s = strrchr(s, '/') + 1; if (strstr(s, "vi") != NULL) keys = MODEKEY_VI; else keys = MODEKEY_EMACS; options_set_number(&global_s_options, "status-keys", keys); options_set_number(&global_w_options, "mode-keys", keys); } /* Locate the configuration file. */ if (cfg_file == NULL) { home = getenv("HOME"); if (home == NULL || *home == '\0') { pw = getpwuid(getuid()); if (pw != NULL) home = pw->pw_dir; } xasprintf(&cfg_file, "%s/%s", home, DEFAULT_CFG); if (access(cfg_file, R_OK) != 0 && errno == ENOENT) { xfree(cfg_file); cfg_file = NULL; } } /* * Figure out the socket path. If specified on the command-line with -S * or -L, use it, otherwise try $TMUX or assume -L default. */ parseenvironment(); if (path == NULL) { /* If no -L, use the environment. */ if (label == NULL) { if (environ_path != NULL) path = xstrdup(environ_path); else label = xstrdup("default"); } /* -L or default set. */ if (label != NULL) { if ((path = makesocketpath(label)) == NULL) { log_warn("can't create socket"); exit(1); } } } if (label != NULL) xfree(label); if (realpath(path, socket_path) == NULL) strlcpy(socket_path, path, sizeof socket_path); xfree(path); #ifdef HAVE_SETPROCTITLE /* Set process title. */ setproctitle("%s (%s)", __progname, socket_path); #endif /* Pass control to the client. */ ev_base = osdep_event_init(); exit(client_main(argc, argv, flags)); }
static void read_file (struct buffer *buffer) { int fd; void *map = MAP_FAILED; struct line line_buffer; size_t line_length; const char *line_begin, *line_end, *end; char newline[8]; size_t newline_length = 0; off_t size = 0; uint32_t digest = 0; if (-1 == (fd = open (buffer->path + 7, O_RDONLY))) { if (errno != ENOENT) { set_error (_("Failed to open '%s' for reading: %s"), buffer->path, strerror (errno)); goto failed; } buffer->charset = CHARSET_UTF8; buffer->line_ending = LINE_ENDING_LF; buffer->log = log_open (buffer->undo_path, buffer, 0); if (!buffer->log) goto failed; return; } if (-1 == (size = lseek (fd, 0, SEEK_END))) { static const size_t readbuf_size = 65536; char *readbuf; const char *begin, *end; int ret; struct line encoded_buffer; readbuf = malloc (readbuf_size); ARRAY_INIT (&encoded_buffer); while (0 < (ret = read (fd, readbuf, readbuf_size))) { digest = crc32 (digest, readbuf, ret); if (!buffer->charset) { charset_detect (&buffer->charset, &buffer->line_ending, readbuf, ret); newline_length = charset_encode_line_ending (newline, buffer->charset, buffer->line_ending); } begin = readbuf; end = readbuf + ret; while (begin != end) { line_end = memmem (begin, end - begin, newline, newline_length); if (!line_end) { ARRAY_ADD_SEVERAL (&encoded_buffer, begin, end - begin); break; } ARRAY_ADD_SEVERAL (&encoded_buffer, begin, line_end - begin); begin = line_end + newline_length; line_length = charset_decode (0, buffer->charset, &ARRAY_GET (&encoded_buffer, 0), ARRAY_COUNT (&encoded_buffer)); ARRAY_INIT (&line_buffer); ARRAY_RESERVE (&line_buffer, line_length); charset_decode (&ARRAY_GET (&line_buffer, 0), buffer->charset, &ARRAY_GET (&encoded_buffer, 0), ARRAY_COUNT (&encoded_buffer)); ARRAY_COUNT (&line_buffer) = line_length; pthread_mutex_lock (&buffer->lock); ARRAY_ADD (&buffer->lines, line_buffer); pthread_mutex_unlock (&buffer->lock); ARRAY_RESET (&encoded_buffer); } } } else if (size > 0) { if (MAP_FAILED == (map = mmap (0, size, PROT_READ, MAP_SHARED, fd, 0))) { set_error (_("Failed to mmap '%s': %s"), buffer->path, strerror (errno)); goto failed; } digest = crc32 (0, map, size); charset_detect (&buffer->charset, &buffer->line_ending, map, size); newline_length = charset_encode_line_ending (newline, buffer->charset, buffer->line_ending); end = (char *) map + size; for (line_begin = map; line_begin < end; line_begin = line_end + newline_length) { line_end = memmem (line_begin, end - line_begin, newline, newline_length); if (!line_end) line_end = end; line_length = charset_decode (0, buffer->charset, line_begin, line_end - line_begin); ARRAY_INIT (&line_buffer); ARRAY_RESERVE (&line_buffer, line_length); charset_decode (&ARRAY_GET (&line_buffer, 0), buffer->charset, line_begin, line_end - line_begin); ARRAY_COUNT (&line_buffer) = line_length; pthread_mutex_lock (&buffer->lock); ARRAY_ADD (&buffer->lines, line_buffer); pthread_mutex_unlock (&buffer->lock); /* XXX: Avoid issuing full repaints when nothing really happens onscreen */ gui_repaint (); } } else { buffer->charset = CHARSET_UTF8; buffer->line_ending = LINE_ENDING_LF; } buffer->log = log_open (buffer->undo_path, buffer, digest); failed: if (fd != -1) close (fd); if (map != MAP_FAILED) munmap (map, size); }
/* Check mail against next rule or part of expression. */ int mail_match(struct mail_ctx *mctx, struct msg *msg, struct msgbuf *msgbuf) { struct account *a = mctx->account; struct mail *m = mctx->mail; struct expritem *ei; struct replstrs *users; int should_free, this = -1, error = MAIL_CONTINUE; char desc[DESCBUFSIZE]; set_wrapped(m, ' '); /* If blocked, check for msgs from parent. */ if (mctx->msgid != 0) { if (msg == NULL || msg->id != mctx->msgid) return (MAIL_BLOCKED); mctx->msgid = 0; if (msg->type != MSG_DONE) fatalx("unexpected message"); if (msgbuf->buf != NULL && msgbuf->len != 0) { strb_destroy(&m->tags); m->tags = msgbuf->buf; reset_tags(&m->tags); } ei = mctx->expritem; switch (msg->data.error) { case MATCH_ERROR: return (MAIL_ERROR); case MATCH_TRUE: this = 1; break; case MATCH_FALSE: this = 0; break; default: fatalx("unexpected response"); } apply_result(ei, &mctx->result, this); goto next_expritem; } /* Check for completion and end of ruleset. */ if (mctx->done) return (MAIL_DONE); if (mctx->rule == NULL) { switch (conf.impl_act) { case DECISION_NONE: log_warnx("%s: reached end of ruleset. no " "unmatched-mail option; keeping mail", a->name); m->decision = DECISION_KEEP; break; case DECISION_KEEP: log_debug2("%s: reached end of ruleset. keeping mail", a->name); m->decision = DECISION_KEEP; break; case DECISION_DROP: log_debug2("%s: reached end of ruleset. dropping mail", a->name); m->decision = DECISION_DROP; break; } return (MAIL_DONE); } /* Expression not started. Start it. */ if (mctx->expritem == NULL) { /* Start the expression. */ mctx->result = 0; mctx->expritem = TAILQ_FIRST(mctx->rule->expr); } /* Check this expression item and adjust the result. */ ei = mctx->expritem; /* Handle short-circuit evaluation. */ switch (ei->op) { case OP_NONE: break; case OP_AND: /* And and the result is already false. */ if (!mctx->result) goto next_expritem; break; case OP_OR: /* Or and the result is already true. */ if (mctx->result) goto next_expritem; break; } switch (ei->match->match(mctx, ei)) { case MATCH_ERROR: return (MAIL_ERROR); case MATCH_PARENT: return (MAIL_BLOCKED); case MATCH_TRUE: this = 1; break; case MATCH_FALSE: this = 0; break; default: fatalx("unexpected op"); } apply_result(ei, &mctx->result, this); ei->match->desc(ei, desc, sizeof desc); log_debug3("%s: tried %s, result now %d", a->name, desc, mctx->result); next_expritem: /* Move to the next item. If there is one, then return. */ mctx->expritem = TAILQ_NEXT(mctx->expritem, entry); if (mctx->expritem != NULL) return (MAIL_CONTINUE); log_debug3("%s: finished rule %u, result %d", a->name, mctx->rule->idx, mctx->result); /* If the result was false, skip to find the next rule. */ if (!mctx->result) goto next_rule; log_debug2("%s: matched to rule %u", a->name, mctx->rule->idx); /* * If this rule is stop, mark the context so when we get back after * delivery we know to stop. */ if (mctx->rule->stop) mctx->done = 1; /* Handle nested rules. */ if (!TAILQ_EMPTY(&mctx->rule->rules)) { log_debug2("%s: entering nested rules", a->name); /* * Stack the current rule (we are at the end of it so the * the expritem must be NULL already). */ ARRAY_ADD(&mctx->stack, mctx->rule); /* Continue with the first rule of the nested list. */ mctx->rule = TAILQ_FIRST(&mctx->rule->rules); return (MAIL_CONTINUE); } mctx->matched = 1; /* Handle lambda actions. */ if (mctx->rule->lambda != NULL) { users = find_delivery_users(mctx, NULL, &should_free); chained = MAXACTIONCHAIN; if (fill_from_action(mctx, mctx->rule, mctx->rule->lambda, users) != 0) { if (should_free) ARRAY_FREEALL(users); return (MAIL_ERROR); } if (should_free) ARRAY_FREEALL(users); error = MAIL_DELIVER; } /* Fill the delivery action queue. */ if (!ARRAY_EMPTY(mctx->rule->actions)) { chained = MAXACTIONCHAIN; if (fill_from_strings(mctx, mctx->rule, mctx->rule->actions) != 0) return (MAIL_ERROR); error = MAIL_DELIVER; } next_rule: /* Move to the next rule. */ mctx->ruleidx = mctx->rule->idx; /* save last index */ mctx->rule = TAILQ_NEXT(mctx->rule, entry); /* If no more rules, try to move up the stack. */ while (mctx->rule == NULL) { if (ARRAY_EMPTY(&mctx->stack)) break; log_debug2("%s: exiting nested rules", a->name); mctx->rule = ARRAY_LAST(&mctx->stack); mctx->rule = TAILQ_NEXT(mctx->rule, entry); ARRAY_TRUNC(&mctx->stack, 1); } return (error); }
int load_cfg(const char *path, struct cmd_q *cmdq, char **cause) { FILE *f; u_int n, found; char *buf, *copy, *line, *cause1, *msg; size_t len, oldlen; struct cmd_list *cmdlist; log_debug("loading %s", path); if ((f = fopen(path, "rb")) == NULL) { xasprintf(cause, "%s: %s", path, strerror(errno)); return (-1); } n = found = 0; line = NULL; while ((buf = fgetln(f, &len))) { /* Trim \n. */ if (buf[len - 1] == '\n') len--; log_debug("%s: %.*s", path, (int)len, buf); /* Current line is the continuation of the previous one. */ if (line != NULL) { oldlen = strlen(line); line = xrealloc(line, 1, oldlen + len + 1); } else { oldlen = 0; line = xmalloc(len + 1); } /* Append current line to the previous. */ memcpy(line + oldlen, buf, len); line[oldlen + len] = '\0'; n++; /* Continuation: get next line? */ len = strlen(line); if (len > 0 && line[len - 1] == '\\') { line[len - 1] = '\0'; /* Ignore escaped backslash at EOL. */ if (len > 1 && line[len - 2] != '\\') continue; } copy = line; line = NULL; /* Skip empty lines. */ buf = copy; while (isspace((u_char)*buf)) buf++; if (*buf == '\0') { free(copy); continue; } /* Parse and run the command. */ if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) { free(copy); if (cause1 == NULL) continue; xasprintf(&msg, "%s:%u: %s", path, n, cause1); ARRAY_ADD(&cfg_causes, msg); free(cause1); continue; } free(copy); if (cmdlist == NULL) continue; cmdq_append(cmdq, cmdlist); cmd_list_free(cmdlist); found++; } if (line != NULL) free(line); fclose(f); return (found); }