reimplement getdnsdomainname
[apps/madmutt.git] / lib-sys / unix.c
index 372ff06..4f189c1 100644 (file)
@@ -8,13 +8,21 @@
  * please see the file GPL in the top level source directory.
  */
 
  * please see the file GPL in the top level source directory.
  */
 
+#include <errno.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #include <lib-lib/macros.h>
 #include <lib-lib/mem.h>
 #include <lib-lib/str.h>
 
 #include <lib-lib/macros.h>
 #include <lib-lib/mem.h>
 #include <lib-lib/str.h>
+#include <lib-lib/file.h>
 
 #include "unix.h"
 
 #include "unix.h"
+#include "mutt_signal.h"
+
+#include <imap/imap.h> /* for imap_wait_keepalive EEEEK */
 
 /* Extract the real name from /etc/passwd's GECOS field.
  * When set, honor the regular expression in rx,
 
 /* Extract the real name from /etc/passwd's GECOS field.
  * When set, honor the regular expression in rx,
@@ -61,3 +69,129 @@ ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx)
 
     return len;
 }
 
     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, p - q - trailing_dot);
+                safe_fclose(&f);
+                return 0;
+            }
+
+            p = q;
+        }
+    }
+
+    safe_fclose (&f);
+    return -1;
+}