static void _backtrace(int pid, char *btarg) { char *proc, *spid, *gdbcmd; int fd[3], p[2]; int status, cmdfd; gdbcmd = estrdup("/tmp/gdbcmd.XXXXXX"); if(pipe(p) < 0) goto done; closeexec(p[0]); cmdfd = mkstemp(gdbcmd); if(cmdfd < 0) goto done; fprint(cmdfd, "bt %s\n", btarg); fprint(cmdfd, "detach\n"); close(cmdfd); fd[0] = open("/dev/null", O_RDONLY); fd[1] = p[1]; fd[2] = dup(2); proc = sxprint("/proc/%d/" PROGTXT, pid); spid = sxprint("%d", pid); if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", gdbcmd, proc, spid, nil) < 0) { unlink(gdbcmd); goto done; } Biobuf bp; char *s; Binit(&bp, p[0], OREAD); while((s = Brdstr(&bp, '\n', 1))) { Dprint(DStack, "%s\n", s); free(s); } unlink(gdbcmd); done: free(gdbcmd); kill(pid, SIGKILL); waitpid(pid, &status, 0); }
int spawn3(int fd[3], const char *file, char *argv[]) { /* Some ideas from Russ Cox's libthread port. */ int p[2]; int pid; if(pipe(p) < 0) return -1; closeexec(p[1]); switch(pid = doublefork()) { case 0: dup2(fd[0], 0); dup2(fd[1], 1); dup2(fd[2], 2); execvp(file, argv); write(p[1], &errno, sizeof errno); exit(1); break; default: close(p[1]); if(read(p[0], &errno, sizeof errno) == sizeof errno) pid = -1; close(p[0]); break; case -1: /* can't happen */ break; } close(fd[0]); /* These could fail if any of these was also a previous fd. */ close(fd[1]); close(fd[2]); return pid; }
int main(int argc, char *argv[]) { IxpMsg m; char **oargv; char *wmiirc, *s; int i; quotefmtinstall(); fmtinstall('r', errfmt); fmtinstall('a', afmt); fmtinstall('C', Cfmt); extern int fmtevent(Fmt*); fmtinstall('E', fmtevent); wmiirc = "wmiirc"; oargv = argv; ARGBEGIN{ case 'a': address = EARGF(usage()); break; case 'r': wmiirc = EARGF(usage()); break; case 'v': print("%s", version); exit(0); case 'D': s = EARGF(usage()); m = ixp_message(s, strlen(s), 0); msg_debug(&m); break; default: usage(); break; }ARGEND; if(argc) usage(); setlocale(LC_CTYPE, ""); starting = true; initdisplay(); traperrors(true); selectinput(&scr.root, EnterWindowMask | SubstructureRedirectMask); if(traperrors(false)) fatal("another window manager is already running"); passwd = getpwuid(getuid()); user = estrdup(passwd->pw_name); init_environment(); fmtinstall('F', Ffmt); ixp_printfcall = printfcall; sock = ixp_announce(address); if(sock < 0) fatal("Can't create socket '%s': %r", address); closeexec(ConnectionNumber(display)); closeexec(sock); if(wmiirc[0]) spawn_command(wmiirc); init_traps(); init_cursors(); init_lock_keys(); ewmh_init(); xext_init(); srv.preselect = check_preselect; ixp_listen(&srv, sock, &p9srv, serve_9pcon, nil); ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, closedisplay); def.border = 1; def.colmode = Colstack; def.font = loadfont(FONT); def.incmode = ISqueeze; def.mod = Mod1Mask; strcpy(def.grabmod, "Mod1"); loadcolor(&def.focuscolor, FOCUSCOLORS); loadcolor(&def.normcolor, NORMCOLORS); disp.sel = pointerscreen(); init_screens(); root_init(); disp.focus = nil; setfocus(screen->barwin, RevertToParent); view_select("1"); scan_wins(); starting = false; view_update_all(); ewmh_updateviews(); event("FocusTag %s\n", selview->name); i = ixp_serverloop(&srv); if(i) fprint(2, "%s: error: %r\n", argv0); else event("Quit"); cleanup(); if(exitsignal) raise(exitsignal); if(execstr) { char *toks[32]; int n; n = unquote(strdup(execstr), toks, nelem(toks)-1); toks[n] = nil; execvp(toks[0], toks); fprint(2, "%s: failed to exec %q: %r\n", argv0, execstr); execvp(argv0, oargv); fatal("failed to exec myself"); } return i; }