Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Apr 2004 22:52:59 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 51082 for review
Message-ID:  <200404150552.i3F5qx1W077327@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=51082

Change 51082 by marcel@marcel_nfs on 2004/04/14 22:52:33

	Functional shell, though limited. We basicly fork/exec a gdb(1)
	process with stdin, stdout and stderr redirected to us (where
	stdout and stderr are multiplexed) and pass our stdin to the
	child and forward the childs stdout to ours. To have a different
	prompt (and a vehicle for setting other operation settings at
	startup), we create a command file and use the --command=FILE
	argument to gdb(1). By default we put a "set prompt (kgdb) " in
	there. We can also copy the contents of .kgdbinit into it if we
	want to support .kgdbinit at some time in the future.
	
	Compile with WARNS=4.

Affected files ...

.. //depot/projects/gdb/usr.bin/kgdb/Makefile#2 edit
.. //depot/projects/gdb/usr.bin/kgdb/main.c#2 edit

Differences ...

==== //depot/projects/gdb/usr.bin/kgdb/Makefile#2 (text+ko) ====

@@ -2,5 +2,5 @@
 
 PROG=	kgdb
 SRCS=	main.c
-
+WARNS?=	4
 .include <bsd.prog.mk>

==== //depot/projects/gdb/usr.bin/kgdb/main.c#2 (text+ko) ====

@@ -27,7 +27,121 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int gdb_in, gdb_out;
+pid_t gdb_pid;
+
+char *cmdfile_name;
+int cmdfile_fd;
+
+static void
+mkpipe(int *rd, int *wr)
+{
+	int f[2];
+
+	if (pipe(f) == -1)
+		err(1, "pipe(2)");
+	*rd = f[0];
+	*wr = f[1];
+}
+
+static void
+launch_gdb(void)
+{
+	char *command;
+	int in, out;
+	int f, fmax;
+
+	mkpipe(&in, &gdb_in);
+	mkpipe(&gdb_out, &out);
+
+	gdb_pid = fork();
+	if (gdb_pid == -1)
+		err(1, "fork(2)");
+	if (gdb_pid == 0) {
+		if (asprintf(&command, "--command=%s", cmdfile_name) < 0)
+			err(1, "asprintf(3)");
+		/* Dup stderr last so that err(3) work as long as possible. */
+		if (dup2(in, 0) == -1 || dup2(out, 1) == -1 ||
+		    dup2(out, 2) == -1)
+			err(1, "dup2(2)");
+		fmax = getdtablesize();
+		for (f = 3; f < fmax; f++)
+			close(f);
+		execlp("gdb", "gdb", command, NULL);
+		_exit(1);
+	}
+
+	close(in);
+	close(out);
+}
+
+static void
+mkcmdfile(void)
+{
+	static const char set_prompt[] = "set prompt (kgdb) ";
+
+	cmdfile_name = strdup("/tmp/kgdb.XXXXXXXX");
+	if (cmdfile_name == NULL)
+		err(1, "strdup(3)");
+	cmdfile_fd = mkstemp(cmdfile_name);
+	if (cmdfile_fd == -1)
+		err(1, "mkstemp(3)");
+	if (write(cmdfile_fd, set_prompt, sizeof(set_prompt) - 1) < 0)
+		err(1, "write(2)");
+}
+
 int
-main(int argc, char *argv[])
+main(int argc __unused, char *argv[] __unused)
 {
+	char buf[128];
+	fd_set rfds, wfds, xfds;
+	ssize_t sz;
+	int status;
+
+	mkcmdfile();
+	launch_gdb();
+
+	while (1) {
+		FD_ZERO(&rfds);
+		FD_ZERO(&wfds);
+		FD_ZERO(&xfds);
+		FD_SET(0, &rfds);
+		FD_SET(gdb_out, &rfds);
+		FD_SET(gdb_in, &xfds);
+		FD_SET(gdb_out, &xfds);
+		if (select(gdb_out + 1, &rfds, &wfds, &xfds, NULL) == -1) {
+			if (errno != EINTR)
+				err(1, "select(2)");
+			continue;
+		}
+		if (FD_ISSET(gdb_in, &xfds) || FD_ISSET(gdb_out, &xfds))
+			break;
+		if (FD_ISSET(0, &rfds)) {
+			sz = read(0, buf, sizeof(buf));
+			if (sz > 0)
+				sz = write(gdb_in, buf, sz);
+		}
+		if (FD_ISSET(gdb_out, &rfds)) {
+			sz = read(gdb_out, buf, sizeof(buf));
+			if (sz > 0)
+				sz = write(1, buf, sz);
+		}
+	}
+
+	close(gdb_in);
+	close(gdb_out);
+
+	wait4(gdb_pid, &status, 0, NULL);
+	return (WEXITSTATUS(status));
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404150552.i3F5qx1W077327>