* please see the file GPL in the top level source directory.
*/
-#include <stdlib.h>
-
-#include <lib-lib/macros.h>
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
+#include <lib-lib/lib-lib.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,
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)) {
}
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)
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;
+}