Diff between 0de52f95ec9b9512165174c7f4b2c5fe84c33dc0 and c0cbadfc2bec5e03b59d43011209b6dad8c6c685

Changed Files

File Additions Deletions Status
Makefile.tools +1 -0 modified
monitor/control.c +5 -0 modified
monitor/packet.c +2 -1 modified
monitor/pager.c +145 -0 added
monitor/pager.h +29 -0 added

Full Patch

diff --git a/Makefile.tools b/Makefile.tools
index f7c85ef..ebda7c5 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -47,6 +47,7 @@ tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c src/eir.c
 tools_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
 
 monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
+					monitor/pager.h monitor/pager.c \
 					monitor/mainloop.h monitor/mainloop.c \
 					monitor/hcidump.h monitor/hcidump.c \
 					monitor/btsnoop.h monitor/btsnoop.c \
diff --git a/monitor/control.c b/monitor/control.c
index bbcdcbb..93189fd 100644
--- a/monitor/control.c
+++ b/monitor/control.c
@@ -40,6 +40,7 @@
 #include <bluetooth/mgmt.h>
 
 #include "mainloop.h"
+#include "pager.h"
 #include "packet.h"
 #include "btsnoop.h"
 #include "control.h"
@@ -778,6 +779,8 @@ void control_reader(const char *path)
 	if (btsnoop_open(path) < 0)
 		return;
 
+	pager_open();
+
 	while (1) {
 		if (btsnoop_read(&tv, &index, &opcode, buf, &pktlen) < 0)
 			break;
@@ -785,6 +788,8 @@ void control_reader(const char *path)
 		packet_monitor(&tv, index, opcode, buf, pktlen);
 	}
 
+	pager_close();
+
 	btsnoop_close();
 }
 
diff --git a/monitor/packet.c b/monitor/packet.c
index 0c4d360..2be1635 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -40,6 +40,7 @@
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
 
+#include "pager.h"
 #include "bt.h"
 #include "control.h"
 #include "packet.h"
@@ -62,7 +63,7 @@ static bool use_color(void)
 	static int cached_use_color = -1;
 
 	if (__builtin_expect(!!(cached_use_color < 0), 0))
-		cached_use_color = isatty(STDOUT_FILENO) > 0;
+		cached_use_color = isatty(STDOUT_FILENO) > 0 || pager_have();
 
 	return cached_use_color;
 }
diff --git a/monitor/pager.c b/monitor/pager.c
new file mode 100644
index 0000000..f24eca7
--- /dev/null
+++ b/monitor/pager.c
@@ -0,0 +1,145 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+
+#include "pager.h"
+
+static pid_t pager_pid = 0;
+
+static void close_pipe(int p[])
+{
+	if (p[0] >= 0)
+		close(p[0]);
+	if (p[1] >= 0)
+		close(p[1]);
+}
+
+static void wait_for_terminate(pid_t pid)
+{
+	siginfo_t dummy;
+
+	for (;;) {
+		memset(&dummy, 0, sizeof(dummy));
+
+		if (waitid(P_PID, pid, &dummy, WEXITED) < 0) {
+			if (errno == EINTR)
+				continue;
+			return;
+		}
+
+		return;
+	}
+}
+
+void pager_open(void)
+{
+	const char *pager;
+	pid_t parent_pid;
+	int fd[2];
+
+	if (pager_pid > 0)
+		return;
+
+	pager = getenv("PAGER");
+	if (pager) {
+		if (!*pager || strcmp(pager, "cat") == 0)
+			return;
+	}
+
+	if (!(isatty(STDOUT_FILENO) > 0))
+		return;
+
+	if (pipe(fd) < 0) {
+		perror("Failed to create pager pipe");
+		return;
+	}
+
+	parent_pid = getpid();
+
+	pager_pid = fork();
+	if (pager_pid < 0) {
+		perror("Failed to fork pager");
+		close_pipe(fd);
+		return;
+	}
+
+	if (pager_pid == 0) {
+		dup2(fd[0], STDIN_FILENO);
+		close_pipe(fd);
+
+		setenv("LESS", "FRSX", 0);
+
+		if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+			_exit(EXIT_FAILURE);
+
+		if (getppid() != parent_pid)
+			_exit(EXIT_SUCCESS);
+
+		if (pager) {
+			execlp(pager, pager, NULL);
+			execl("/bin/sh", "sh", "-c", pager, NULL);
+		}
+
+		execlp("pager", "pager", NULL);
+		execlp("less", "less", NULL);
+		execlp("more", "more", NULL);
+
+		_exit(EXIT_FAILURE);
+	}
+
+	if (dup2(fd[1], STDOUT_FILENO) < 0) {
+		perror("Failed to duplicate pager pipe");
+		return;
+	}
+
+	close_pipe(fd);
+}
+
+void pager_close(void)
+{
+	if (pager_pid <= 0)
+		return;
+
+	fclose(stdout);
+	kill(pager_pid, SIGCONT);
+	wait_for_terminate(pager_pid);
+	pager_pid = 0;
+}
+
+bool pager_have(void)
+{
+	return pager_pid > 0;
+}
diff --git a/monitor/pager.h b/monitor/pager.h
new file mode 100644
index 0000000..041eb74
--- /dev/null
+++ b/monitor/pager.h
@@ -0,0 +1,29 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2011-2012  Intel Corporation
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdbool.h>
+
+void pager_open(void);
+void pager_close(void);
+bool pager_have(void);