static void pre_accept(char *unused_name, char **unused_argv) { const char *table; if ((table = dict_changed_name()) != 0) { msg_info("table %s has changed -- restarting", table); exit(0); } }
static void check_table_stats(int unused_event, char *unused_context) { const char *table; if ((table = dict_changed_name()) != 0) { msg_info("table %s has changed -- restarting", table); exit(0); } event_request_timer(check_table_stats, (char *) 0, 10); }
static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv) { int status = -1; #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT static time_t last; time_t now; const char *table; #endif /* * Sanity check. This service takes no command-line arguments. */ if (argv[0]) msg_fatal("unexpected command-line argument: %s", argv[0]); /* * Client connections are long-lived. Be sure to refesh timely. */ #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT if (server_flags == 0 && (now = event_time()) - last > 10) { if ((table = dict_changed_name()) != 0) { msg_info("table %s has changed -- restarting", table); if (multi_server_drain() == 0) server_flags = 1; } last = now; } #endif /* * This routine runs whenever a client connects to the UNIX-domain socket * dedicated to address rewriting. All connection-management stuff is * handled by the common code in multi_server.c. */ if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, ATTR_TYPE_STR, MAIL_ATTR_REQ, command, ATTR_TYPE_END) == 1) { if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) { status = rewrite_proto(stream); } else if (strcmp(vstring_str(command), RESOLVE_REGULAR) == 0) { status = resolve_proto(&resolve_regular, stream); } else if (strcmp(vstring_str(command), RESOLVE_VERIFY) == 0) { status = resolve_proto(&resolve_verify, stream); } else { msg_warn("bad command %.30s", printable(vstring_str(command), '?')); } } if (status < 0) multi_server_disconnect(stream); }
static void pre_accept(char *unused_name, char **unused_argv) { static time_t last_event_time; time_t new_event_time; const char *name; /* * If some table has changed then stop accepting new connections. Don't * check the tables more than once a second. */ new_event_time = event_time(); if (new_event_time >= last_event_time + 1 && (name = dict_changed_name()) != 0) { msg_info("table %s has changed - finishing in the background", name); event_server_drain(); } else { last_event_time = new_event_time; } }
void dict_test(int argc, char **argv) { VSTRING *keybuf = vstring_alloc(1); VSTRING *inbuf = vstring_alloc(1); DICT *dict; char *dict_name; int open_flags; char *bufp; char *cmd; const char *key; const char *value; int ch; int dict_flags = 0; int n; int rc; #define USAGE "verbose|del key|get key|put key=value|first|next|masks|flags" signal(SIGPIPE, SIG_IGN); msg_vstream_init(argv[0], VSTREAM_ERR); while ((ch = GETOPT(argc, argv, "v")) > 0) { switch (ch) { default: usage(argv[0]); case 'v': msg_verbose++; break; } } optind = OPTIND; if (argc - optind < 2) usage(argv[0]); if (strcasecmp(argv[optind + 1], "create") == 0) open_flags = O_CREAT | O_RDWR | O_TRUNC; else if (strcasecmp(argv[optind + 1], "write") == 0) open_flags = O_RDWR; else if (strcasecmp(argv[optind + 1], "read") == 0) open_flags = O_RDONLY; else msg_fatal("unknown access mode: %s", argv[2]); for (n = 2; argv[optind + n]; n++) dict_flags |= dict_flags_mask(argv[optind + 2]); if ((dict_flags & DICT_FLAG_OPEN_LOCK) == 0) dict_flags |= DICT_FLAG_LOCK; if ((dict_flags & (DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE)) == 0) dict_flags |= DICT_FLAG_DUP_REPLACE; vstream_fflush(VSTREAM_OUT); dict_name = argv[optind]; dict_allow_surrogate = 1; dict = dict_open(dict_name, open_flags, dict_flags); dict_register(dict_name, dict); while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { bufp = vstring_str(inbuf); if (!isatty(0)) { vstream_printf("> %s\n", bufp); vstream_fflush(VSTREAM_OUT); } if (*bufp == '#') continue; if ((cmd = mystrtok(&bufp, " ")) == 0) { vstream_printf("usage: %s\n", USAGE); vstream_fflush(VSTREAM_OUT); continue; } if (dict_changed_name()) msg_warn("dictionary has changed"); key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; value = mystrtok(&bufp, " ="); if (strcmp(cmd, "verbose") == 0 && !key) { msg_verbose++; } else if (strcmp(cmd, "del") == 0 && key && !value) { if ((rc = dict_del(dict, key)) > 0) vstream_printf("%s: not found\n", key); else if (rc < 0) vstream_printf("%s: error\n", key); else vstream_printf("%s: deleted\n", key); } else if (strcmp(cmd, "get") == 0 && key && !value) { if ((value = dict_get(dict, key)) == 0) { vstream_printf("%s: %s\n", key, dict->error ? "error" : "not found"); } else { vstream_printf("%s=%s\n", key, value); } } else if (strcmp(cmd, "put") == 0 && key && value) { if (dict_put(dict, key, value) != 0) vstream_printf("%s: %s\n", key, dict->error ? "error" : "not updated"); else vstream_printf("%s=%s\n", key, value); } else if (strcmp(cmd, "first") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict->error ? "error" : "not found"); } else if (strcmp(cmd, "next") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict->error ? "error" : "not found"); } else if (strcmp(cmd, "flags") == 0 && !key && !value) { vstream_printf("dict flags %s\n", dict_flags_str(dict->flags)); } else if (strcmp(cmd, "masks") == 0 && !key && !value) { vstream_printf("DICT_FLAG_IMPL_MASK %s\n", dict_flags_str(DICT_FLAG_IMPL_MASK)); vstream_printf("DICT_FLAG_PARANOID %s\n", dict_flags_str(DICT_FLAG_PARANOID)); vstream_printf("DICT_FLAG_RQST_MASK %s\n", dict_flags_str(DICT_FLAG_RQST_MASK)); vstream_printf("DICT_FLAG_INST_MASK %s\n", dict_flags_str(DICT_FLAG_INST_MASK)); } else { vstream_printf("usage: %s\n", USAGE); } vstream_fflush(VSTREAM_OUT); } vstring_free(keybuf); vstring_free(inbuf); dict_close(dict); }
int main(int argc, char **argv) { VSTRING *keybuf = vstring_alloc(1); VSTRING *inbuf = vstring_alloc(1); DICT *dict; char *dict_name; int open_flags; char *bufp; char *cmd; const char *key; const char *value; int ch; int dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; int n; signal(SIGPIPE, SIG_IGN); msg_vstream_init(argv[0], VSTREAM_ERR); while ((ch = GETOPT(argc, argv, "v")) > 0) { switch (ch) { default: usage(argv[0]); case 'v': msg_verbose++; break; } } optind = OPTIND; if (argc - optind < 2) usage(argv[0]); if (strcasecmp(argv[optind + 1], "create") == 0) open_flags = O_CREAT | O_RDWR | O_TRUNC; else if (strcasecmp(argv[optind + 1], "write") == 0) open_flags = O_RDWR; else if (strcasecmp(argv[optind + 1], "read") == 0) open_flags = O_RDONLY; else msg_fatal("unknown access mode: %s", argv[2]); for (n = 2; argv[optind + n]; n++) { if (strcasecmp(argv[optind + 2], "fold") == 0) dict_flags |= DICT_FLAG_FOLD_ANY; else if (strcasecmp(argv[optind + 2], "sync") == 0) dict_flags |= DICT_FLAG_SYNC_UPDATE; else usage(argv[0]); } dict_name = argv[optind]; dict = dict_open(dict_name, open_flags, dict_flags); dict_register(dict_name, dict); while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { bufp = vstring_str(inbuf); if (!isatty(0)) { vstream_printf("> %s\n", bufp); vstream_fflush(VSTREAM_OUT); } if (*bufp == '#') continue; if ((cmd = mystrtok(&bufp, " ")) == 0) { vstream_printf("usage: del key|get key|put key=value|first|next\n"); vstream_fflush(VSTREAM_OUT); continue; } if (dict_changed_name()) msg_warn("dictionary has changed"); key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; value = mystrtok(&bufp, " ="); if (strcmp(cmd, "del") == 0 && key && !value) { if (dict_del(dict, key)) vstream_printf("%s: not found\n", key); else vstream_printf("%s: deleted\n", key); } else if (strcmp(cmd, "get") == 0 && key && !value) { if ((value = dict_get(dict, key)) == 0) { vstream_printf("%s: %s\n", key, dict_errno == DICT_ERR_RETRY ? "soft error" : "not found"); } else { vstream_printf("%s=%s\n", key, value); } } else if (strcmp(cmd, "put") == 0 && key && value) { dict_put(dict, key, value); vstream_printf("%s=%s\n", key, value); } else if (strcmp(cmd, "first") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict_errno == DICT_ERR_RETRY ? "soft error" : "not found"); } else if (strcmp(cmd, "next") == 0 && !key && !value) { if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) vstream_printf("%s=%s\n", key, value); else vstream_printf("%s\n", dict_errno == DICT_ERR_RETRY ? "soft error" : "not found"); } else { vstream_printf("usage: del key|get key|put key=value|first|next\n"); } vstream_fflush(VSTREAM_OUT); } vstring_free(keybuf); vstring_free(inbuf); dict_close(dict); return (0); }
int dict_changed(void) { return (dict_changed_name() != 0); }