xref: /aosp_15_r20/external/mesa3d/src/freedreno/decode/pager.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2018 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 
16 #include "pager.h"
17 
18 static pid_t pager_pid;
19 
20 static void
pager_death(int n)21 pager_death(int n)
22 {
23    exit(0);
24 }
25 
26 void
pager_open(void)27 pager_open(void)
28 {
29    int fd[2];
30 
31    if (pipe(fd) < 0) {
32       fprintf(stderr, "Failed to create pager pipe: %m\n");
33       exit(-1);
34    }
35 
36    pager_pid = fork();
37    if (pager_pid < 0) {
38       fprintf(stderr, "Failed to fork pager: %m\n");
39       exit(-1);
40    }
41 
42    if (pager_pid == 0) {
43       const char *less_opts;
44 
45       dup2(fd[0], STDIN_FILENO);
46       close(fd[0]);
47       close(fd[1]);
48 
49       less_opts = "FRSMKX";
50       setenv("LESS", less_opts, 1);
51 
52       execlp("less", "less", NULL);
53 
54    } else {
55       /* we want to kill the parent process when pager exits: */
56       signal(SIGCHLD, pager_death);
57       dup2(fd[1], STDOUT_FILENO);
58       close(fd[0]);
59       close(fd[1]);
60    }
61 }
62 
63 int
pager_close(void)64 pager_close(void)
65 {
66    siginfo_t status;
67 
68    close(STDOUT_FILENO);
69 
70    while (true) {
71       memset(&status, 0, sizeof(status));
72       if (waitid(P_PID, pager_pid, &status, WEXITED) < 0) {
73          if (errno == EINTR)
74             continue;
75          return -errno;
76       }
77 
78       return 0;
79    }
80 }
81