summaryrefslogtreecommitdiffstats
path: root/usr.bin/truss/setup.c
diff options
context:
space:
mode:
authorsef <sef@FreeBSD.org>1997-12-06 05:23:12 +0000
committersef <sef@FreeBSD.org>1997-12-06 05:23:12 +0000
commit9e9a114f06c905e161ecc38cc4dc8af9b94ebb1e (patch)
tree700ff37c19e14441400de713fc6c2d0bce947daf /usr.bin/truss/setup.c
parentbfd5e43c20b17aed3a09d69833c3db05c8a68609 (diff)
downloadFreeBSD-src-9e9a114f06c905e161ecc38cc4dc8af9b94ebb1e.zip
FreeBSD-src-9e9a114f06c905e161ecc38cc4dc8af9b94ebb1e.tar.gz
Truss program. Requires procfs.
Diffstat (limited to 'usr.bin/truss/setup.c')
-rw-r--r--usr.bin/truss/setup.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c
new file mode 100644
index 0000000..ca6692b
--- /dev/null
+++ b/usr.bin/truss/setup.c
@@ -0,0 +1,125 @@
+/*
+ * Various setup functions for truss. Not the cleanest-written code,
+ * I'm afraid.
+ */
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/pioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static int evflags = 0;
+
+/*
+ * setup_and_wait() is called to start a process. All it really does
+ * is vfork(), set itself up to stop on exec or exit, and then exec
+ * the given command. At that point, the child process stops, and
+ * the parent can wake up and deal with it.
+ */
+
+int
+setup_and_wait(char *command[]) {
+ struct procfs_status pfs;
+ char buf[32];
+ int fd;
+ int pid;
+ extern char *prog;
+ int flags;
+
+ pid = vfork();
+ if (pid == -1) {
+ err(1, "vfork failed\n");
+ }
+ if (pid == 0) { /* Child */
+ int mask = S_EXEC | S_EXIT;
+ fd = open("/proc/curproc/mem", O_WRONLY);
+ if (fd == -1)
+ err(2, "cannot open /proc/curproc/mem: %s\n", strerror(errno));
+ if (ioctl(fd, PIOCBIS, &mask) == -1)
+ err(3, "PIOCBIS: %s\n", strerror(errno));
+ execvp(command[0], command);
+ mask = ~0;
+ ioctl(fd, PIOCBIC, &mask);
+ err(4, "execvp %s", command[0]);
+ }
+ /* Only in the parent here */
+
+ if (waitpid(pid, NULL, WNOHANG) != 0) {
+ /*
+ * Process exited before it got to us -- meaning the exec failed
+ * miserably -- so we just quietly exit.
+ */
+ exit(1);
+ }
+
+ sprintf(buf, "/proc/%d/mem", pid);
+ if ((fd = open(buf, O_RDWR)) == -1)
+ err(5, "cannot open %s: %s\n", buf, strerror(errno));
+ if (ioctl(fd, PIOCWAIT, &pfs) == -1)
+ err(6, "PIOCWAIT: %s\n", strerror(errno));
+ if (pfs.why == S_EXIT) {
+ int zero = 0;
+ fprintf(stderr, "process exited before exec'ing\n");
+ ioctl(fd, PIOCCONT, &zero);
+ wait(0);
+ exit(7);
+ }
+ close(fd);
+ return pid;
+}
+
+/*
+ * start_tracing picks up where setup_and_wait() dropped off -- namely,
+ * it sets the event mask for the given process id. Called for both
+ * monitoring an existing process and when we create our own.
+ */
+
+int
+start_tracing(int pid, int flags) {
+ int fd;
+ char buf[32];
+ struct procfs_status tmp;
+ sprintf(buf, "/proc/%d/mem", pid);
+ fd = open(buf, O_RDWR);
+ if (fd == -1)
+ err(8, "cannot open %s", buf);
+
+ if (ioctl(fd, PIOCSTATUS, &tmp) == -1) {
+ err(10, "cannot get procfs status struct");
+ }
+ evflags = tmp.events;
+
+ if (ioctl(fd, PIOCBIS, &flags) == -1)
+ err(9, "cannot set procfs event bit mask");
+
+ return fd;
+}
+
+/*
+ * Restore a process back to it's pre-truss state.
+ * Called for SIGINT, SIGTERM, SIGQUIT. This only
+ * applies if truss was told to monitor an already-existing
+ * process.
+ */
+void
+restore_proc(int signo) {
+ extern int Procfd;
+ int i;
+
+ i = ~0;
+ ioctl(Procfd, PIOCBIC, &i);
+ if (evflags)
+ ioctl(Procfd, PIOCBIS, &evflags);
+ exit(0);
+}
OpenPOWER on IntegriCloud