Mercurial > projects > pwm
annotate pager.c @ 17:a08ef0674d8e
Page long output in interactive mode
author | Guido Berhoerster <guido+pwm@berhoerster.name> |
---|---|
date | Sat, 12 Aug 2017 10:41:52 +0200 |
parents | |
children | 1e39a251cbe9 |
rev | line source |
---|---|
17
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
1 /* |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
2 * Copyright (C) 2017 Guido Berhoerster <guido+pwm@berhoerster.name> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
3 * |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
4 * Permission is hereby granted, free of charge, to any person obtaining |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
5 * a copy of this software and associated documentation files (the |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
6 * "Software"), to deal in the Software without restriction, including |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
7 * without limitation the rights to use, copy, modify, merge, publish, |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
8 * distribute, sublicense, and/or sell copies of the Software, and to |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
9 * permit persons to whom the Software is furnished to do so, subject to |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
10 * the following conditions: |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
11 * |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
12 * The above copyright notice and this permission notice shall be included |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
13 * in all copies or substantial portions of the Software. |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
14 * |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
22 */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
23 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
24 #include "compat.h" |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
25 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
26 #ifdef HAVE_ERR_H |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
27 #include <err.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
28 #endif /* HAVE_ERR_H */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
29 #include <errno.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
30 #include <fcntl.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
31 #include <limits.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
32 #include <signal.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
33 #include <stdio.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
34 #include <string.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
35 #include <sys/ioctl.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
36 #ifdef HAVE_SYS_QUEUE_H |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
37 #include <sys/queue.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
38 #endif /* HAVE_SYS_QUEUE_H */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
39 #include <sys/stat.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
40 #include <sys/types.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
41 #include <termios.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
42 #include <unistd.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
43 #include <wchar.h> |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
44 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
45 #include "pwm.h" |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
46 #include "pager.h" |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
47 #include "util.h" |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
48 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
49 #ifndef TCSASOFT |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
50 #define TCSASOFT 0 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
51 #endif /* !TCSASOFT */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
52 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
53 #ifndef _NSIG |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
54 #ifdef NSIG |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
55 #define _NSIG NSIG |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
56 #else /* NSIG */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
57 #define _NSIG 128 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
58 #endif /* NSIG */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
59 #endif /* !_NSIG */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
60 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
61 #ifndef _PATH_TTY |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
62 #define _PATH_TTY "/dev/tty" |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
63 #endif |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
64 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
65 struct pager { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
66 TAILQ_HEAD(lines_head, lines_entry) lines_head; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
67 FILE *fp; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
68 size_t buf_size; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
69 char *buf; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
70 }; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
71 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
72 struct lines_entry { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
73 TAILQ_ENTRY(lines_entry) entry; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
74 char *line; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
75 }; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
76 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
77 static volatile sig_atomic_t signals[_NSIG]; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
78 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
79 static void |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
80 sig_handler(int signo) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
81 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
82 signals[signo] = 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
83 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
84 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
85 static int |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
86 getch_prompt(const char *prompt) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
87 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
88 int retval = -1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
89 int signo; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
90 int fd; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
91 struct termios saved_term; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
92 struct termios term; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
93 struct sigaction sa; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
94 struct sigaction saved_sa_hup; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
95 struct sigaction saved_sa_int; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
96 struct sigaction saved_sa_quit; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
97 struct sigaction saved_sa_pipe; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
98 struct sigaction saved_sa_alrm; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
99 struct sigaction saved_sa_term; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
100 struct sigaction saved_sa_tstp; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
101 struct sigaction saved_sa_ttin; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
102 struct sigaction saved_sa_ttou; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
103 char c; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
104 int need_restart = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
105 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
106 printf("%s", prompt); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
107 fflush(stdout); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
108 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
109 restart: |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
110 for (signo = 0; signo < _NSIG; signo++) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
111 signals[signo] = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
112 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
113 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
114 fd = open(_PATH_TTY, O_RDONLY); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
115 if (fd < 0) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
116 return (-1); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
117 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
118 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
119 if (tcgetattr(fd, &saved_term) != 0) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
120 close(fd); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
121 return (-1); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
122 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
123 memcpy(&term, &saved_term, sizeof (struct termios)); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
124 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
125 /* enter raw mode and turn echo off */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
126 term.c_lflag &= ~(ICANON | ECHO); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
127 while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, &term) < 0) && |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
128 (errno != EINTR)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
129 continue; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
130 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
131 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
132 /* install temporary signal handler */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
133 sigemptyset(&sa.sa_mask); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
134 sa.sa_flags = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
135 sa.sa_handler = sig_handler; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
136 sigaction(SIGHUP, &sa, &saved_sa_hup); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
137 sigaction(SIGINT, &sa, &saved_sa_int); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
138 sigaction(SIGQUIT, &sa, &saved_sa_quit); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
139 sigaction(SIGPIPE, &sa, &saved_sa_pipe); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
140 sigaction(SIGALRM, &sa, &saved_sa_alrm); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
141 sigaction(SIGTERM, &sa, &saved_sa_term); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
142 sigaction(SIGTSTP, &sa, &saved_sa_tstp); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
143 sigaction(SIGTTIN, &sa, &saved_sa_ttin); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
144 sigaction(SIGTTOU, &sa, &saved_sa_ttou); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
145 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
146 /* read key */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
147 if (read(fd, &c, 1) == sizeof (c)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
148 retval = c; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
149 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
150 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
151 /* restore previous mode and echo setting */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
152 do { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
153 while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
154 &saved_term) < 0) && (errno != EINTR)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
155 continue; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
156 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
157 } while ((tcgetattr(fd, &term) == 0) && |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
158 (term.c_lflag != saved_term.c_lflag)); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
159 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
160 /* restore previous signal handlers */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
161 sigaction(SIGHUP, &saved_sa_hup, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
162 sigaction(SIGINT, &saved_sa_int, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
163 sigaction(SIGQUIT, &saved_sa_quit, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
164 sigaction(SIGPIPE, &saved_sa_pipe, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
165 sigaction(SIGALRM, &saved_sa_alrm, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
166 sigaction(SIGTERM, &saved_sa_term, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
167 sigaction(SIGTSTP, &saved_sa_tstp, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
168 sigaction(SIGTTIN, &saved_sa_ttin, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
169 sigaction(SIGTTOU, &saved_sa_ttou, &sa); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
170 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
171 /* erase prompt */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
172 printf("\r%*s\r", (int)strlen(prompt), ""); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
173 fflush(stdout); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
174 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
175 while ((close(fd) < 0) && (errno != EINTR)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
176 continue; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
177 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
178 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
179 /* re-raise signals received */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
180 for (signo = 0; signo < _NSIG; signo++) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
181 if (signals[signo]) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
182 raise(signo); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
183 if ((signo == SIGTSTP) || (signo == SIGTTIN) || |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
184 (signo == SIGTTOU)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
185 need_restart = 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
186 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
187 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
188 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
189 if (need_restart) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
190 goto restart; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
191 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
192 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
193 return (retval); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
194 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
195 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
196 struct pager * |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
197 pager_create(FILE *fp) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
198 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
199 struct pager *pager; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
200 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
201 pager = xmalloc(sizeof (struct pager)); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
202 TAILQ_INIT(&pager->lines_head); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
203 pager->fp = fp; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
204 pager->buf_size = BUFSIZ; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
205 pager->buf = xmalloc(BUFSIZ); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
206 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
207 return (pager); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
208 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
209 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
210 void |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
211 pager_destroy(struct pager *pager) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
212 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
213 struct lines_entry *entry; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
214 struct lines_entry *entry_tmp; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
215 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
216 if (pager == NULL) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
217 return; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
218 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
219 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
220 TAILQ_FOREACH_SAFE(entry, &pager->lines_head, entry, entry_tmp) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
221 TAILQ_REMOVE(&pager->lines_head, entry, entry); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
222 free(entry->line); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
223 free(entry); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
224 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
225 free(pager->buf); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
226 free(pager); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
227 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
228 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
229 int |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
230 pager_vprintf(struct pager *pager, const char *fmt, va_list args) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
231 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
232 int len; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
233 va_list args_new; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
234 char *p; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
235 size_t line_len; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
236 struct lines_entry *entry; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
237 size_t line_offset; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
238 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
239 va_copy(args_new, args); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
240 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
241 /* format multibyte string in buffer */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
242 len = vsnprintf(NULL, 0, fmt, args); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
243 if (len < 0) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
244 err(1, "vsnprintf"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
245 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
246 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
247 if (pager->buf_size < (size_t)len + 1) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
248 pager->buf_size = len + 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
249 pager->buf = xrealloc(pager->buf, pager->buf_size); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
250 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
251 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
252 len = vsnprintf(pager->buf, pager->buf_size, fmt, args_new); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
253 if (len < 0) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
254 err(1, "vsnprintf"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
255 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
256 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
257 /* split buffer into lines */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
258 for (p = pager->buf; *p != '\0'; p += line_len) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
259 line_len = strcspn(p, "\n"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
260 if (p[line_len] == '\n') { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
261 line_len++; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
262 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
263 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
264 entry = TAILQ_LAST(&pager->lines_head, lines_head); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
265 line_offset = (entry != NULL) ? strlen(entry->line) : 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
266 if ((entry != NULL) && (entry->line[line_offset - 1] != '\n')) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
267 /* |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
268 * append to the last line if it doesn't end with a |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
269 * newline |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
270 */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
271 entry->line = xrealloc(entry->line, line_offset + |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
272 line_len + 1); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
273 memcpy(entry->line + line_offset, p, line_len); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
274 entry->line[line_offset + line_len] = '\0'; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
275 } else { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
276 entry = xmalloc(sizeof (struct lines_entry)); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
277 entry->line = xmalloc(line_len + 1); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
278 memcpy(entry->line, p, line_len); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
279 entry->line[line_len] = '\0'; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
280 TAILQ_INSERT_TAIL(&pager->lines_head, entry, entry); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
281 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
282 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
283 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
284 va_end(args_new); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
285 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
286 return (len); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
287 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
288 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
289 int |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
290 pager_printf(struct pager *pager, const char *fmt, ...) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
291 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
292 int len; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
293 va_list args; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
294 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
295 va_start(args, fmt); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
296 len = pager_vprintf(pager, fmt, args); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
297 va_end(args); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
298 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
299 return (len); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
300 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
301 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
302 static unsigned int |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
303 mbsnprint(unsigned int cols, const char *s, FILE *fp) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
304 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
305 const char *p = s; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
306 unsigned int col = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
307 int mb_len; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
308 wchar_t wc; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
309 int width; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
310 char mb_buf[MB_LEN_MAX]; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
311 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
312 while ((*p != '\n') && (*p != '\0') && (col < cols)) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
313 mb_len = mbtowc(&wc, p, MB_CUR_MAX); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
314 if (mb_len != -1) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
315 width = wcwidth(wc); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
316 if (width != -1) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
317 if (snprintf(mb_buf, sizeof (mb_buf), "%.*s", |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
318 mb_len, p) != mb_len) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
319 err(1, "snprintf"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
320 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
321 } else { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
322 /* |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
323 * non-printable character, print |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
324 * replacement character |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
325 */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
326 width = 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
327 if (snprintf(mb_buf, sizeof (mb_buf), |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
328 "\357\277\275") != 3) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
329 err(1, "snprintf"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
330 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
331 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
332 } else { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
333 /* |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
334 * decoding failed, reset state and skip one |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
335 * byte |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
336 */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
337 mbtowc(NULL, NULL, MB_CUR_MAX); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
338 mb_len = 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
339 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
340 /* print replacement character */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
341 width = 1; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
342 if (snprintf(mb_buf, sizeof (mb_buf), |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
343 "\357\277\275") != 3) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
344 err(1, "snprintf"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
345 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
346 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
347 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
348 p += mb_len; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
349 col += width; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
350 if (col <= cols) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
351 if (fputs(mb_buf, fp) == EOF) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
352 err(1, "fputs"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
353 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
354 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
355 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
356 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
357 fputc('\n', fp); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
358 fflush(fp); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
359 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
360 return (col); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
361 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
362 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
363 void |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
364 pager_show(struct pager *pager) |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
365 { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
366 int is_interactive; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
367 unsigned int rows = 24; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
368 unsigned int cols = 80; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
369 #ifdef TIOCGWINSZ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
370 struct winsize ws; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
371 #endif /* TIOCGWINSZ */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
372 unsigned int row = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
373 struct lines_entry *entry; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
374 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
375 is_interactive = (isatty(STDIN_FILENO) && (pager->fp == stdout)); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
376 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
377 #ifdef TIOCGWINSZ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
378 if (is_interactive) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
379 /* determine terminal size */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
380 if (ioctl(fileno(pager->fp), TIOCGWINSZ, &ws) == 0) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
381 rows = (ws.ws_row > 0) ? ws.ws_row : rows; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
382 cols = (ws.ws_col > 0) ? ws.ws_col : cols; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
383 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
384 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
385 #endif /* TIOCGWINSZ */ |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
386 |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
387 TAILQ_FOREACH(entry, &pager->lines_head, entry) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
388 if (is_interactive) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
389 mbsnprint(cols, entry->line, pager->fp); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
390 row++; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
391 if (row == rows - 1) { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
392 getch_prompt("--More--"); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
393 row = 0; |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
394 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
395 } else { |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
396 fprintf(pager->fp, "%s", entry->line); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
397 fflush(pager->fp); |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
398 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
399 } |
a08ef0674d8e
Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff
changeset
|
400 } |