From owner-p4-projects@FreeBSD.ORG Wed Apr 14 22:53:00 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3662716A4D0; Wed, 14 Apr 2004 22:53:00 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E7E8616A4CE for ; Wed, 14 Apr 2004 22:52:59 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id E041943D49 for ; Wed, 14 Apr 2004 22:52:59 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i3F5qxGe077330 for ; Wed, 14 Apr 2004 22:52:59 -0700 (PDT) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i3F5qx1W077327 for perforce@freebsd.org; Wed, 14 Apr 2004 22:52:59 -0700 (PDT) (envelope-from marcel@freebsd.org) Date: Wed, 14 Apr 2004 22:52:59 -0700 (PDT) Message-Id: <200404150552.i3F5qx1W077327@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Subject: PERFORCE change 51082 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Apr 2004 05:53:00 -0000 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 ==== //depot/projects/gdb/usr.bin/kgdb/main.c#2 (text+ko) ==== @@ -27,7 +27,121 @@ #include __FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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)); }