annotate pager.c @ 25:616385fa1fd9

Build common functions as a library that can be reused
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Wed, 20 Sep 2017 23:57:51 +0200
parents 5c6155c8e9b6
children
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 struct pager {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
50 TAILQ_HEAD(lines_head, lines_entry) lines_head;
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
51 int fd;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
52 size_t buf_size;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
53 char *buf;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
54 };
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
55
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
56 struct lines_entry {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
57 TAILQ_ENTRY(lines_entry) entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
58 char *line;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
59 };
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 struct pager *
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
62 pager_create(int fd)
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
63 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
64 struct pager *pager;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
65
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
66 pager = xmalloc(sizeof (struct pager));
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
67 TAILQ_INIT(&pager->lines_head);
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
68 pager->fd = fd;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
69 pager->buf_size = BUFSIZ;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
70 pager->buf = xmalloc(BUFSIZ);
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 return (pager);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
73 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
74
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
75 void
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
76 pager_destroy(struct pager *pager)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
77 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
78 struct lines_entry *entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
79 struct lines_entry *entry_tmp;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
80
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
81 if (pager == NULL) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
82 return;
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 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
86 TAILQ_REMOVE(&pager->lines_head, entry, entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
87 free(entry->line);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
88 free(entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
89 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
90 free(pager->buf);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
91 free(pager);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
92 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
93
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
94 int
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
95 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
96 {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
97 int len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
98 va_list args_new;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
99 char *p;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
100 size_t line_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
101 struct lines_entry *entry;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
102 size_t line_offset;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
103
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
104 va_copy(args_new, args);
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 /* format multibyte string in buffer */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
107 len = vsnprintf(NULL, 0, fmt, args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
108 if (len < 0) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
109 err(1, "vsnprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
110 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
111
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
112 if (pager->buf_size < (size_t)len + 1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
113 pager->buf_size = len + 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
114 pager->buf = xrealloc(pager->buf, pager->buf_size);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
115 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
116
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
117 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
118 if (len < 0) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
119 err(1, "vsnprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
120 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
121
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
122 /* split buffer into lines */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
123 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
124 line_len = strcspn(p, "\n");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
125 if (p[line_len] == '\n') {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
126 line_len++;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
127 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
128
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
129 entry = TAILQ_LAST(&pager->lines_head, lines_head);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
130 line_offset = (entry != NULL) ? strlen(entry->line) : 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
131 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
132 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
133 * 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
134 * newline
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
135 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
136 entry->line = xrealloc(entry->line, line_offset +
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
137 line_len + 1);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
138 memcpy(entry->line + line_offset, p, line_len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
139 entry->line[line_offset + line_len] = '\0';
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
140 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
141 entry = xmalloc(sizeof (struct lines_entry));
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
142 entry->line = xmalloc(line_len + 1);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
143 memcpy(entry->line, p, line_len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
144 entry->line[line_len] = '\0';
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
145 TAILQ_INSERT_TAIL(&pager->lines_head, entry, entry);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
146 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
147 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
148
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
149 va_end(args_new);
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 return (len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
152 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
153
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
154 int
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
155 pager_printf(struct pager *pager, const char *fmt, ...)
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 int len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
158 va_list args;
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 va_start(args, fmt);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
161 len = pager_vprintf(pager, fmt, args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
162 va_end(args);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
163
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
164 return (len);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
165 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
166
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
167 static int
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
168 mbsnprint(unsigned int cols, const char *s, int fd)
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
169 {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
170 int retval;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
171 const char *p = s;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
172 unsigned int col = 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
173 int mb_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
174 wchar_t wc;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
175 int width;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
176 char mb_buf[MB_LEN_MAX];
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 while ((*p != '\n') && (*p != '\0') && (col < cols)) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
179 mb_len = mbtowc(&wc, p, MB_CUR_MAX);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
180 if (mb_len != -1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
181 width = wcwidth(wc);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
182 if (width != -1) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
183 if (snprintf(mb_buf, sizeof (mb_buf), "%.*s",
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
184 mb_len, p) != mb_len) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
185 err(1, "snprintf");
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 } else {
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 * non-printable character, print
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
190 * replacement character
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 width = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
193 if (snprintf(mb_buf, sizeof (mb_buf),
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
194 "\357\277\275") != 3) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
195 err(1, "snprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
196 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
197 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
198 } else {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
199 /*
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
200 * decoding failed, reset state and skip one
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
201 * byte
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
202 */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
203 mbtowc(NULL, NULL, MB_CUR_MAX);
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
204 mb_len = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
205
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
206 /* print replacement character */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
207 width = 1;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
208 if (snprintf(mb_buf, sizeof (mb_buf),
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
209 "\357\277\275") != 3) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
210 err(1, "snprintf");
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
211 }
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
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
214 p += mb_len;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
215 col += width;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
216 if (col <= cols) {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
217 retval = io_dputs(fd, mb_buf);
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
218 if (retval != IO_OK) {
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
219 return (retval);
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
220 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
221 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
222 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
223
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
224 retval = io_dputs(fd, "\n");
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
225
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
226 return (retval);
17
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
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
229 enum io_status
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
230 pager_show(struct pager *pager)
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
231 {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
232 int retval = IO_OK;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
233 int is_interactive;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
234 unsigned int rows = 24;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
235 unsigned int cols = 80;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
236 #ifdef TIOCGWINSZ
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
237 struct winsize ws;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
238 #endif /* TIOCGWINSZ */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
239 unsigned int row = 0;
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
240 struct lines_entry *entry;
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
241 int c;
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
242
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
243 is_interactive = (isatty(STDIN_FILENO) && (pager->fd == STDOUT_FILENO));
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
244
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
245 #ifdef TIOCGWINSZ
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
246 if (is_interactive) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
247 /* determine terminal size */
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
248 if (ioctl(pager->fd, TIOCGWINSZ, &ws) == 0) {
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
249 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
250 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
251 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
252 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
253 #endif /* TIOCGWINSZ */
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
254
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
255 TAILQ_FOREACH(entry, &pager->lines_head, entry) {
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
256 if (is_interactive) {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
257 retval = mbsnprint(cols, entry->line, pager->fd);
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
258 if (retval != IO_OK) {
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
259 goto out;
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
260 }
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
261 row++;
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
262 if ((TAILQ_NEXT(entry, entry) != NULL) &&
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
263 (row == rows - 1)) {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
264 /* prompt for keypress */
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
265 retval = io_get_char("--More--", &c);
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
266 if (retval != IO_OK) {
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
267 goto out;
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
268 }
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
269 row = 0;
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 } else {
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
272 retval = io_dputs(pager->fd, entry->line);
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
273 if (retval != IO_OK) {
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
274 goto out;
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
275 }
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
276 }
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
277 }
18
1e39a251cbe9 Use libtecla for interactive input
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 17
diff changeset
278
19
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
279 out:
5c6155c8e9b6 Handle signals
Guido Berhoerster <guido+pwm@berhoerster.name>
parents: 18
diff changeset
280 return (retval);
17
a08ef0674d8e Page long output in interactive mode
Guido Berhoerster <guido+pwm@berhoerster.name>
parents:
diff changeset
281 }