X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-sys%2Funix.c;h=3e2c23dcdc3f7f125f820f683a86143695fa8147;hp=372ff0631890a88640bcb76ed6a3345603373881;hb=bb8c11821cc88fef9da474587cc42e0f7554cf28;hpb=d04295aaf918032c1c2fafc94ddf637cf23341e9 diff --git a/lib-sys/unix.c b/lib-sys/unix.c index 372ff06..3e2c23d 100644 --- a/lib-sys/unix.c +++ b/lib-sys/unix.c @@ -8,13 +8,12 @@ * please see the file GPL in the top level source directory. */ -#include - -#include -#include -#include +#include #include "unix.h" +#include "mutt_signal.h" + +#include /* for imap_wait_keepalive EEEEK */ /* Extract the real name from /etc/passwd's GECOS field. * When set, honor the regular expression in rx, @@ -32,7 +31,7 @@ ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx) if (!pw->pw_gecos) return 0; - if (rx) { + if (rx->rx) { regmatch_t pat_match[1]; if (regexec(rx->rx, pw->pw_gecos, 1, pat_match, 0)) { @@ -40,16 +39,16 @@ ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx) } p = pw->pw_gecos + pat_match[0].rm_so; - end = pw->pw_gecos + pat_match[0].rm_so; + end = pw->pw_gecos + pat_match[0].rm_eo; } else { p = pw->pw_gecos; end = m_strchrnul(pw->pw_gecos, ','); } for (;;) { - const char *q = MIN(end, m_strchrnul(p, '&')); + const char *q = m_strchrnul(p, '&'); - len += m_strncpy(dst + len, n - len, p, q - p); + len += m_strncpy(dst + len, n - len, p, MIN(end, q) - p); p = q + 1; if (!p[-1] || p >= end) @@ -61,3 +60,129 @@ ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx) return len; } + +int _mutt_system(const char *cmd, int flags) +{ + int rc = -1; + struct sigaction act; + struct sigaction oldtstp; + struct sigaction oldcont; + sigset_t set; + pid_t pid; + + if (m_strisempty(cmd)) + return 0; + + /* must ignore SIGINT and SIGQUIT */ + mutt_block_signals_system(); + + /* also don't want to be stopped right now */ + if (flags & M_DETACH_PROCESS) { + sigemptyset(&set); + sigaddset(&set, SIGTSTP); + sigprocmask(SIG_BLOCK, &set, NULL); + } else { + act.sa_handler = SIG_DFL; + /* we want to restart the waitpid() below */ +#ifdef SA_RESTART + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaction(SIGTSTP, &act, &oldtstp); + sigaction(SIGCONT, &act, &oldcont); + } + + pid = fork (); + if (pid == 0) { + act.sa_flags = 0; + + if (flags & M_DETACH_PROCESS) { + /* give up controlling terminal */ + setsid(); + + switch (fork()) { + int fd, nb_fds; + + case 0: + nb_fds = getdtablesize(); + for (fd = 0; fd < nb_fds; fd++) { + close(fd); + } + chdir ("/"); + act.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &act, NULL); + break; + + case -1: + _exit(127); + + default: + _exit(0); + } + } + + /* reset signals for the child; not really needed, but... */ + mutt_unblock_signals_system(0); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGTSTP, &act, NULL); + sigaction(SIGCONT, &act, NULL); + + execl("/bin/sh", "sh", "-c", cmd, NULL); + _exit(127); /* execl error */ + } else + if (pid != -1) { + rc = imap_wait_keepalive(pid); + } + + sigaction(SIGCONT, &oldcont, NULL); + sigaction(SIGTSTP, &oldtstp, NULL); + + /* reset SIGINT, SIGQUIT and SIGCHLD */ + mutt_unblock_signals_system(1); + if (flags & M_DETACH_PROCESS) { + sigprocmask (SIG_UNBLOCK, &set, NULL); + } + + return (pid > 0 && WIFEXITED(rc)) ? WEXITSTATUS(rc) : -1; +} + +int getdnsdomainname(char *s, ssize_t n) +{ + char tmp[1024]; + FILE *f; + + if ((f = fopen("/etc/resolv.conf", "r")) == NULL) + return -1; + + while (fgets(tmp, sizeof(tmp), f)) { + const char *p = skipspaces(tmp); + + if (m_strncmp("domain", p, 6) && m_strncmp("search", p, 6)) + continue; + + p += 6; + + while (*p) { + int trailing_dot; + const char *q; + + p = skipspaces(p); + q = m_strnextsp(p); + + trailing_dot = q[-1] == '.'; + if (!trailing_dot || q > p + 1) { + m_strncpy(s, n, p, q - trailing_dot - p); + m_fclose(&f); + return 0; + } + + p = q; + } + } + + m_fclose(&f); + return -1; +}