alot of renaming...
[k8sterm.git] / src / ttyrw.c
blobd046461814400c05a6c4a121bbfa1f8623a29632
1 ////////////////////////////////////////////////////////////////////////////////
2 // tty r/w
3 static int k8t_ttyCanRead (K8Term *term) {
4 for (;;) {
5 fd_set rfd;
6 struct timeval timeout = {0};
7 //
8 if (term->dead || term->cmdfd < 0) return 0;
9 FD_ZERO(&rfd);
10 FD_SET(term->cmdfd, &rfd);
11 if (select(term->cmdfd+1, &rfd, NULL, NULL, &timeout) < 0) {
12 if (errno == EINTR) continue;
13 die("select failed: %s", strerror(errno));
15 if (FD_ISSET(term->cmdfd, &rfd)) return 1;
16 break;
18 return 0;
22 static int k8t_ttyCanWrite (K8Term *term) {
23 for (;;) {
24 fd_set wfd;
25 struct timeval timeout = {0};
27 if (term->dead || term->cmdfd < 0) return 0;
28 FD_ZERO(&wfd);
29 FD_SET(term->cmdfd, &wfd);
30 if (select(term->cmdfd+1, NULL, &wfd, NULL, &timeout) < 0) {
31 if (errno == EINTR) continue;
32 die("select failed: %s", strerror(errno));
34 if (FD_ISSET(term->cmdfd, &wfd)) return 1;
35 break;
37 return 0;
41 #ifdef DUMP_IO
42 static void wrstr (const char *s, int len) {
43 if (s == NULL) return;
44 while (len-- > 0) {
45 unsigned char c = (unsigned char)(*s++);
47 if (c < 32) fprintf(stderr, "{%u}", c); else fwrite(&c, 1, 1, stderr);
50 #endif
53 // return -1 if there was read error, 0 otherwise
54 static int k8t_ttyRead (K8Term *term) {
55 char *ptr;
56 int left;
57 int res = 0;
59 /* append read bytes to unprocessed bytes */
60 if (term == NULL || term->dead || term->cmdfd < 0) return -1;
61 #ifdef DUMP_PROG_OUTPUT
62 term->xobuflen = term->obuflen;
63 #endif
64 left = OBUFSIZ-term->obuflen;
65 //fprintf(stderr, "0: k8t_ttyRead before: free=%d, used=%d\n", left, term->obuflen);
66 while (left > 0 && k8t_ttyCanRead(term)) {
67 int ret;
69 //if ((ret = read(term->cmdfd, term->obuf+term->obuflen, 1)) < 0) die("Couldn't read from shell: %s", strerror(errno));
70 if ((ret = read(term->cmdfd, term->obuf+term->obuflen, left)) < 0) {
71 //fprintf(stderr, "Warning: couldn't read from tty: %s\n", strerror(errno));
72 if (errno == EINTR) continue;
73 res = -1;
74 break;
77 if (ret == 0) break;
78 //fprintf(stderr, "k8t_ttyRead: got %d bytes\n", ret);
79 term->obuflen += ret;
80 left -= ret;
82 //fprintf(stderr, "1: k8t_ttyRead after: free=%d, used=%d\n", left, term->obuflen);
83 if (term->obuflen == 0) return res;
84 /* process every complete utf8 char */
85 #ifdef DUMP_PROG_OUTPUT
87 FILE *fo = fopen("zlogo.log", "ab");
88 if (fo) {
89 fwrite(term->obuf+term->xobuflen, term->obuflen-term->xobuflen, 1, fo);
90 fclose(fo);
93 #endif
94 ptr = term->obuf;
95 if (term->needConv) {
96 // need conversion from locale to utf-8
97 //fprintf(stderr, "buf: %d bytes\n", term->obuflen);
98 while (term->obuflen > 0) {
99 char obuf[UTF_SIZ+1];
100 int len;
102 //fprintf(stderr, "'%c' (%d)\n", (*ptr >= ' ' && *ptr != 127 ? *ptr : '.'), *ptr);
103 len = loc2utf(obuf, ptr, 1);
104 #ifdef DUMP_IO_READ
106 fprintf(stderr, "rdc: [");
107 wrstr(ptr, 1);
108 fprintf(stderr, "] --> [");
109 wrstr(obuf, len);
110 fprintf(stderr, "]\n");
111 fflush(stderr);
113 #endif
114 if (len > 0) {
115 obuf[len] = 0;
116 k8t_tmPutC(term, obuf);
118 ++ptr;
119 --term->obuflen;
121 term->obuflen = 0;
122 } else {
123 // don't do any conversion
124 while (term->obuflen >= UTF_SIZ || k8t_UTF8IsFull(ptr, term->obuflen)) {
125 uint32_t utf8c;
126 char s[UTF_SIZ+1];
127 int charsize = k8t_UTF8Decode(&utf8c, ptr);
128 int len;
130 len = k8t_UTF8Encode(s, utf8c);
131 #ifdef DUMP_IO_READ
133 fprintf(stderr, "rdx: [");
134 wrstr(s, len);
135 fprintf(stderr, "]\n");
136 fflush(stderr);
138 #endif
139 if (len > 0) {
140 s[len] = 0;
141 k8t_tmPutC(term, s);
143 ptr += charsize;
144 term->obuflen -= charsize;
146 if (res < 0) term->obuflen = 0; // there was read error, we should not expect more bytes
147 //dlogf("2: k8t_ttyRead afterproc: used=%d", term->obuflen);
149 /* keep any uncomplete utf8 char for the next call */
150 if (term->obuflen > 0) {
151 res = 0;
152 memmove(term->obuf, ptr, term->obuflen);
155 return res;
159 static void k8t_ttyFlushWriteBuf (K8Term *term) {
160 if (term == NULL || term->dead || term->cmdfd < 0) return;
161 if (term->wrbufpos >= term->wrbufused) {
162 term->wrbufpos = term->wrbufused = 0;
163 return;
165 //dlogf("0: k8t_ttyFlushWriteBuf before: towrite=%d", term->wrbufused-term->wrbufpos);
166 while (term->wrbufpos < term->wrbufused && k8t_ttyCanWrite(term)) {
167 int ret;
169 if ((ret = write(term->cmdfd, term->wrbuf+term->wrbufpos, term->wrbufused-term->wrbufpos)) < 0) {
170 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, strerror(errno));
171 if (errno == EINTR) continue;
172 break;
174 term->wrbufpos += ret;
176 if (term->wrbufpos > 0) {
177 int left = term->wrbufused-term->wrbufpos;
179 if (left < 1) {
180 // write buffer is empty
181 term->wrbufpos = term->wrbufused = 0;
182 } else {
183 memmove(term->wrbuf, term->wrbuf+term->wrbufpos, left);
184 term->wrbufpos = 0;
185 term->wrbufused = left;
188 //dlogf("1: k8t_ttyFlushWriteBuf after: towrite=%d", term->wrbufused-term->wrbufpos);
192 // convert char to locale and write it
193 // return<0: error; ==0: ok
194 static int k8t_ttyWriteRawChar (K8Term *term, const char *s, int len, int noenc) {
195 char loc[16];
196 int clen;
198 if (s == NULL || len < 1) return 0;
199 if (!noenc) {
200 if (term->needConv) {
201 if ((clen = utf2loc(loc, s, len)) < 1) return 0;
202 } else {
203 if ((clen = k8t_UTF8Size(s)) < 1) return 0;
204 memmove(loc, s, clen);
206 } else {
207 memmove(loc, s, (clen = len));
209 #ifdef DUMP_IO_WRITE
211 fprintf(stderr, "wrc: [");
212 wrstr(s, len);
213 fprintf(stderr, "] --> [");
214 wrstr(loc, clen);
215 fprintf(stderr, "]\n");
216 fflush(stderr);
218 #endif
220 while (term->wrbufused+clen >= term->wrbufsize) {
221 //FIXME: make write buffer dynamic?
222 int res;
224 // force write at least one char
225 //dlogf("k8t_ttyWrite: forced write");
226 if ((res = write(term->cmdfd, term->wrbuf+term->wrbufpos, 1)) < 0) {
227 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, strerror(errno));
228 if (errno == EINTR) continue;
229 return -1; //SHIT!
231 if (res == 0) return -1; //SHIT!
232 ++term->wrbufpos;
233 k8t_ttyFlushWriteBuf(term); // make room for char
235 memcpy(term->wrbuf+term->wrbufused, loc, clen);
236 term->wrbufused += clen;
238 return 0;
242 static void k8t_ttyWriteNoEnc (K8Term *term, const char *s, size_t n) {
243 if (n > 0) {
244 term->ubufpos = 0; // discard possible utf-8 char
245 while (n-- > 0) k8t_ttyWriteRawChar(term, s++, 1, 1);
247 k8t_ttyFlushWriteBuf(term);
251 static void k8t_ttyWrite (K8Term *term, const char *s, size_t n) {
252 if (term == NULL || term->dead || term->cmdfd < 0) return;
253 #ifdef DUMP_PROG_INPUT
254 if (s != NULL && n > 0) {
255 FILE *fo = fopen("zlogw.log", "ab");
256 if (fo) {
257 fwrite(s, n, 1, fo);
258 fclose(fo);
261 #endif
262 //k8t_ttyFlushWriteBuf();
263 if (s != NULL && n > 0) {
264 while (n > 0) {
265 unsigned char c = (unsigned char)(s[0]);
267 if (term->ubufpos > 0 && k8t_UTF8IsFull(term->ubuf, term->ubufpos)) {
268 // have complete char
269 k8t_ttyWriteRawChar(term, term->ubuf, term->ubufpos, 0);
270 term->ubufpos = 0;
271 continue;
274 if (term->ubufpos == 0) {
275 // new char
276 if (c < 128) {
277 k8t_ttyWriteRawChar(term, s, 1, 0);
278 } else if ((c&0xc0) == 0xc0) {
279 // new utf-8 char
280 term->ubuf[term->ubufpos++] = *s;
281 } else {
282 // ignore unsynced utf-8
284 ++s;
285 --n;
286 continue;
288 // char continues
289 if (c < 128 || term->ubufpos >= UTF_SIZ || (c&0xc0) == 0xc0) {
290 // discard previous utf-8, it's bad
291 term->ubufpos = 0;
292 continue;
294 // collect
295 term->ubuf[term->ubufpos++] = *s;
296 ++s;
297 --n;
298 if (k8t_UTF8IsFull(term->ubuf, term->ubufpos)) {
299 // have complete char
300 k8t_ttyWriteRawChar(term, term->ubuf, term->ubufpos, 0);
301 term->ubufpos = 0;
305 k8t_ttyFlushWriteBuf(term);