changeset 3864:6124ca416a6c HEAD

Added gdbhelper binary.
author Timo Sirainen <tss@iki.fi>
date Sat, 14 Jan 2006 14:46:33 +0200
parents 55df57c028d4
children 749d42902341
files dovecot-example.conf src/util/Makefile.am src/util/gdbhelper.c
diffstat 3 files changed, 79 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Fri Jan 13 22:25:57 2006 +0200
+++ b/dovecot-example.conf	Sat Jan 14 14:46:33 2006 +0200
@@ -413,10 +413,17 @@
   # Login executable location.
   #login_executable = /usr/libexec/dovecot/imap-login
 
-  # IMAP executable location
+  # IMAP executable location. Changing this allows you to execute other
+  # binaries before the imap process is executed.
+  #
+  # This would write rawlogs into ~/dovecot.rawlog/ directory:
+  #   mail_executable = /usr/libexec/dovecot/rawlog /usr/libexec/dovecot/imap
+  #
+  # This would attach gdb into the imap process and write backtraces into
+  # /tmp/gdbhelper.* files:
+  #   mail_executable = /usr/libexec/dovecot/gdbhelper /usr/libexec/dovecot/imap
+  #
   #mail_executable = /usr/libexec/dovecot/imap
-  # This would write rawlogs into ~/dovecot.rawlog/ directory:
-  #mail_executable = /usr/libexec/dovecot/rawlog /usr/libexec/dovecot/imap
 
   # Maximum IMAP command line length in bytes. Some clients generate very long
   # command lines with huge mailboxes, so you may need to raise this if you get
--- a/src/util/Makefile.am	Fri Jan 13 22:25:57 2006 +0200
+++ b/src/util/Makefile.am	Sat Jan 14 14:46:33 2006 +0200
@@ -1,6 +1,6 @@
 pkglibexecdir = $(libexecdir)/dovecot
 
-pkglibexec_PROGRAMS = rawlog
+pkglibexec_PROGRAMS = rawlog gdbhelper
 sbin_PROGRAMS = dovecotpw
 
 AM_CPPFLAGS = \
@@ -13,6 +13,12 @@
 rawlog_SOURCES = \
 	rawlog.c
 
+gdbhelper_LDADD = \
+	../lib/liblib.a
+
+gdbhelper_SOURCES = \
+	gdbhelper.c
+
 dovecotpw_LDADD = \
 	../auth/libpassword.a \
 	../lib-ntlm/libntlm.a \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/gdbhelper.c	Sat Jan 14 14:46:33 2006 +0200
@@ -0,0 +1,62 @@
+/* Copyright (C) 2006 Timo Sirainen */
+
+#include "lib.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/wait.h>
+
+int main(int argc, char *argv[])
+{
+	pid_t pid = fork();
+	const char *path, *cmd;
+	int fd_in[2], fd_log, status;
+
+	if (argc < 2)
+		i_fatal("Usage: gdbhelper <program> [<args>]");
+
+	switch (pid) {
+	case 1:
+		i_fatal("fork() failed: %m");
+	case 0:
+		/* child */
+		(void)execvp(argv[1], argv+1);
+		i_fatal("execvp(%s) failed: %m", argv[1]);
+	default:
+		path = t_strdup_printf("/tmp/gdbhelper.%s.%s",
+				       dec2str(time(NULL)), dec2str(pid));
+		fd_log = open(path, O_CREAT | O_WRONLY, 0600);
+		if (fd_log < 0)
+			i_fatal("open(%s) failed: %m", path);
+
+		if (pipe(fd_in) < 0)
+			i_fatal("pipe() failed: %m");
+		cmd = "handle SIGPIPE nostop\n"
+			"handle SIGALRM nostop\n"
+			"cont\n"
+			"where\n"
+			"quit\n";
+		if (write(fd_in[1], cmd, strlen(cmd)) < 0)
+			i_fatal("write() failed: %m");
+
+		if (dup2(fd_in[0], 0) < 0 ||
+		    dup2(fd_log, 1) < 0 ||
+		    dup2(fd_log, 2) < 0)
+			i_fatal("dup2() failed: %m");
+
+		cmd = t_strdup_printf("gdb %s %s", argv[1], dec2str(pid));
+		if (system(cmd) < 0)
+			i_fatal("system() failed: %m");
+
+		if (wait(&status) < 0)
+			i_fatal("wait() failed: %m");
+		if (status == 0) {
+			if (unlink(path) < 0 && errno != ENOENT)
+				i_error("unlink(%s) failed: %m", path);
+		}
+	}
+	return 0;
+}