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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }