static void exec_cmd(int fdin, int fdout, const char** argv, const str* env, const struct passwd* pw) { selfpipe_close(); dup2(fdin, 0); dup2(fdout, 1); dup2(fdout, 2); close(fdin); close(fdout); if (!testmode) { if (initgroups(pw->pw_name, pw->pw_gid) != 0) die1sys(111, "Could not initgroups"); if (setgid(pw->pw_gid) != 0) die1sys(111, "Could not setgid"); if (setuid(pw->pw_uid) != 0) die1sys(111, "Could not setuid"); } if (chdir(pw->pw_dir) != 0) die1sys(111, "Could not change directory"); if (env) if ((environ = envstr_make_array(env)) == 0) die_oom(111); execv(argv[0], (char**)argv); die3sys(111, "Could not execute '", argv[0], "'"); exit(111); }
int fork_inject(const char* sender) { int p[2]; debug6(1, "forking ", opt_qmail_inject, " -f '' -a -- '", sender, "' ", extra_rcpt); if(opt_nosend) { inject_pid = 0; return dup(1); } if (pipe(p) != 0) die1sys(111, "Could not create pipe"); inject_pid = fork(); switch(inject_pid) { case -1: die1sys(111, "Could not fork"); case 0: wrap_chdir(qmail_home); close(p[1]); close(0); dup2(p[0], 0); close(p[0]); execl(opt_qmail_inject, opt_qmail_inject, "-f", "", "-a", "--", sender, extra_rcpt, NULL); die1sys(111, "Exec of qmail-inject failed"); default: close(p[0]); return p[1]; } }
int main(int argc, char* argv[]) { struct connection conn; iopoll_fd fds[2]; int selfpipe; int i; msg_debug_init(); testmode = getenv("TESTMODE") != 0; if ((shell_argv = malloc((argc + 3) * sizeof *argv)) == 0) die_oom(111); for (i = 1; i < argc; ++i) shell_argv[i-1] = argv[i]; for (; i < argc + 4; ++i) shell_argv[i-1] = 0; shell_argc = argc - 1; if ((path = getenv("PATH")) == 0) die1(111, "No PATH is set"); if ((devnull = open("/dev/null", O_RDWR)) == -1) die1sys(111, "Could not open \"/dev/null\""); if (!nonblock_on(0)) die1sys(111, "Could not set non-blocking status"); if ((selfpipe = selfpipe_init()) == -1) die1sys(111, "Could not create self-pipe"); init_slots(); connection_init(&conn, 0, 0); fds[0].fd = 0; fds[0].events = IOPOLL_READ; fds[1].fd = selfpipe; fds[1].events = IOPOLL_READ; for (;;) { if (iopoll_restart(fds, 2, -1) == -1) die1sys(111, "Poll failed"); if (fds[0].revents) if (connection_read(&conn, handle_packet) <= 0) break; if (fds[1].revents) { read(selfpipe, &i, 1); handle_child(WNOHANG); } } msg1("Waiting for remaining slots to complete"); while (slots_used > 0) handle_child(0); return 0; }
int main(int argc, char* argv[]) { const char* dir; int fd; struct stat s; char fdstr[32]; if (argc < 2) die1(1, "usage: relay-ctrl-chdir program [arguments]\n"); if ((dir = getenv("RELAY_CTRL_DIR")) == 0) die1(111, "$RELAY_CTRL_DIR is not set."); else if ((fd = open(dir, O_RDONLY)) == -1) die3sys(111, "Could not open dir '", dir, "'"); else if (fstat(fd, &s) == -1) die1sys(111, "Could not stat opened file"); else if (!S_ISDIR(s.st_mode)) die3(111, "'", dir, "' is not a directory"); else { fd = move_high(fd); utoa2(fd, fdstr); if (setenv("RELAY_CTRL_DIR_FD", fdstr, 1) == -1) die1(111, "Could not set environment variable"); } execvp(argv[1], argv+1); die1(111, "execution of program failed!\n"); return 111; argc = 0; }
void touch_run_file(void) { obuf out; if (!obuf_open(&out, opt_run_file, OBUF_CREATE|OBUF_TRUNCATE, 0666, 0) || !obuf_putu(&out, now) || !obuf_close(&out)) die1sys(111, "Could not update run file"); }
void minifstat(int fd, struct ministat* s) { struct stat st; if (fstat(fd, &st) != 0) die1sys(111, "Could not fstat"); else copystat(s, &st); }
void send_bounce(const char* sender, const char* filename, const char* remotes, const char* locals, time_t age) { int fd = fork_inject(sender); make_bounce_body(fd, sender, filename, remotes, locals, age); if (close(fd) != 0) die1sys(111, "Writing to qmail-inject failed"); wait_inject(); }
int main(int argc, char* argv[]) { if (argc < 5) usage("Too few parameters"); if (argc > 7) usage("Too many parameters"); logacct = getpwnam(argv[1]); maindir = argv[2]; logdir = argv[3]; if (maindir[0] != '/' || logdir[0] != '/') die1(1, "Directory names must start with /."); cvmpath = argv[4]; if (argc > 5) { ip = argv[5]; if (argc > 6) dochroot = argv[6]; } if (!logacct) die1(1, "Unknown logacct user name"); umask(0); if (mkdir(maindir, 0755) == -1) die1sys(1, "Error creating main directory"); if (chmod(maindir, 01755) == -1) die1sys(1, "Error setting permissions on main directory"); if (mkdir(logdir, 0700) == -1) die1sys(1, "Error creating log directory"); if (chown(logdir, logacct->pw_uid, logacct->pw_gid) == -1) die1sys(1, "Error setting owner on log directory"); if (chdir(maindir) == -1) die1sys(1, "Error changing to main directory"); if (mkdir("log", 0755) == -1) die1sys(1, "Error creating log service directory"); if (mkdir("env", 0755) == -1) die1sys(1, "Error creating env directory"); start_file("run", 0755); obuf_put5s(&conf_out, "#!/bin/sh\n" "exec 2>&1\n" "umask 022\n" "exec \\\n" "tcpserver -DRHv -llocalhost ", ip, " 21 \\\n" "envdir ", maindir, "/env \\\n"); obuf_put7s(&conf_out, "softlimit -m 2000000 \\\n", conf_bin, "/twoftpd-auth \\\n", cvmpath, " \\\n", conf_bin, "/twoftpd-xfer"); end_file(); make_file("log/run", 0755, "#!/bin/sh\n" "exec \\\n" "setuidgid ", logacct->pw_name, " \\\n" "multilog t ", logdir, 0, 0, 0); if (dochroot) make_fileu("env/CHROOT", 1); return 0; }
static void load_keys(const char* server) { str path = {0,0,0}; wrap_str(str_copy4s(&path, keydir, "/servers/", server, ".")); if (!keylist_load_multi(&server_publics, path.s, 0) && !keylist_load_multi(&server_publics, "server.", 0)) die1sys(1, "Could not load server keys"); if (!keylist_load_multi(&client_secrets, "", 0)) { wrap_str(str_copy2s(&path, keydir, "/")); if (!keylist_load_multi(&client_secrets, path.s, 0)) die1sys(1, "Could not load sender keys"); } if (!keylist_exchange_all(&shared_secrets, &server_publics, &client_secrets)) die1(1, "No server keys matched any sender keys"); str_free(&path); }
void wait_inject(void) { int status; if(inject_pid) { if(waitpid(inject_pid, &status, WUNTRACED) == -1) die1sys(111, "Could not wait for qmail-inject to exit"); if(!WIFEXITED(status)) die1(111, "qmail-inject crashed"); if(WEXITSTATUS(status)) die1(111, "qmail-inject exited with an error"); } }
void scan_queue(void) { DIR* dir; direntry* entry; wrap_chdir(qmail_home); wrap_chdir("queue"); if((dir = opendir("info")) == 0) die1sys(111, "Can't open queue directory"); while((entry = readdir(dir)) != 0) if(entry->d_name[0] != '.') scan_dir(entry->d_name); closedir(dir); }
static void prep_sender(void) { static char hostname[256]; char* p; if ((sender = getenv("SENDER")) == 0) { if (gethostname(hostname, sizeof hostname) != 0) die1sys(1, "gethostname failed"); hostname[sizeof hostname - 1] = 0; if ((p = strchr(hostname, '.')) != 0) *p = 0; sender = hostname; } }
static int poll_both(void) { struct timeval timestamp; int ready; /* Sanity check to make sure no data is lost */ if (inbuf.io.buflen > inbuf.io.bufstart) { stdin_ready = IOPOLL_READ; sock_ready = 0; return 1; } /* Calculate remaining timeout */ gettimeofday(×tamp, 0); if (poll_timestamp.tv_sec != 0) { poll_timeout -= (timestamp.tv_sec - poll_timestamp.tv_sec) * 1000 + (timestamp.tv_usec - poll_timestamp.tv_usec) / 1000; if (poll_timeout < 0) poll_timeout = 0; } poll_timestamp = timestamp; io[0].fd = stdin_eof ? -1 : 0; io[0].events = stdin_eof ? 0 : IOPOLL_READ; io[1].fd = sock; io[1].events = IOPOLL_READ; switch (ready = iopoll(io, 2, poll_timeout)) { case -1: if (errno == EAGAIN || errno == EINTR) exitasap = 1; else die1sys(1, "Poll failed!"); return 0; case 0: poll_timeout = 0; return 0; default: if (stdin_error) { stdin_eof = 1; if (exitoneof || seq_next == seq_send) exitasap = 1; io[0].revents = 0; } return ready; } }
void scan_dir(const char* dirnum) { DIR* dir; direntry* entry; char buf1[100]; strcpy(buf1, "info/"); strcpy(buf1+5, dirnum); if((dir = opendir(buf1)) == 0) die1sys(111, "Can't open queue directory"); while((entry = readdir(dir)) != 0) { if(entry->d_name[0] != '.') { char filename[100]; strcpy(filename, dirnum); strcat(filename, "/"); strcat(filename, entry->d_name); scan_info(filename); } } closedir(dir); }
int cli_main(int argc, char* argv[]) { const char* server_name = 0; const char* env; msg_debug_init(); encr_start(); prep_sender(); service = argv[0]; if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '+') { server_name = argv[1]; ++argv; --argc; } if (argc > 1) load_patterns(argv + 1); if (server_name == 0 && (server_name = getenv("SERVER")) == 0) die1(1, "Server address not named on command line nor in $SERVER"); if (!resolve_ipv4name(server_name, &ip)) die3(1, "Could not resolve '", server_name, "'"); brandom_init(); if ((env = getenv("KEYDIR")) != 0) keydir = env; load_keys(server_name); if ((env = getenv("PORT")) != 0) port = strtoul(env, 0, 10); if (port == 0) port = 11014; if ((sock = socket_udp()) == -1) die1sys(1, "Could not create UDP socket"); if (!socket_connect4(sock, &ip, port)) die1sys(1, "Could not bind socket"); if (!str_ready(&packet, 65535) || !str_ready(&rpacket, 4+4+8+256*5)) die1(1, "Out of memory"); getenvu("ACK_TIMEOUT", &ack_timeout); getenvu("CID_TIMEOUT", &cid_timeout); getenvu("RETRANSMITS", &retransmits); getenvu("READWAIT", &readwait); getenvu("STARTLINES", &startlines); if (getenv("EXITONEOF") != 0) exitoneof = 1; if (getenv("NOFILES") == 0 && getenv("NOFILE") == 0) buffer = buffer_file_init(); else buffer = buffer_nofile_init(); sig_all_catch(sigfn); exitasap = 0; mainloop(); return 0; }