1 ////////////////////////////////////////////////////////////////////////////////
3 static int ttycanread (void) {
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", SERRNO
);
15 if (FD_ISSET(term
->cmdfd
, &rfd
)) return 1;
22 static int ttycanwrite (void) {
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", SERRNO
);
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 static void ttyread (void) {
57 /* append read bytes to unprocessed bytes */
58 if (term
== NULL
|| term
->dead
|| term
->cmdfd
< 0) return;
59 #ifdef DUMP_PROG_OUTPUT
60 term
->xobuflen
= term
->obuflen
;
62 left
= OBUFSIZ
-term
->obuflen
;
63 //dlogf("0: ttyread before: free=%d, used=%d", left, term->obuflen);
64 while (left
> 0 && ttycanread()) {
67 //if ((ret = read(term->cmdfd, term->obuf+term->obuflen, 1)) < 0) die("Couldn't read from shell: %s", SERRNO);
68 if ((ret
= read(term
->cmdfd
, term
->obuf
+term
->obuflen
, left
)) < 0) {
69 //fprintf(stderr, "Warning: couldn't read from tty #%d: %s\n", termidx, SERRNO);
75 //dlogf("1: ttyread after: free=%d, used=%d", left, term->obuflen);
76 /* process every complete utf8 char */
77 #ifdef DUMP_PROG_OUTPUT
79 FILE *fo
= fopen("zlogo.log", "ab");
81 fwrite(term
->obuf
+term
->xobuflen
, term
->obuflen
-term
->xobuflen
, 1, fo
);
88 // need conversion from locale to utf-8
89 //fprintf(stderr, "buf: %d bytes\n", term->obuflen);
90 while (term
->obuflen
> 0) {
94 len
= loc2utf(obuf
, ptr
, 1);
97 fprintf(stderr
, "rdc: [");
99 fprintf(stderr
, "] --> [");
101 fprintf(stderr
, "]\n");
114 // don't do any conversion
115 while (term
->obuflen
>= UTF_SIZ
|| isfullutf8(ptr
, term
->obuflen
)) {
118 int charsize
= utf8decode(&utf8c
, ptr
);
121 len
= utf8encode(s
, utf8c
);
124 fprintf(stderr
, "rdx: [");
126 fprintf(stderr
, "]\n");
135 term
->obuflen
-= charsize
;
137 //dlogf("2: ttyread afterproc: used=%d", term->obuflen);
139 /* keep any uncomplete utf8 char for the next call */
140 if (term
->obuflen
> 0) memmove(term
->obuf
, ptr
, term
->obuflen
);
144 static void ttyflushwrbuf (void) {
145 if (term
== NULL
|| term
->dead
|| term
->cmdfd
< 0) return;
146 if (term
->wrbufpos
>= term
->wrbufused
) {
147 term
->wrbufpos
= term
->wrbufused
= 0;
150 //dlogf("0: ttyflushwrbuf before: towrite=%d", term->wrbufused-term->wrbufpos);
151 while (term
->wrbufpos
< term
->wrbufused
&& ttycanwrite()) {
154 if ((ret
= write(term
->cmdfd
, term
->wrbuf
+term
->wrbufpos
, term
->wrbufused
-term
->wrbufpos
)) == -1) {
155 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, SERRNO);
157 term
->wrbufpos
+= ret
;
159 if (term
->wrbufpos
> 0) {
160 int left
= term
->wrbufused
-term
->wrbufpos
;
163 // write buffer is empty
164 term
->wrbufpos
= term
->wrbufused
= 0;
166 memmove(term
->wrbuf
, term
->wrbuf
+term
->wrbufpos
, left
);
168 term
->wrbufused
= left
;
171 //dlogf("1: ttyflushwrbuf after: towrite=%d", term->wrbufused-term->wrbufpos);
175 // convert char to locale and write it
176 static void ttywriterawchar (const char *s
, int len
, int noenc
) {
180 if (s
== NULL
|| len
< 1) return;
182 if (term
->needConv
) {
183 if ((clen
= utf2loc(loc
, s
, len
)) < 1) return;
185 if ((clen
= utf8size(s
)) < 1) return;
186 memmove(loc
, s
, clen
);
189 memmove(loc
, s
, (clen
= len
));
193 fprintf(stderr
, "wrc: [");
195 fprintf(stderr
, "] --> [");
197 fprintf(stderr
, "]\n");
202 while (term
->wrbufused
+clen
>= term
->wrbufsize
) {
203 //FIXME: make write buffer dynamic?
204 // force write at least one char
205 //dlogf("ttywrite: forced write");
206 if (write(term
->cmdfd
, term
->wrbuf
+term
->wrbufpos
, 1) == -1) {
207 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, SERRNO);
211 ttyflushwrbuf(); // make room for char
213 memcpy(term
->wrbuf
+term
->wrbufused
, loc
, clen
);
214 term
->wrbufused
+= clen
;
218 static void ttywritenoenc (const char *s
, size_t n
) {
220 term
->ubufpos
= 0; // discard possible utf-8 char
221 while (n
-- > 0) ttywriterawchar(s
++, 1, 1);
227 static void ttywrite (const char *s
, size_t n
) {
228 if (term
== NULL
|| term
->dead
|| term
->cmdfd
< 0) return;
229 #ifdef DUMP_PROG_INPUT
230 if (s
!= NULL
&& n
> 0) {
231 FILE *fo
= fopen("zlogw.log", "ab");
239 if (s
!= NULL
&& n
> 0) {
241 unsigned char c
= (unsigned char)(s
[0]);
243 if (term
->ubufpos
> 0 && isfullutf8(term
->ubuf
, term
->ubufpos
)) {
244 // have complete char
245 ttywriterawchar(term
->ubuf
, term
->ubufpos
, 0);
250 if (term
->ubufpos
== 0) {
253 ttywriterawchar(s
, 1, 0);
254 } else if ((c
&0xc0) == 0xc0) {
256 term
->ubuf
[term
->ubufpos
++] = *s
;
258 // ignore unsynced utf-8
265 if (c
< 128 || term
->ubufpos
>= UTF_SIZ
|| (c
&0xc0) == 0xc0) {
266 // discard previous utf-8, it's bad
271 term
->ubuf
[term
->ubufpos
++] = *s
;
274 if (isfullutf8(term
->ubuf
, term
->ubufpos
)) {
275 // have complete char
276 ttywriterawchar(term
->ubuf
, term
->ubufpos
, 0);