//void do_sender(const char *s) void do_sender(char *s) { char *x; int n; int a; int i; env_unset("QMAILNAME"); env_unset("MAILNAME"); env_unset("NAME"); env_unset("QMAILHOST"); env_unset("MAILHOST"); n = str_len(s); a = str_rchr(s, '@'); if (a == n) { env_put("QMAILUSER", s); return; } env_put("QMAILHOST",s + a + 1); x = (char *) alloc((a + 1) * sizeof(char)); if (!x) nomem(); for (i = 0; i < a; i++) x[i] = s[i]; x[i] = 0; env_put("QMAILUSER", x); alloc_free(x); }
static void service_process_setup_config_environment(struct service *service) { const struct master_service_settings *set = service->list->service_set; switch (service->type) { case SERVICE_TYPE_CONFIG: env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=", service->config_file_path, NULL)); break; case SERVICE_TYPE_LOG: /* give the log's configuration directly, so it won't depend on config process */ env_put("DOVECONF_ENV=1"); env_put(t_strconcat("LOG_PATH=", set->log_path, NULL)); env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL)); env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL)); env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL)); env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL)); if (set->verbose_proctitle) env_put("VERBOSE_PROCTITLE=1"); env_put("SSL=no"); break; default: env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=", services_get_config_socket_path(service->list), NULL)); break; } }
static void ATTR_NORETURN master_service_exec_config(struct master_service *service, const struct master_service_settings_input *input) { const char **conf_argv, *binary_path = service->argv[0]; const char *home = NULL, *user = NULL, *timestamp = NULL; unsigned int i, argv_max_count; (void)t_binary_abspath(&binary_path); if (!service->keep_environment && !input->preserve_environment) { if (input->preserve_home) home = getenv("HOME"); if (input->preserve_user) user = getenv("USER"); if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) timestamp = getenv("LOG_STDERR_TIMESTAMP"); master_service_env_clean(); if (home != NULL) env_put(t_strconcat("HOME=", home, NULL)); if (user != NULL) env_put(t_strconcat("USER="******"LOG_STDERR_TIMESTAMP=", timestamp, NULL)); } if (input->use_sysexits) env_put("USE_SYSEXITS=1"); /* @UNSAFE */ i = 0; argv_max_count = 11 + (service->argc + 1) + 1; conf_argv = t_new(const char *, argv_max_count); conf_argv[i++] = DOVECOT_CONFIG_BIN_PATH; if (input->service != NULL) { conf_argv[i++] = "-f"; conf_argv[i++] = t_strconcat("service=", input->service, NULL); } conf_argv[i++] = "-c"; conf_argv[i++] = service->config_path; if (input->module != NULL) { conf_argv[i++] = "-m"; conf_argv[i++] = input->module; if (service->want_ssl_settings) { conf_argv[i++] = "-m"; conf_argv[i++] = "ssl"; } } if (input->parse_full_config) conf_argv[i++] = "-p"; conf_argv[i++] = "-e"; conf_argv[i++] = binary_path; memcpy(conf_argv+i, service->argv + 1, (service->argc) * sizeof(conf_argv[0])); i += service->argc; i_assert(i < argv_max_count); execv_const(conf_argv[0], conf_argv); }
static void env_put_extra_fields(const char *extra_fields) { const char *const *tmp; const char *key, *p; for (tmp = t_strsplit(extra_fields, "\t"); *tmp != NULL; tmp++) { key = t_str_ucase(t_strcut(*tmp, '=')); p = strchr(*tmp, '='); if (p == NULL) env_put(t_strconcat(key, "=1", NULL)); else env_put(t_strconcat(key, p, NULL)); } }
static void env_clean_except_real(const char *const preserve_envs[]) { ARRAY_TYPE(const_string) copy; const char *value, *const *envp; unsigned int i; t_array_init(©, 16); for (i = 0; preserve_envs[i] != NULL; i++) { const char *key = preserve_envs[i]; value = getenv(key); if (value != NULL) { value = t_strconcat(key, "=", value, NULL); array_append(©, &value, 1); } } /* Note that if the original environment was set with env_put(), the environment strings will be invalid after env_clean(). That's why we t_strconcat() them above. */ env_clean(); array_foreach(©, envp) env_put(*envp); }
static void main_init(void) { struct module_dir_load_settings mod_set; void **sets; sets = master_service_settings_get_others(master_service); dict_settings = sets[0]; if (*dict_settings->dict_db_config != '\0') { /* for berkeley db library */ env_put(t_strconcat("DB_CONFIG=", dict_settings->dict_db_config, NULL)); } memset(&mod_set, 0, sizeof(mod_set)); mod_set.version = master_service_get_version_string(master_service); mod_set.require_init_funcs = TRUE; modules = module_dir_load(DICT_MODULE_DIR, NULL, &mod_set); module_dir_init(modules); /* Register only after loading modules. They may contain SQL drivers, which we'll need to register. */ dict_drivers_register_all(); }
static void test_var_expand_builtin(void) { static struct var_expand_test tests[] = { { "%{hostname}", NULL }, { "%{pid}", NULL }, { "a%{env:FOO}b", "abaRb" } }; static struct var_expand_table table[] = { { '\0', NULL, NULL } }; string_t *str = t_str_new(128); unsigned int i; tests[0].out = my_hostname; tests[1].out = my_pid; env_put("FOO=baR"); test_begin("var_expand"); for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); var_expand(str, tests[i].in, table); test_assert(strcmp(tests[i].out, str_c(str)) == 0); } test_end(); }
static void test_var_expand_builtin(void) { static struct var_expand_test tests[] = { { "%{hostname}", NULL, 1 }, { "%{pid}", NULL, 1 }, { "a%{env:FOO}b", "abaRb", 1 }, { "%50Hv", "1f", 1 }, { "%50Hw", "2e", 1 }, { "%50Nv", "25", 1 }, { "%50Nw", "e", 1 }, { "%{nonexistent}", "UNSUPPORTED_VARIABLE_nonexistent", 0 }, { "%{nonexistent:default}", "UNSUPPORTED_VARIABLE_nonexistent", 0 }, }; static const struct var_expand_table table[] = { { 'v', "value", NULL }, { 'w', "value2", NULL }, { '\0', NULL, NULL } }; string_t *str = t_str_new(128); const char *error; unsigned int i; tests[0].out = my_hostname; tests[1].out = my_pid; env_put("FOO=baR"); test_begin("var_expand - builtin"); for (i = 0; i < N_ELEMENTS(tests); i++) { str_truncate(str, 0); test_assert_idx(var_expand(str, tests[i].in, table, &error) == tests[i].ret, i); test_assert_idx(strcmp(tests[i].out, str_c(str)) == 0, i); } test_end(); }
static void ATTR_NORETURN checkpassword_lookup_child(struct auth_request *request, struct checkpassword_userdb_module *module, int fd_in, int fd_out) { const char *cmd, *const *args; if (dup2(fd_out, 3) < 0 || dup2(fd_in, 4) < 0) { auth_request_log_error(request, "userdb-checkpassword", "dup2() failed: %m"); } else { /* We want to retrieve user data and don't do authorization, so we need to signalize the checkpassword program that the password shall be ignored by setting AUTHORIZED. This needs a special checkpassword program which knows how to handle this. */ env_put("AUTHORIZED=1"); checkpassword_setup_env(request); cmd = checkpassword_get_cmd(request, module->checkpassword_path, module->checkpassword_reply_path); auth_request_log_debug(request, "userdb-checkpassword", "execute: %s", cmd); /* very simple argument splitting. */ args = t_strsplit(cmd, " "); execv_const(args[0], args); } exit(2); }
struct pop3c_client * pop3c_client_init(const struct pop3c_client_settings *set) { struct pop3c_client *client; struct ssl_iostream_settings ssl_set; const char *error; pool_t pool; // CLEANUP: Remove Warning i_warning("pop3c_client_init called"); pool = pool_alloconly_create("pop3c client", 1024); client = p_new(pool, struct pop3c_client, 1); client->pool = pool; client->fd = -1; client->set.debug = set->debug; client->set.host = p_strdup(pool, set->host); client->set.port = set->port; client->set.master_user = p_strdup_empty(pool, set->master_user); client->set.username = p_strdup(pool, set->username); // CLEANUP: remove warning i_warning("pop3c_client_init: username %s", client->set.username); env_put(t_strconcat("POP3C_USERNAME="******"pop3c(%s:%u): Couldn't initialize SSL context: %s", set->host, set->port, error); } } return client; }
void checkpassword_setup_env(struct auth_request *request) { /* Besides passing the standard username and password in a pipe, also pass some other possibly interesting information via environment. Use UCSPI names for local/remote IPs. */ env_put("PROTO=TCP"); /* UCSPI */ env_put(t_strconcat("SERVICE=", request->service, NULL)); if (request->local_ip.family != 0) { env_put(t_strconcat("TCPLOCALIP=", net_ip2addr(&request->local_ip), NULL)); /* FIXME: for backwards compatibility only, remove some day */ env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&request->local_ip), NULL)); } if (request->remote_ip.family != 0) { env_put(t_strconcat("TCPREMOTEIP=", net_ip2addr(&request->remote_ip), NULL)); /* FIXME: for backwards compatibility only, remove some day */ env_put(t_strconcat("REMOTE_IP=", net_ip2addr(&request->remote_ip), NULL)); } if (request->local_port != 0) { env_put(t_strdup_printf("TCPLOCALPORT=%u", request->local_port)); } if (request->remote_port != 0) { env_put(t_strdup_printf("TCPREMOTEPORT=%u", request->remote_port)); } if (request->master_user != NULL) { env_put(t_strconcat("MASTER_USER=", request->master_user, NULL)); } if (request->extra_fields != NULL) { const char *fields = auth_stream_reply_export(request->extra_fields); /* extra fields could come from master db */ env_put_extra_fields(fields); } }
void smtpd() { if (!env_get("PROTO")) { if (!env_put("RELAYCLIENT=")) nomem(); if (!env_put("DATABYTES=0")) nomem(); if (!env_put("PROTO=TCP")) nomem(); if (!env_put("TCPLOCALIP=127.0.0.1")) nomem(); if (!env_put("TCPLOCALHOST=localhost")) nomem(); if (!env_put("TCPREMOTEIP=127.0.0.1")) nomem(); if (!env_put("TCPREMOTEHOST=localhost")) nomem(); if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem(); } execv(*smtpdarg,(char **)smtpdarg); substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n"); _exit(111); }
static void exec_child(struct master_service_connection *conn, const char *const *args, const char *const *envs) { unsigned int i, socket_count; if (dup2(conn->fd, STDIN_FILENO) < 0) i_fatal("dup2() failed: %m"); if (dup2(conn->fd, STDOUT_FILENO) < 0) i_fatal("dup2() failed: %m"); /* close all fds */ socket_count = master_service_get_socket_count(master_service); for (i = 0; i < socket_count; i++) { if (close(MASTER_LISTEN_FD_FIRST + i) < 0) i_error("close(listener) failed: %m"); } if (close(MASTER_STATUS_FD) < 0) i_error("close(status) failed: %m"); if (close(conn->fd) < 0) i_error("close(conn->fd) failed: %m"); for (; *args != NULL; args++) { const char *arg = t_str_tabunescape(*args); array_append(&exec_args, &arg, 1); } array_append_zero(&exec_args); env_clean(); if (envs != NULL) { for(; *envs != NULL; envs++) env_put(*envs); } args = array_idx(&exec_args, 0); execvp_const(args[0], args); }
static void service_dup_fds(struct service *service) { struct service_listener *const *listeners; ARRAY_TYPE(dup2) dups; string_t *listener_settings; int fd = MASTER_LISTEN_FD_FIRST; unsigned int i, count, socket_listener_count; /* stdin/stdout is already redirected to /dev/null. Other master fds should have been opened with fd_close_on_exec() so we don't have to worry about them. because the destination fd might be another one's source fd we have to be careful not to overwrite anything. dup() the fd when needed */ socket_listener_count = 0; listeners = array_get(&service->listeners, &count); t_array_init(&dups, count + 10); switch (service->type) { case SERVICE_TYPE_LOG: i_assert(fd == MASTER_LISTEN_FD_FIRST); services_log_dup2(&dups, service->list, fd, &socket_listener_count); fd += socket_listener_count; break; case SERVICE_TYPE_ANVIL: dup2_append(&dups, service_anvil_global->log_fdpass_fd[0], MASTER_ANVIL_LOG_FDPASS_FD); /* nonblocking anvil fd must be the first one. anvil treats it as the master's fd */ dup2_append(&dups, service_anvil_global->nonblocking_fd[0], fd++); dup2_append(&dups, service_anvil_global->blocking_fd[0], fd++); socket_listener_count += 2; break; default: break; } /* add listeners */ listener_settings = t_str_new(256); for (i = 0; i < count; i++) { if (listeners[i]->fd != -1) { str_truncate(listener_settings, 0); str_append_tabescaped(listener_settings, listeners[i]->name); if (listeners[i]->type == SERVICE_LISTENER_INET) { if (listeners[i]->set.inetset.set->ssl) str_append(listener_settings, "\tssl"); if (listeners[i]->set.inetset.set->haproxy) str_append(listener_settings, "\thaproxy"); } dup2_append(&dups, listeners[i]->fd, fd++); env_put(t_strdup_printf("SOCKET%d_SETTINGS=%s", socket_listener_count, str_c(listener_settings))); socket_listener_count++; } } if (service->login_notify_fd != -1) { dup2_append(&dups, service->login_notify_fd, MASTER_LOGIN_NOTIFY_FD); } switch (service->type) { case SERVICE_TYPE_LOG: case SERVICE_TYPE_ANVIL: case SERVICE_TYPE_CONFIG: dup2_append(&dups, null_fd, MASTER_ANVIL_FD); break; case SERVICE_TYPE_UNKNOWN: case SERVICE_TYPE_LOGIN: case SERVICE_TYPE_STARTUP: dup2_append(&dups, service_anvil_global->blocking_fd[1], MASTER_ANVIL_FD); break; } dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD); if (service->type != SERVICE_TYPE_ANVIL) { dup2_append(&dups, service->list->master_dead_pipe_fd[1], MASTER_DEAD_FD); } else { dup2_append(&dups, global_master_dead_pipe_fd[1], MASTER_DEAD_FD); } if (service->type == SERVICE_TYPE_LOG) { /* keep stderr as-is. this is especially important when log_path=/dev/stderr, but might be helpful even in other situations for logging startup errors */ } else { /* set log file to stderr. dup2() here immediately so that we can set up logging to it without causing any log messages to be lost. */ i_assert(service->log_fd[1] != -1); env_put("LOG_SERVICE=1"); if (dup2(service->log_fd[1], STDERR_FILENO) < 0) i_fatal("dup2(log fd) failed: %m"); i_set_failure_internal(); } /* make sure we don't leak syslog fd. try to do it as late as possible, but also before dup2()s in case syslog fd is one of them. */ closelog(); if (dup2_array(&dups) < 0) i_fatal("service(%s): dup2s failed", service->set->name); i_assert(fd == MASTER_LISTEN_FD_FIRST + (int)socket_listener_count); env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count)); }
static void service_process_setup_environment(struct service *service, unsigned int uid, const char *hostdomain) { master_service_env_clean(); env_put(MASTER_IS_PARENT_ENV"=1"); service_process_setup_config_environment(service); env_put(t_strdup_printf(MASTER_CLIENT_LIMIT_ENV"=%u", service->client_limit)); env_put(t_strdup_printf(MASTER_PROCESS_LIMIT_ENV"=%u", service->process_limit)); env_put(t_strdup_printf(MASTER_PROCESS_MIN_AVAIL_ENV"=%u", service->set->process_min_avail)); env_put(t_strdup_printf(MASTER_SERVICE_IDLE_KILL_ENV"=%u", service->idle_kill)); if (service->set->service_count != 0) { env_put(t_strdup_printf(MASTER_SERVICE_COUNT_ENV"=%u", service->set->service_count)); } env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid)); env_put(t_strdup_printf(MY_HOSTNAME_ENV"=%s", my_hostname)); env_put(t_strdup_printf(MY_HOSTDOMAIN_ENV"=%s", hostdomain)); if (!service->set->master_set->version_ignore) env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION); if (ssl_manual_key_password != NULL && service->have_inet_listeners) { /* manually given SSL password. give it only to services that have inet listeners. */ env_put(t_strconcat(MASTER_SSL_KEY_PASSWORD_ENV"=", ssl_manual_key_password, NULL)); } if (service->type == SERVICE_TYPE_ANVIL && service_anvil_global->restarted) env_put("ANVIL_RESTARTED=1"); }
static void client_connected(struct master_service_connection *conn) { enum mail_storage_service_flags flags = MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS; string_t *instr, *keys; const char **args, *key, *value, *error, *version_line, *data_line; struct mail_storage_service_ctx *service_ctx; struct mail_storage_service_input input; struct mail_storage_service_user *user; char buf[1024]; unsigned int i, socket_count; int fd = -1; ssize_t ret; alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS); net_set_nonblock(conn->fd, FALSE); instr = t_str_new(1024); ret = fd_read(conn->fd, buf, sizeof(buf), &fd); while (ret > 0) { str_append_n(instr, buf, ret); if (buf[ret-1] == '\n' && strchr(str_c(instr), '\n')[1] != '\0') { str_truncate(instr, str_len(instr)-1); break; } ret = read(conn->fd, buf, sizeof(buf)); } version_line = str_c(instr); data_line = strchr(version_line, '\n'); if (data_line != NULL) version_line = t_strdup_until(version_line, data_line++); else version_line = NULL; if (ret > 0 || version_line != NULL) { if (version_line == NULL || !version_string_verify(version_line, "script-login", SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) { i_fatal("Client not compatible with this binary " "(connecting to wrong socket?)"); } } if (ret <= 0) { if (ret < 0) i_fatal("read() failed: %m"); else i_fatal("read() failed: disconnected"); } if (fd == -1) i_fatal("client fd not received"); alarm(0); /* put everything to environment */ env_clean(); keys = t_str_new(256); args = t_strsplit_tab(data_line); if (str_array_length(args) < 3) i_fatal("Missing input fields"); i = 0; memset(&input, 0, sizeof(input)); input.module = "mail"; /* need to get mail_uid, mail_gid */ input.service = "script-login"; (void)net_addr2ip(args[i++], &input.local_ip); (void)net_addr2ip(args[i++], &input.remote_ip); input.username = args[i++]; input.userdb_fields = args + i; env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL)); env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL)); env_put(t_strconcat("USER="******"%s ", key); } } env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL)); master_service_init_log(master_service, t_strdup_printf("script-login(%s): ", input.username)); if (drop_to_userdb_privileges) { service_ctx = mail_storage_service_init(master_service, NULL, flags); if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0) i_fatal("%s", error); mail_storage_service_restrict_setenv(service_ctx, user); /* we can't exec anything in a chroot */ env_remove("RESTRICT_CHROOT"); restrict_access_by_env(getenv("HOME"), TRUE); } if (dup2(fd, STDIN_FILENO) < 0) i_fatal("dup2() failed: %m"); if (dup2(fd, STDOUT_FILENO) < 0) i_fatal("dup2() failed: %m"); if (close(fd) < 0) i_fatal("close() failed: %m"); if (conn->fd != SCRIPT_COMM_FD) { if (dup2(conn->fd, SCRIPT_COMM_FD) < 0) i_fatal("dup2() failed: %m"); if (close(conn->fd) < 0) i_fatal("close() failed: %m"); } /* close all listener sockets */ socket_count = master_service_get_socket_count(master_service); for (i = 0; i < socket_count; i++) { if (close(MASTER_LISTEN_FD_FIRST + i) < 0) i_error("close(listener) failed: %m"); } if (close(MASTER_STATUS_FD) < 0) i_error("close(status) failed: %m"); execvp_const(exec_args[0], exec_args); }
array_foreach(extra_fields, field) { key = t_str_ucase(field->key); value = field->value != NULL ? field->value : "1"; env_put(t_strconcat(key, "=", value, NULL)); }
int sieve_ldap_storage_read_settings (struct sieve_ldap_storage *lstorage, const char *config_path) { struct sieve_storage *storage = &lstorage->storage; const char *str, *error; struct stat st; if ( stat(config_path, &st) < 0 ) { sieve_storage_sys_error(storage, "Failed to read LDAP storage config: " "stat(%s) failed: %m", config_path); return -1; } lstorage->set = default_settings; lstorage->set_mtime = st.st_mtime; if (!settings_read_nosection (config_path, parse_setting, lstorage, &error)) { sieve_storage_set_critical(storage, "Failed to read LDAP storage config `%s': %s", config_path, error); return -1; } if (lstorage->set.base == NULL) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "No search base given", config_path); return -1; } if (lstorage->set.uris == NULL && lstorage->set.hosts == NULL) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "No uris or hosts set", config_path); return -1; } if (*lstorage->set.ldaprc_path != '\0') { str = getenv("LDAPRC"); if (str != NULL && strcmp(str, lstorage->set.ldaprc_path) != 0) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "Multiple different ldaprc_path settings not allowed " "(%s and %s)", config_path, str, lstorage->set.ldaprc_path); return -1; } env_put(t_strconcat("LDAPRC=", lstorage->set.ldaprc_path, NULL)); } if ( ldap_deref_from_str (lstorage->set.deref, &lstorage->set.ldap_deref) < 0 ) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "Invalid deref option `%s'", config_path, lstorage->set.deref);; } if ( ldap_scope_from_str (lstorage->set.scope, &lstorage->set.ldap_scope) < 0 ) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "Invalid scope option `%s'", config_path, lstorage->set.scope);; } #ifdef OPENLDAP_TLS_OPTIONS if ( lstorage->set.tls_require_cert != NULL && ldap_tls_require_cert_from_str(lstorage->set.tls_require_cert, &lstorage->set.ldap_tls_require_cert) < 0) { sieve_storage_set_critical(storage, "Invalid LDAP storage config `%s': " "Invalid tls_require_cert option `%s'", config_path, lstorage->set.tls_require_cert); } #endif return 0; }
static void exec_child (const char *bin_path, const char *const *args, const char *const *envs, int in_fd, int out_fd, int *extra_fds, bool drop_stderr) { ARRAY_TYPE(const_string) exec_args; /* Setup stdin/stdout */ if ( in_fd < 0 ) { in_fd = open("/dev/null", O_RDONLY); if ( in_fd == -1 ) i_fatal("open(/dev/null) failed: %m"); } if ( out_fd < 0 ) { out_fd = open("/dev/null", O_WRONLY); if ( out_fd == -1 ) i_fatal("open(/dev/null) failed: %m"); } if ( dup2(in_fd, STDIN_FILENO) < 0 ) i_fatal("dup2(stdin) failed: %m"); if ( dup2(out_fd, STDOUT_FILENO) < 0 ) i_fatal("dup2(stdout) failed: %m"); if ( close(in_fd) < 0 ) i_error("close(in_fd) failed: %m"); if ( (out_fd != in_fd) && close(out_fd) < 0 ) i_error("close(out_fd) failed: %m"); /* Drop stderr if requested */ if ( drop_stderr ) { int err_fd = open("/dev/null", O_WRONLY); if ( err_fd == -1 ) i_fatal("open(/dev/null) failed: %m"); if ( dup2(err_fd, STDERR_FILENO) < 0 ) i_fatal("dup2(stderr) failed: %m"); if ( close(err_fd) < 0 ) i_error("close(err_fd) failed: %m"); } /* Setup extra fds */ if ( extra_fds != NULL ) { for (; *extra_fds != -1; extra_fds += 2 ) { if ( dup2(extra_fds[0], extra_fds[1]) < 0 ) i_fatal("dup2(extra_fd=%d) failed: %m", extra_fds[1]); if ( close(extra_fds[0]) < 0 ) i_error("close(extra_fd=%d) failed: %m", extra_fds[1]); } } /* Compose argv */ t_array_init(&exec_args, 16); array_append(&exec_args, &bin_path, 1); if ( args != NULL ) { for (; *args != NULL; args++) array_append(&exec_args, args, 1); } (void)array_append_space(&exec_args); /* Setup environment */ env_clean(); if ( envs != NULL ) { for (; *envs != NULL; envs++) env_put(*envs); } /* Execute */ args = array_idx(&exec_args, 0); execvp_const(args[0], args); }
int main(int argc,char *argv[]) //int argc; //char *argv[]; { int dummy; char *proto; int opt; int flagremoteinfo; unsigned long timeout; // struct sockaddr_in *v4; sig_pipeignore(); flagremoteinfo = 1; timeout = 30; while ((opt = getopt(argc,argv,"rRt:")) != opteof) switch(opt) { case 'r': flagremoteinfo = 1; break; case 'R': flagremoteinfo = 0; break; case 't': scan_ulong(subgetoptarg,&timeout); break; } argv += subgetoptind; argc -= subgetoptind; if (argc < 1) die(); if (!env_init()) die(); proto = env_get("PROTO"); if (!proto || str_diff(proto,"TCP")) { if (!env_puts("PROTO=TCP")) die(); dummy = sizeof(salocal); if (getsockname(0,(struct sockaddr *) &salocal, (socklen_t *) &dummy) == -1) die(); mappedtov4(&salocal); switch(salocal.sa.sa_family) { case AF_INET: localport = ntohs(salocal.sa4.sin_port); temp[fmt_ulong(temp,localport)] = 0; if (!env_put("TCPLOCALPORT",temp)) die(); temp[ip4_fmt(temp,(char *) &salocal.sa4.sin_addr)] = 0; if (!env_put("TCPLOCALIP",temp)) die(); switch(dns_ptr(&localname,&salocal.sa4.sin_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&localname,"softdnserror")) die(); case 0: if (!stralloc_0(&localname)) die(); case_lowers(localname.s); if (!env_put("TCPLOCALHOST",localname.s)) die(); break; default: if (!env_unset("TCPLOCALHOST")) die(); } break; #ifdef INET6 case AF_INET6: localport = ntohs(salocal.sa6.sin6_port); temp[fmt_ulong(temp,localport)] = 0; if (!env_put("TCPLOCALPORT",temp)) die(); temp[ip6_fmt(temp,(char *) &salocal.sa6.sin6_addr)] = 0; if (!env_put("TCPLOCALIP",temp)) die(); switch(dns_ptr6(&localname,&salocal.sa6.sin6_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&localname,"softdnserror")) die(); case 0: if (!stralloc_0(&localname)) die(); case_lowers(localname.s); if (!env_put("TCPLOCALHOST",localname.s)) die(); break; default: if (!env_unset("TCPLOCALHOST")) die(); } break; #endif default: die(); } dummy = sizeof(saremote); if (getpeername(0,(struct sockaddr *) &saremote, (socklen_t *) &dummy) == -1) die(); mappedtov4(&saremote); switch(saremote.sa.sa_family) { case AF_INET: remoteport = ntohs(saremote.sa4.sin_port); temp[fmt_ulong(temp,remoteport)] = 0; if (!env_put("TCPREMOTEPORT",temp)) die(); temp[ip4_fmt(temp,(char *)&saremote.sa4.sin_addr)] = 0; if (!env_put("TCPREMOTEIP",temp)) die(); switch(dns_ptr(&remotename,&saremote.sa4.sin_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&remotename,"softdnserror")) die(); case 0: if (!stralloc_0(&remotename)) die(); case_lowers(remotename.s); if (!env_put("TCPREMOTEHOST",remotename.s)) die(); break; default: if (!env_unset("TCPREMOTEHOST")) die(); } break; #ifdef INET6 case AF_INET6: remoteport = ntohs(saremote.sa6.sin6_port); temp[fmt_ulong(temp,remoteport)] = 0; if (!env_put("TCPREMOTEPORT",temp)) die(); temp[ip6_fmt(temp,(char *) &saremote.sa6.sin6_addr)] = 0; if (!env_put("TCPREMOTEIP",temp)) die(); switch(dns_ptr6(&remotename,&saremote.sa6.sin6_addr)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&remotename,"softdnserror")) die(); case 0: if (!stralloc_0(&remotename)) die(); case_lowers(remotename.s); if (!env_put("TCPREMOTEHOST",remotename.s)) die(); break; default: if (!env_unset("TCPREMOTEHOST")) die(); } break; #endif default: die(); } if (!env_unset("TCPREMOTEINFO")) die(); if (flagremoteinfo) { char *rinfo; rinfo = remoteinfo_get(&saremote, &salocal,(int) timeout); if (rinfo) if (!env_put("TCPREMOTEINFO",rinfo)) die(); } } sig_pipedefault(); execvp(*argv,argv); die(); return(0); /* never reached */ }
int main(int argc,char **argv) { int opt; char **qiargv; char **arg; int i; if (chdir(auto_qmail) == -1) { buffer_putsflush(buffer_2,"sendmail: fatal: unable to switch to qmail home directory\n"); _exit(111); } flagh = 0; sender = 0; while ((opt = getopt(argc,argv,"vimte:f:p:o:B:F:EJxb:")) != opteof) switch(opt) { case 'B': break; case 't': flagh = 1; break; case 'f': sender = optarg; break; case 'F': if (!env_put("MAILNAME",optarg)) nomem(); break; case 'p': break; /* could generate a Received line from optarg */ case 'v': break; case 'i': break; /* what an absurd concept */ case 'x': break; /* SVR4 stupidity */ case 'm': break; /* twisted-paper-path blindness, incompetent design */ case 'e': break; /* qmail has only one error mode */ case 'o': switch(optarg[0]) { case 'd': break; /* qmail has only one delivery mode */ case 'e': break; /* see 'e' above */ case 'i': break; /* see 'i' above */ case 'm': break; /* see 'm' above */ } break; case 'E': case 'J': /* Sony NEWS-OS */ while (argv[optind][optpos]) ++optpos; /* skip optional argument */ break; case 'b': switch(optarg[0]) { case 'm': break; case 'p': mailq(); case 's': smtpd(); default: die_usage(); } break; default: die_usage(); } argc -= optind; argv += optind; if (str_equal(optprogname,"mailq")) mailq(); if (str_equal(optprogname,"newaliases")) { buffer_putsflush(buffer_2,"sendmail: fatal: please use fastforward/newaliases instead\n"); _exit(100); } qiargv = (char **) alloc((argc + 10) * sizeof(char *)); if (!qiargv) nomem(); arg = qiargv; *arg++ = "bin/qmail-inject"; *arg++ = (flagh ? "-H" : "-a"); if (sender) { *arg++ = "-f"; *arg++ = sender; do_sender(sender); } *arg++ = "--"; for (i = 0;i < argc;++i) *arg++ = argv[i]; *arg = 0; execv(*qiargv,qiargv); buffer_putsflush(buffer_2,"sendmail: fatal: unable to run qmail-inject\n"); _exit(111); // return(0); /* never reached */ }