1 ////////////////////////////////////////////////////////////////////////////////
3 static int k8t_ttyCanRead (K8Term
*term
) {
6 struct timeval timeout
= {0};
8 if (term
->dead
|| term
->cmdfd
< 0) return 0;
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;
22 static int k8t_ttyCanWrite (K8Term
*term
) {
25 struct timeval timeout
= {0};
27 if (term
->dead
|| term
->cmdfd
< 0) return 0;
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;
42 static void wrstr (const char *s
, int len
) {
43 if (s
== NULL
) return;
45 unsigned char c
= (unsigned char)(*s
++);
47 if (c
< 32) fprintf(stderr
, "{%u}", c
); else fwrite(&c
, 1, 1, stderr
);
53 // return -1 if there was read error, 0 otherwise
54 static int k8t_ttyRead (K8Term
*term
) {
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
;
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
)) {
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;
78 //fprintf(stderr, "k8t_ttyRead: got %d bytes\n", 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");
89 fwrite(term
->obuf
+term
->xobuflen
, term
->obuflen
-term
->xobuflen
, 1, fo
);
96 // need conversion from locale to utf-8
97 //fprintf(stderr, "buf: %d bytes\n", term->obuflen);
98 while (term
->obuflen
> 0) {
102 //fprintf(stderr, "'%c' (%d)\n", (*ptr >= ' ' && *ptr != 127 ? *ptr : '.'), *ptr);
103 len
= loc2utf(obuf
, ptr
, 1);
106 fprintf(stderr
, "rdc: [");
108 fprintf(stderr
, "] --> [");
110 fprintf(stderr
, "]\n");
116 k8t_tmPutC(term
, obuf
);
123 // don't do any conversion
124 while (term
->obuflen
>= UTF_SIZ
|| k8t_UTF8IsFull(ptr
, term
->obuflen
)) {
127 int charsize
= k8t_UTF8Decode(&utf8c
, ptr
);
130 len
= k8t_UTF8Encode(s
, utf8c
);
133 fprintf(stderr
, "rdx: [");
135 fprintf(stderr
, "]\n");
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) {
152 memmove(term
->obuf
, ptr
, term
->obuflen
);
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;
165 //dlogf("0: k8t_ttyFlushWriteBuf before: towrite=%d", term->wrbufused-term->wrbufpos);
166 while (term
->wrbufpos
< term
->wrbufused
&& k8t_ttyCanWrite(term
)) {
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;
174 term
->wrbufpos
+= ret
;
176 if (term
->wrbufpos
> 0) {
177 int left
= term
->wrbufused
-term
->wrbufpos
;
180 // write buffer is empty
181 term
->wrbufpos
= term
->wrbufused
= 0;
183 memmove(term
->wrbuf
, term
->wrbuf
+term
->wrbufpos
, left
);
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
) {
198 if (s
== NULL
|| len
< 1) return 0;
200 if (term
->needConv
) {
201 if ((clen
= utf2loc(loc
, s
, len
)) < 1) return 0;
203 if ((clen
= k8t_UTF8Size(s
)) < 1) return 0;
204 memmove(loc
, s
, clen
);
207 memmove(loc
, s
, (clen
= len
));
211 fprintf(stderr
, "wrc: [");
213 fprintf(stderr
, "] --> [");
215 fprintf(stderr
, "]\n");
220 while (term
->wrbufused
+clen
>= term
->wrbufsize
) {
221 //FIXME: make write buffer dynamic?
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;
231 if (res
== 0) return -1; //SHIT!
233 k8t_ttyFlushWriteBuf(term
); // make room for char
235 memcpy(term
->wrbuf
+term
->wrbufused
, loc
, clen
);
236 term
->wrbufused
+= clen
;
242 static void k8t_ttyWriteNoEnc (K8Term
*term
, const char *s
, size_t n
) {
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");
262 //k8t_ttyFlushWriteBuf();
263 if (s
!= NULL
&& 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);
274 if (term
->ubufpos
== 0) {
277 k8t_ttyWriteRawChar(term
, s
, 1, 0);
278 } else if ((c
&0xc0) == 0xc0) {
280 term
->ubuf
[term
->ubufpos
++] = *s
;
282 // ignore unsynced utf-8
289 if (c
< 128 || term
->ubufpos
>= UTF_SIZ
|| (c
&0xc0) == 0xc0) {
290 // discard previous utf-8, it's bad
295 term
->ubuf
[term
->ubufpos
++] = *s
;
298 if (k8t_UTF8IsFull(term
->ubuf
, term
->ubufpos
)) {
299 // have complete char
300 k8t_ttyWriteRawChar(term
, term
->ubuf
, term
->ubufpos
, 0);
305 k8t_ttyFlushWriteBuf(term
);