int main(int unused_argc, char **argv) { VSTRING *buffer = vstring_alloc(1); msg_vstream_init(argv[0], VSTREAM_ERR); msg_verbose = 1; while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { msg_info("testing: \"%s\"", vstring_str(buffer)); valid_hostname(vstring_str(buffer), DO_GRIPE); valid_hostaddr(vstring_str(buffer), DO_GRIPE); } exit(0); }
static NORETURN PRINTFLIKE(1, 2) fatal_with_context(char *format,...) { const char *myname = "fatal_with_context"; VSTRING *vp = vstring_alloc(100); va_list ap; if (master_path == 0) msg_panic("%s: no configuration file specified", myname); va_start(ap, format); vstring_vsprintf(vp, format, ap); va_end(ap); msg_fatal("%s: %s", master_conf_context(), vstring_str(vp)); }
int main(int argc, char **argv) { VSTRING *in = vstring_alloc(10); VSTRING *out = vstring_alloc(10); int un_escape = 1; if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0) msg_fatal("usage: %s [-e (escape)]", argv[0]); if (un_escape) { while (vstring_fgets_nonl(in, VSTREAM_IN)) { unescape(out, vstring_str(in)); vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); } } else { while (vstring_fgets(in, VSTREAM_IN)) { escape(out, vstring_str(in), VSTRING_LEN(in)); vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); } } vstream_fflush(VSTREAM_OUT); exit(0); }
const char *str_long_name_mask_opt(VSTRING *buf, const char *context, const LONG_NAME_MASK * table, long mask, int flags) { const char *myname = "name_mask"; int len; static VSTRING *my_buf = 0; int delim = (flags & NAME_MASK_COMMA ? ',' : (flags & NAME_MASK_PIPE ? '|' : ' ')); const LONG_NAME_MASK *np; if ((flags & STR_NAME_MASK_REQUIRED) == 0) msg_panic("%s: missing NAME_MASK_NUMBER/FATAL/RETURN/WARN/IGNORE flag", myname); if (buf == 0) { if (my_buf == 0) my_buf = vstring_alloc(1); buf = my_buf; } VSTRING_RESET(buf); for (np = table; mask != 0; np++) { if (np->name == 0) { if (flags & NAME_MASK_NUMBER) { vstring_sprintf_append(buf, "0x%lx%c", mask, delim); } else if (flags & NAME_MASK_FATAL) { msg_fatal("%s: unknown %s bit in mask: 0x%lx", myname, context, mask); } else if (flags & NAME_MASK_RETURN) { msg_warn("%s: unknown %s bit in mask: 0x%lx", myname, context, mask); return (0); } else if (flags & NAME_MASK_WARN) { msg_warn("%s: unknown %s bit in mask: 0x%lx", myname, context, mask); } break; } if (mask & np->mask) { mask &= ~np->mask; vstring_sprintf_append(buf, "%s%c", np->name, delim); } } if ((len = VSTRING_LEN(buf)) > 0) vstring_truncate(buf, len - 1); VSTRING_TERMINATE(buf); return (STR(buf)); }
DICT *dict_env_open(const char *name, int unused_flags, int dict_flags) { DICT *dict; dict = dict_alloc(DICT_TYPE_ENVIRON, name, sizeof(*dict)); dict->lookup = dict_env_lookup; dict->update = dict_env_update; dict->close = dict_env_close; dict->flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict->fold_buf = vstring_alloc(10); dict->owner.status = DICT_OWNER_TRUSTED; return (DICT_DEBUG (dict)); }
int main(int unused_argc, char **unused_argv) { VSTRING *buf = vstring_alloc(1); ARGV *argv; struct action *ap; int interactive = isatty(0); endp_prop = vstring_alloc(1); dest_prop = vstring_alloc(1); vstream_fileno(VSTREAM_ERR) = 1; while (get_buffer(buf, VSTREAM_IN, interactive) != VSTREAM_EOF) { argv = argv_split(STR(buf), CHARS_SPACE); if (argv->argc > 0 && argv->argv[0][0] != '#') { msg_verbose = verbose_level; for (ap = actions; ap->command != 0; ap++) { if (strcmp(ap->command, argv->argv[0]) == 0) { if ((ap->flags & FLAG_NEED_CACHE) != 0 && scache == 0) msg_error("no session cache"); else ap->action(argv); break; } } msg_verbose = 0; if (ap->command == 0) msg_error("bad command: %s", argv->argv[0]); } argv_free(argv); } scache_free(scache); vstring_free(endp_prop); vstring_free(dest_prop); vstring_free(buf); exit(0); }
int main(int unused_argc, char **unused_argv) { VSTRING *vp = vstring_alloc(100); TOK822 *list; VSTRING *buf = vstring_alloc(100); #define TEST_TOKEN_LIMIT 20 while (readlline(buf, VSTREAM_IN, (int *) 0)) { while (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\n') { vstring_end(buf)[-1] = 0; vstring_truncate(buf, VSTRING_LEN(buf) - 1); } if (!isatty(vstream_fileno(VSTREAM_IN))) vstream_printf(">>>%s<<<\n\n", vstring_str(buf)); list = tok822_parse_limit(vstring_str(buf), TEST_TOKEN_LIMIT); vstream_printf("Parse tree:\n"); tok822_print(list, 0); vstream_printf("\n"); vstream_printf("Internalized:\n%s\n\n", vstring_str(tok822_internalize(vp, list, TOK822_STR_DEFL))); vstream_fflush(VSTREAM_OUT); vstream_printf("Externalized, no newlines inserted:\n%s\n\n", vstring_str(tok822_externalize(vp, list, TOK822_STR_DEFL | TOK822_STR_TRNC))); vstream_fflush(VSTREAM_OUT); vstream_printf("Externalized, newlines inserted:\n%s\n\n", vstring_str(tok822_externalize(vp, list, TOK822_STR_DEFL | TOK822_STR_LINE | TOK822_STR_TRNC))); vstream_fflush(VSTREAM_OUT); tok822_free_tree(list); } vstring_free(vp); vstring_free(buf); return (0); }
int milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, int flags, void *ptr) { MILTER_MACROS *mp = (MILTER_MACROS *) ptr; int ret; /* * We could simplify this by moving memory allocation into attr_scan*(). */ VSTRING *conn_macros = vstring_alloc(10); VSTRING *helo_macros = vstring_alloc(10); VSTRING *mail_macros = vstring_alloc(10); VSTRING *rcpt_macros = vstring_alloc(10); VSTRING *data_macros = vstring_alloc(10); VSTRING *eoh_macros = vstring_alloc(10); VSTRING *eod_macros = vstring_alloc(10); VSTRING *unk_macros = vstring_alloc(10); /* * The attribute order does not matter, except that it must be the same * as in the milter_macros_print() function. */ ret = scan_fn(fp, flags | ATTR_FLAG_MORE, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, conn_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, helo_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mail_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, data_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, eoh_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, eod_macros, ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_UNK, unk_macros, ATTR_TYPE_END); /* * Don't optimize for error. */ mp->conn_macros = vstring_export(conn_macros); mp->helo_macros = vstring_export(helo_macros); mp->mail_macros = vstring_export(mail_macros); mp->rcpt_macros = vstring_export(rcpt_macros); mp->data_macros = vstring_export(data_macros); mp->eoh_macros = vstring_export(eoh_macros); mp->eod_macros = vstring_export(eod_macros); mp->unk_macros = vstring_export(unk_macros); return (ret == 8 ? 1 : -1); }
char *dir_forest(VSTRING *buf, const char *path, int depth) { const char *myname = "dir_forest"; static VSTRING *private_buf = 0; int n; const char *cp; int ch; /* * Sanity checks. */ if (*path == 0) msg_panic("%s: empty path", myname); if (depth < 1) msg_panic("%s: depth %d", myname, depth); /* * Your buffer or mine? */ if (buf == 0) { if (private_buf == 0) private_buf = vstring_alloc(1); buf = private_buf; } /* * Generate one or more subdirectory levels, depending on the pathname * contents. When the pathname is short, use underscores instead. * Disallow non-printable characters or characters that are special to * the file system. */ VSTRING_RESET(buf); for (cp = path, n = 0; n < depth; n++) { if ((ch = *cp) == 0) { ch = '_'; } else { if (!ISPRINT(ch) || ch == '.' || ch == '/') msg_panic("%s: invalid pathname: %s", myname, path); cp++; } VSTRING_ADDCH(buf, ch); VSTRING_ADDCH(buf, '/'); } VSTRING_TERMINATE(buf); if (msg_verbose > 1) msg_info("%s: %s -> %s", myname, path, vstring_str(buf)); return (vstring_str(buf)); }
const char *check_user_acl_byuid(char *acl, uid_t uid) { struct mypasswd *mypwd; STRING_LIST *list; static VSTRING *who = 0; int matched; const char *name; /* * Optimize for the most common case. This also makes Postfix a little * more robust in the face of local infrastructure failures. */ if (strcmp(acl, STATIC_ANYONE_ACL) == 0) return (0); /* * XXX: Substitute "unknown" for UIDs without username, so that * static:anyone results in "permit" even when the uid is not found in * the password file, and so that a pattern of !unknown can be used to * block non-existent accounts. * * The alternative is to use the UID as a surrogate lookup key for * non-existent accounts. There are several reasons why this is not a * good idea. 1) An ACL with a numerical UID should work regardless of * whether or not an account has a password file entry. Therefore we * would always have search on the numerical UID whenever the username * fails to produce a match. 2) The string-list infrastructure is not * really suitable for mixing numerical and non-numerical user * information, because the numerical match is done in a separate pass * from the non-numerical match. This breaks when the ! operator is used. */ if ((mypwd = mypwuid(uid)) == 0) { name = "unknown"; } else { name = mypwd->pw_name; } list = string_list_init(MATCH_FLAG_NONE, acl); if ((matched = string_list_match(list, name)) == 0) { if (!who) who = vstring_alloc(10); vstring_strcpy(who, name); } string_list_free(list); if (mypwd) mypwfree(mypwd); return (matched ? 0 : vstring_str(who)); }
static const char *dict_env_lookup(DICT *dict, const char *name) { dict->error = 0; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } return (safe_getenv(name)); }
static const char *dict_ht_lookup(DICT *dict, const char *name) { DICT_HT *dict_ht = (DICT_HT *) dict; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name)); }
static NORETURN PRINTFLIKE(1, 2) pcf_fix_fatal(const char *fmt,...) { VSTRING *buf = vstring_alloc(100); va_list ap; /* * Replace newline with whitespace. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); translit(STR(buf), "\n", " "); msg_fatal("%s", STR(buf)); /* NOTREACHED */ }
int main(int argc, char **argv) { int type; char *name; VSTRING *fqdn = vstring_alloc(100); VSTRING *why = vstring_alloc(100); DNS_RR *rr; msg_vstream_init(argv[0], VSTREAM_ERR); if (argc != 3) msg_fatal("usage: %s type name", argv[0]); if ((type = dns_type(argv[1])) == 0) msg_fatal("invalid query type: %s", argv[1]); name = argv[2]; msg_verbose = 1; switch (dns_lookup_types(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why, type, 0)) { default: msg_fatal("%s", vstring_str(why)); case DNS_OK: printf("%s: fqdn: %s\n", name, vstring_str(fqdn)); print_rr(rr); } exit(0); }
static SSL_SESSION *get_server_session_cb(SSL *ssl, unsigned char *session_id, int session_id_length, int *unused_copy) { const char *myname = "get_server_session_cb"; TLS_SESS_STATE *TLScontext; VSTRING *cache_id; VSTRING *session_data = vstring_alloc(2048); SSL_SESSION *session = 0; if ((TLScontext = SSL_get_ex_data(ssl, TLScontext_index)) == 0) msg_panic("%s: null TLScontext in session lookup callback", myname); #define GEN_CACHE_ID(buf, id, len, service) \ do { \ buf = vstring_alloc(2 * (len + strlen(service))); \ hex_encode(buf, (char *) (id), (len)); \ vstring_sprintf_append(buf, "&s=%s", (service)); \ vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \ } while (0) GEN_CACHE_ID(cache_id, session_id, session_id_length, TLScontext->serverid); if (TLScontext->log_level >= 2) msg_info("%s: looking up session %s in %s cache", TLScontext->namaddr, STR(cache_id), TLScontext->cache_type); /* * Load the session from cache and decode it. */ if (tls_mgr_lookup(TLScontext->cache_type, STR(cache_id), session_data) == TLS_MGR_STAT_OK) { session = tls_session_activate(STR(session_data), LEN(session_data)); if (session && (TLScontext->log_level >= 2)) msg_info("%s: reloaded session %s from %s cache", TLScontext->namaddr, STR(cache_id), TLScontext->cache_type); } /* * Clean up. */ vstring_free(cache_id); vstring_free(session_data); return (session); }
DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *fp, off_t offset, int flags) { char *cp; DELIVERED_HDR_INFO *info; const HEADER_OPTS *hdr; /* * Sanity check. */ info = (DELIVERED_HDR_INFO *) mymalloc(sizeof(*info)); info->flags = flags; info->buf = vstring_alloc(10); info->table = htable_create(0); if (vstream_fseek(fp, offset, SEEK_SET) < 0) msg_fatal("seek queue file %s: %m", VSTREAM_PATH(fp)); /* * XXX Assume that mail_copy() produces delivered-to headers that fit in * a REC_TYPE_NORM record. Lowercase the delivered-to addresses for * consistency. * * XXX Don't get bogged down by gazillions of delivered-to headers. */ #define DELIVERED_HDR_LIMIT 1000 while (rec_get(fp, info->buf, 0) == REC_TYPE_NORM && info->table->used < DELIVERED_HDR_LIMIT) { if (is_header(STR(info->buf))) { if ((hdr = header_opts_find(STR(info->buf))) != 0 && hdr->type == HDR_DELIVERED_TO) { cp = STR(info->buf) + strlen(hdr->name) + 1; while (ISSPACE(*cp)) cp++; if (info->flags & FOLD_ADDR_ALL) fold_addr(cp, info->flags); if (msg_verbose) msg_info("delivered_hdr_init: %s", cp); htable_enter(info->table, cp, (char *) 0); } } else if (ISSPACE(STR(info->buf)[0])) { continue; } else { break; } } return (info); }
PSC_STATE *psc_new_session_state(VSTREAM *stream, const char *addr, const char *port) { PSC_STATE *state; HTABLE_INFO *ht; state = (PSC_STATE *) mymalloc(sizeof(*state)); PSC_INIT_TESTS(state); if ((state->smtp_client_stream = stream) != 0) psc_check_queue_length++; state->smtp_server_fd = (-1); state->smtp_client_addr = mystrdup(addr); state->smtp_client_port = mystrdup(port); state->send_buf = vstring_alloc(100); state->test_name = "TEST NAME HERE"; state->dnsbl_reply = 0; state->final_reply = "421 4.3.2 Service currently unavailable\r\n"; state->rcpt_reply = "450 4.3.2 Service currently unavailable\r\n"; state->command_count = 0; state->protocol = MAIL_PROTO_SMTP; state->helo_name = 0; state->sender = 0; state->cmd_buffer = 0; state->read_state = 0; state->ehlo_discard_mask = 0; /* XXX Should be ~0 */ state->expand_buf = 0; /* * Update the stress level. */ if (psc_stress == 0 && psc_check_queue_length >= psc_hiwat_check_queue_length) { psc_stress = 1; msg_info("entering STRESS mode with %d connections", psc_check_queue_length); } /* * Update the per-client session count. */ if ((ht = htable_locate(psc_client_concurrency, addr)) == 0) ht = htable_enter(psc_client_concurrency, addr, (char *) 0); ht->value += 1; state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value); return (state); }
void cleanup_map11_internal(CLEANUP_STATE *state, VSTRING *addr, MAPS *maps, int propagate) { VSTRING *temp = vstring_alloc(100); /* * Produce sensible output even in the face of a recoverable error. This * simplifies error recovery considerably because we can do delayed error * checking in one place, instead of having error handling code all over * the place. */ quote_822_local(temp, STR(addr)); cleanup_map11_external(state, temp, maps, propagate); unquote_822_local(addr, STR(temp)); vstring_free(temp); }
int main(int argc, char **argv) { VSTRING *buf = vstring_alloc(10); char *dir; char *base; while (vstring_get_nonl(buf, VSTREAM_IN) > 0) { dir = sane_dirname((VSTRING *) 0, STR(buf)); base = sane_basename((VSTRING *) 0, STR(buf)); vstream_printf("input=\"%s\" dir=\"%s\" base=\"%s\"\n", STR(buf), dir, base); } vstream_fflush(VSTREAM_OUT); vstring_free(buf); return (0); }
DICT *dict_ht_open(const char *name, int unused_open_flags, int dict_flags) { DICT_HT *dict_ht; dict_ht = (DICT_HT *) dict_alloc(DICT_TYPE_HT, name, sizeof(*dict_ht)); dict_ht->dict.lookup = dict_ht_lookup; dict_ht->dict.update = dict_ht_update; dict_ht->dict.sequence = dict_ht_sequence; dict_ht->dict.close = dict_ht_close; dict_ht->dict.flags = dict_flags | DICT_FLAG_FIXED; if (dict_flags & DICT_FLAG_FOLD_FIX) dict_ht->dict.fold_buf = vstring_alloc(10); dict_ht->table = htable_create(0); dict_ht->dict.owner.status = DICT_OWNER_TRUSTED; return (&dict_ht->dict); }
int main(int unused_argc, char **unused_argv) { int mask_bits; VSTRING *buf = vstring_alloc(1); const char *mask_string; while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { mask_bits = ehlo_mask(vstring_str(buf)); mask_string = str_ehlo_mask(mask_bits); vstream_printf("%s -> 0x%x -> %s\n", vstring_str(buf), mask_bits, mask_string); vstream_fflush(VSTREAM_OUT); } vstring_free(buf); exit(0); }
void smtp_sasl_start(SMTP_SESSION *session, const char *sasl_opts_name, const char *sasl_opts_val) { XSASL_CLIENT_CREATE_ARGS create_args; if (msg_verbose) msg_info("starting new SASL client"); if ((session->sasl_client = XSASL_CLIENT_CREATE(smtp_sasl_impl, &create_args, stream = session->stream, service = var_procname, server_name = session->host, security_options = sasl_opts_val)) == 0) msg_fatal("SASL per-connection initialization failed"); session->sasl_reply = vstring_alloc(20); }
int main(int unused_argc, char **unused_argv) { VSTRING *buf = vstring_alloc(100); off_t offset; while (vstring_fgets_nonl(buf, VSTREAM_IN)) { if ((offset = off_cvt_string(STR(buf))) < 0) { msg_warn("bad input %s", STR(buf)); } else { vstream_printf("%s\n", STR(off_cvt_number(buf, offset))); } vstream_fflush(VSTREAM_OUT); } vstring_free(buf); return (0); }
static RESPONSE *response(VSTREAM *stream, VSTRING *buf) { static RESPONSE rdata; int more; char *cp; /* * Initialize the response data buffer. Defend against a denial of * service attack by limiting the amount of multi-line text that we are * willing to store. */ if (rdata.buf == 0) { rdata.buf = vstring_alloc(100); vstring_ctl(rdata.buf, VSTRING_CTL_MAXLEN, (ssize_t) var_line_limit, 0); } /* * Censor out non-printable characters in server responses. Concatenate * multi-line server responses. Separate the status code from the text. * Leave further parsing up to the application. */ #define BUF ((char *) vstring_str(buf)) VSTRING_RESET(rdata.buf); for (;;) { smtp_get(buf, stream, var_line_limit, SMTP_GET_FLAG_SKIP); for (cp = BUF; *cp != 0; cp++) if (!ISPRINT(*cp) && !ISSPACE(*cp)) *cp = '?'; cp = BUF; if (msg_verbose) msg_info("<<< %s", cp); while (ISDIGIT(*cp)) cp++; rdata.code = (cp - BUF == 3 ? atoi(BUF) : 0); if ((more = (*cp == '-')) != 0) cp++; while (ISSPACE(*cp)) cp++; vstring_strcat(rdata.buf, cp); if (more == 0) break; VSTRING_ADDCH(rdata.buf, '\n'); } VSTRING_TERMINATE(rdata.buf); rdata.str = vstring_str(rdata.buf); return (&rdata); }
char *sane_dirname(VSTRING *bp, const char *path) { static VSTRING *buf; const char *last; /* * Your buffer or mine? */ if (bp == 0) { bp = buf; if (bp == 0) bp = buf = vstring_alloc(10); } /* * Special case: return "." for null or zero-length input. */ if (path == 0 || *path == 0) return (STR(vstring_strcpy(bp, "."))); /* * Remove trailing '/' characters from input. Return "/" if input is all * '/' characters. */ last = path + strlen(path) - 1; while (*last == '/') { if (last == path) return (STR(vstring_strcpy(bp, "/"))); last--; } /* * This pathname does not end in '/'. Skip to last '/' character if any. */ while (last >= path && *last != '/') last--; if (last < path) /* no '/' */ return (STR(vstring_strcpy(bp, "."))); /* * Strip trailing '/' characters from dirname (not strictly needed). */ while (last > path && *last == '/') last--; return (STR(vstring_strncpy(bp, path, last - path + 1))); }
MAPS *maps_create(const char *title, const char *map_names, int dict_flags) { const char *myname = "maps_create"; char *temp; char *bufp; static char sep[] = CHARS_COMMA_SP; static char parens[] = CHARS_BRACE; MAPS *maps; char *map_type_name; VSTRING *map_type_name_flags; DICT *dict; /* * Initialize. */ maps = (MAPS *) mymalloc(sizeof(*maps)); maps->title = mystrdup(title); maps->argv = argv_alloc(2); maps->error = 0; /* * For each specified type:name pair, either register a new dictionary, * or increment the reference count of an existing one. */ if (*map_names) { bufp = temp = mystrdup(map_names); map_type_name_flags = vstring_alloc(10); #define OPEN_FLAGS O_RDONLY while ((map_type_name = mystrtokq(&bufp, sep, parens)) != 0) { vstring_sprintf(map_type_name_flags, "%s(%o,%s)", map_type_name, OPEN_FLAGS, dict_flags_str(dict_flags)); if ((dict = dict_handle(vstring_str(map_type_name_flags))) == 0) dict = dict_open(map_type_name, OPEN_FLAGS, dict_flags); if ((dict->flags & dict_flags) != dict_flags) msg_panic("%s: map %s has flags 0%o, want flags 0%o", myname, map_type_name, dict->flags, dict_flags); dict_register(vstring_str(map_type_name_flags), dict); argv_add(maps->argv, vstring_str(map_type_name_flags), ARGV_END); } myfree(temp); vstring_free(map_type_name_flags); } return (maps); }
void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) { VSTRING *clean_addr = vstring_alloc(100); const char *bcc; /* * Note: an unqualified envelope address is for all practical purposes * equivalent to a fully qualified local address, both for delivery and * for replying. Having to support both forms is error prone, therefore * an incomplete envelope address is rewritten to fully qualified form in * the local domain context. * * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle * bounced mail traffic more robustly. */ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf); if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) vstring_strcpy(clean_addr, ""); } if (state->flags & CLEANUP_FLAG_MAP_OK) { if (cleanup_send_canon_maps && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_comm_canon_maps && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); } CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); if (state->sender) /* XXX Can't happen */ myfree(state->sender); state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */ if ((state->flags & CLEANUP_FLAG_BCC_OK) && *STR(clean_addr) && cleanup_send_bcc_maps && (bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr), IGNORE_EXTENSION)) != 0) cleanup_addr_bcc(state, bcc); vstring_free(clean_addr); }
void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) { VSTRING *clean_addr = vstring_alloc(100); const char *bcc; /* * Note: an unqualified envelope address is for all practical purposes * equivalent to a fully qualified local address, both for delivery and * for replying. Having to support both forms is error prone, therefore * an incomplete envelope address is rewritten to fully qualified form in * the local domain context. */ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, *buf ? buf : var_empty_addr); if (state->flags & CLEANUP_FLAG_MAP_OK) { if (cleanup_rcpt_canon_maps && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_comm_canon_maps && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); } cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify, state->orig_rcpt, STR(clean_addr)); if (state->recip) /* This can happen */ myfree(state->recip); state->recip = mystrdup(STR(clean_addr)); /* Used by Milter client */ if ((state->flags & CLEANUP_FLAG_BCC_OK) && *STR(clean_addr) && cleanup_rcpt_bcc_maps) { if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr), IGNORE_EXTENSION)) != 0) { cleanup_addr_bcc(state, bcc); } else if (cleanup_rcpt_bcc_maps->error) { msg_warn("%s: %s map lookup problem -- " "message not accepted, try again later", state->queue_id, cleanup_rcpt_bcc_maps->title); state->errs |= CLEANUP_STAT_WRITE; } } vstring_free(clean_addr); }
const char *fullname(void) { static VSTRING *result; char *cp; int ch; uid_t uid; struct passwd *pwd; if (result == 0) result = vstring_alloc(10); /* * Try the environment. */ if ((cp = safe_getenv("NAME")) != 0) return (vstring_str(vstring_strcpy(result, cp))); /* * Try the password file database. */ uid = getuid(); if ((pwd = getpwuid(uid)) == 0) return (0); /* * Replace all `&' characters by the login name of this user, first * letter capitalized. Although the full name comes from the protected * password file, the actual data is specified by the user so we should * not trust its sanity. */ VSTRING_RESET(result); for (cp = pwd->pw_gecos; (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == ',' || ch == ';' || ch == '%') break; if (ch == '&') { if (pwd->pw_name[0]) { VSTRING_ADDCH(result, TOUPPER(pwd->pw_name[0])); vstring_strcat(result, pwd->pw_name + 1); } } else { VSTRING_ADDCH(result, ch); } } VSTRING_TERMINATE(result); return (vstring_str(result)); }
void vlog_adhoc(const char *id, const char *orig_rcpt, const char *recipient, const char *relay, time_t entry, const char *status, const char *fmt, va_list ap) { VSTRING *why = vstring_alloc(100); int delay = time((time_t *) 0) - entry; vstring_vsprintf(why, fmt, ap); if (orig_rcpt && *orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0) msg_info("%s: to=<%s>, orig_to=<%s>, relay=%s, delay=%d, status=%s (%s)", id, recipient, orig_rcpt, relay, delay, status, vstring_str(why)); else msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)", id, recipient, relay, delay, status, vstring_str(why)); vstring_free(why); }