Introduction
Introduction Statistics Contact Development Disclaimer Help
ptty.c - scroll - scrollbackbuffer program for st
git clone git://git.suckless.org/scroll
Log
Files
Refs
README
LICENSE
---
ptty.c (2734B)
---
1 #include <sys/wait.h>
2
3 #include <errno.h>
4 #include <inttypes.h>
5 #include <limits.h>
6 #include <poll.h>
7 #include <stdarg.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <termios.h>
13 #include <unistd.h>
14
15 #if defined(__linux)
16 #include <pty.h>
17 #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
18 #include <util.h>
19 #elif defined(__FreeBSD__) || defined(__DragonFly__)
20 #include <libutil.h>
21 #endif
22
23 void
24 die(const char *fmt, ...)
25 {
26 va_list ap;
27 va_start(ap, fmt);
28 vfprintf(stderr, fmt, ap);
29 va_end(ap);
30
31 if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
32 fputc(' ', stderr);
33 perror(NULL);
34 } else {
35 fputc('\n', stderr);
36 }
37
38 exit(EXIT_FAILURE);
39 }
40
41 void
42 usage(void)
43 {
44 fputs("ptty [-C] [-c cols] [-r rows] cmd\n", stderr);
45 exit(EXIT_FAILURE);
46 }
47
48 int
49 main(int argc, char *argv[])
50 {
51 struct winsize ws = {.ws_row = 25, .ws_col = 80, 0, 0};
52 int ch;
53 bool closeflag = false;
54
55 while ((ch = getopt(argc, argv, "c:r:Ch")) != -1) {
56 switch (ch) {
57 case 'c': /* cols */
58 ws.ws_col = strtoimax(optarg, NULL, 10);
59 if (errno != 0)
60 die("strtoimax: %s", optarg);
61 break;
62 case 'r': /* lines */
63 ws.ws_row = strtoimax(optarg, NULL, 10);
64 if (errno != 0)
65 die("strtoimax: %s", optarg);
66 break;
67 case 'C':
68 closeflag = true;
69 break;
70 case 'h':
71 default:
72 usage();
73 }
74 }
75 argc -= optind;
76 argv += optind;
77
78 if (argc < 1)
79 usage();
80
81 int mfd;
82 pid_t child = forkpty(&mfd, NULL, NULL, &ws);
83 switch (child) {
84 case -1:
85 die("forkpty");
86 case 0: /* child */
87 execvp(argv[0], argv);
88 die("exec");
89 }
90
91 /* parent */
92
93 if (closeflag && close(mfd) == -1)
94 die("close:");
95
96 int pfds = 2;
97 struct pollfd pfd[2] = {
98 { STDIN_FILENO, POLLIN, 0},
99 { mfd, POLLIN, 0}
100 };
101
102 for (;;) {
103 char buf[BUFSIZ];
104 ssize_t n;
105 int r;
106
107 if ((r = poll(pfd, pfds, -1)) == -1)
108 die("poll:");
109
110 if (pfd[0].revents & POLLIN) {
111 if ((n = read(STDIN_FILENO, buf, sizeof buf)) ==…
112 die("read:");
113 if (n == 0) {
114 pfd[0].fd = -1;
115 if (close(mfd) == -1)
116 die("close:");
117 break;
118 }
119 if (write(mfd, buf, n) == -1)
120 die("write:");
121 }
122
123 if (pfd[1].revents & POLLIN) {
124 if ((n = read(mfd, buf, sizeof(buf)-1)) == -1)
125 die("read:");
126
127 if (n == 0) break;
128
129 buf[n] = '\0';
130
131 /* handle cursor position request */
132 if (strcmp("\033[6n", buf) == 0) {
133 dprintf(mfd, "\033[25;1R");
134 continue;
135 }
136
137 if (write(STDOUT_FILENO, buf, n) == -1)
138 die("write:");
139 }
140
141 if (pfd[0].revents & POLLHUP) {
142 pfd[0].fd = -1;
143 if (close(mfd) == -1)
144 die("close:");
145 break;
146 }
147 if (pfd[1].revents & POLLHUP)
148 break;
149 }
150
151 int status;
152 if (waitpid(child, &status, 0) != child)
153 die("waitpid:");
154
155 return WEXITSTATUS(status);
156 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.