char * replace(char *src, struct strb *tags, struct mail *m, struct rmlist *rml) { const char *tptr, *alias; char *ptr, *tend, *dst, ch; size_t i, off, len, tlen; int strip; if (src == NULL) return (NULL); if (*src == '\0') return (xstrdup("")); off = 0; len = REPLBUFSIZE; dst = xmalloc(len); strip = 1; for (ptr = src; *ptr != '\0'; ptr++) { switch (*ptr) { case '%': break; default: ENSURE_FOR(dst, len, off, 1); dst[off++] = *ptr; continue; } switch (ch = *++ptr) { case '\0': goto out; case '%': ENSURE_FOR(dst, len, off, 1); dst[off++] = '%'; continue; case '[': if ((tend = strchr(ptr, ']')) == NULL) { ENSURE_FOR(dst, len, off, 2); dst[off++] = '%'; dst[off++] = '['; continue; } ptr++; if (*ptr == ':') { strip = 0; ptr++; } if (ptr == tend) continue; *tend = '\0'; if ((tptr = find_tag(tags, ptr)) == NULL) { *tend = ']'; ptr = tend; continue; } tlen = strlen(tptr); *tend = ']'; ptr = tend; break; case ':': ch = *++ptr; if (ch >= '0' && ch <= '9') { tptr = submatch(ch, m, rml, &tlen); if (tptr == NULL) continue; strip = 0; break; } ENSURE_FOR(dst, len, off, 1); dst[off++] = ch; continue; default: if (ch >= '0' && ch <= '9') { tptr = submatch(ch, m, rml, &tlen); if (tptr == NULL) continue; break; } alias = NULL; if (ALIAS_IDX((u_char) ch) != -1) alias = aliases[ALIAS_IDX((u_char) ch)]; if (alias == NULL) continue; if ((tptr = find_tag(tags, alias)) == NULL) continue; tlen = strlen(tptr); break; } if (tlen == 0) continue; ENSURE_FOR(dst, len, off, tlen); if (!strip) { memcpy(dst + off, tptr, tlen); off += tlen; continue; } for (i = 0; i < tlen; i++) { if (strchr(conf.strip_chars, tptr[i]) == NULL) dst[off++] = tptr[i]; } } out: ENSURE_FOR(dst, len, off, 1); dst[off] = '\0'; return (dst); }
/* * Return a line from the read buffer. EOL is stripped and the string returned * is zero-terminated. */ char * io_readline2(struct io *io, char **buf, size_t *len) { char *ptr, *base; size_t size, maxlen, eollen; if (io->error != NULL) return (NULL); maxlen = BUFFER_USED(io->rd); if (maxlen > IO_MAXLINELEN) maxlen = IO_MAXLINELEN; eollen = strlen(io->eol); if (BUFFER_USED(io->rd) < eollen) return (NULL); IO_DEBUG(io, "in: rd: used=%zu, free=%zu", BUFFER_USED(io->rd), BUFFER_FREE(io->rd)); base = ptr = BUFFER_OUT(io->rd); for (;;) { /* Find the first character in the EOL string. */ ptr = memchr(ptr, *io->eol, maxlen - (ptr - base)); if (ptr != NULL) { /* Found. Is there enough space for the rest? */ if (ptr - base + eollen > maxlen) { /* * No, this isn't it. Set ptr to NULL to handle * as not found. */ ptr = NULL; } else if (strncmp(ptr, io->eol, eollen) == 0) { /* This is an EOL. */ size = ptr - base; break; } } if (ptr == NULL) { IO_DEBUG(io, "not found (%zu, %d)", maxlen, IO_CLOSED(io)); /* * Not found within the length searched. If that was * the maximum length, this is an error. */ if (maxlen == IO_MAXLINELEN) { if (io->error != NULL) xfree(io->error); io->error = xstrdup("io: maximum line length exceeded"); return (NULL); } /* * If the socket has closed, just return all the data * (the buffer is known to be at least eollen long). */ if (!IO_CLOSED(io)) return (NULL); size = BUFFER_USED(io->rd); ENSURE_FOR(*buf, *len, size, 1); buffer_read(io->rd, *buf, size); (*buf)[size] = '\0'; return (*buf); } /* Start again from the next character. */ ptr++; } /* Copy the line and remove it from the buffer. */ ENSURE_FOR(*buf, *len, size, 1); if (size != 0) buffer_read(io->rd, *buf, size); (*buf)[size] = '\0'; /* Discard the EOL from the buffer. */ buffer_remove(io->rd, eollen); IO_DEBUG(io, "out: %zu bytes, rd: used=%zu, free=%zu", size, BUFFER_USED(io->rd), BUFFER_FREE(io->rd)); return (*buf); }
char * read_string(char endch, int esc) { int ch, oldch; size_t pos, len, slen; char *name, *s, *buf; struct macro *macro; len = 24; buf = xmalloc(len + 1); pos = 0; while ((ch = lex_getc()) != endch) { switch (ch) { case EOF: yyerror("missing %c", endch); case '\\': if (!esc) break; switch (ch = lex_getc()) { case EOF: yyerror("missing %c", endch); case 'r': ch = '\r'; break; case 'n': ch = '\n'; break; case 't': ch = '\t'; break; } break; case '$': case '%': if (!esc) break; oldch = ch; ch = lex_getc(); if (ch == EOF) yyerror("missing %c", endch); if (ch != '{') { lex_ungetc(ch); ch = oldch; break; } name = read_macro(oldch, '{'); if ((macro = find_macro(name)) == NULL) { xfree(name); continue; } xfree(name); if (macro->type == MACRO_NUMBER) xasprintf(&s, "%lld", macro->value.num); else s = macro->value.str; slen = strlen(s); ENSURE_FOR(buf, len, pos, slen + 1); memcpy(buf + pos, s, slen); pos += slen; if (macro->type == MACRO_NUMBER) xfree(s); continue; } buf[pos++] = ch; ENSURE_SIZE(buf, len, pos); } buf[pos] = '\0'; return (buf); }