| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011-2014 Intel Corporation
- * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #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 <termios.h>
- #include "display.h"
- static pid_t pager_pid = 0;
- int default_pager_num_columns = FALLBACK_TERMINAL_WIDTH;
- enum monitor_color setting_monitor_color = COLOR_AUTO;
- void set_monitor_color(enum monitor_color color)
- {
- setting_monitor_color = color;
- }
- bool use_color(void)
- {
- static int cached_use_color = -1;
- if (setting_monitor_color == COLOR_ALWAYS)
- cached_use_color = 1;
- else if (setting_monitor_color == COLOR_NEVER)
- cached_use_color = 0;
- else if (__builtin_expect(!!(cached_use_color < 0), 0))
- cached_use_color = isatty(STDOUT_FILENO) > 0 || pager_pid > 0;
- return cached_use_color;
- }
- void set_default_pager_num_columns(int num_columns)
- {
- default_pager_num_columns = num_columns;
- }
- 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 ||
- ws.ws_col == 0)
- cached_num_columns = default_pager_num_columns;
- else
- 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;
- }
|