diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2012-11-04 10:16:30 +0100 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2012-11-04 10:16:30 +0100 |
commit | 9cb91579643c106f08b1e862fcd6ffdb56bc4041 (patch) | |
tree | acc1662e2a96c12d9e91bb3a206ab9b86d894713 /monitor/display.c | |
parent | 14883d64dde384fc0d671d33c058fbdb3aa8bb11 (diff) | |
download | bluez-9cb91579643c106f08b1e862fcd6ffdb56bc4041.tar.gz |
monitor: Use global file for display settings
Diffstat (limited to 'monitor/display.c')
-rw-r--r-- | monitor/display.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/monitor/display.c b/monitor/display.c new file mode 100644 index 000000000..7b6fc98ef --- /dev/null +++ b/monitor/display.c @@ -0,0 +1,170 @@ +/* + * + * 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 <sys/ioctl.h> + +#include "display.h" + +static pid_t pager_pid = 0; + +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 || pager_pid > 0; + + return cached_use_color; +} + +int num_columns(void) +{ + static int cached_num_columns = -1; + + if (__builtin_expect(!!(cached_num_columns < 0), 0)) { + struct winsize ws; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) + return -1; + + if (ws.ws_col > 0) + cached_num_columns = ws.ws_col; + } + + return cached_num_columns; +} + +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 open_pager(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; + + num_columns(); + + 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 close_pager(void) +{ + if (pager_pid <= 0) + return; + + fclose(stdout); + kill(pager_pid, SIGCONT); + wait_for_terminate(pager_pid); + pager_pid = 0; +} |