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>