chiark / gitweb /
*** empty log message ***
[sympathy.git] / src / tty.c
1 /*
2  * testtty.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id$";
10
11 /*
12  * $Log$
13  * Revision 1.1  2008/02/07 01:02:52  james
14  * *** empty log message ***
15  *
16  * Revision 1.3  2008/02/06 17:53:28  james
17  * *** empty log message ***
18  *
19  * Revision 1.2  2008/02/04 02:05:06  james
20  * *** empty log message ***
21  *
22  * Revision 1.1  2008/02/04 01:32:39  james
23  * *** empty log message ***
24  *
25  */
26
27 #include "project.h"
28
29 static void
30 set_nonblocking (int fd)
31 {
32   long arg;
33   arg = fcntl (fd, F_GETFL, arg);
34   arg |= O_NONBLOCK;
35   fcntl (fd, F_SETFL, arg);
36 }
37
38 static void
39 set_blocking (int fd)
40 {
41   long arg;
42   arg = fcntl (fd, F_GETFL, arg);
43   arg &= ~O_NONBLOCK;
44   fcntl (fd, F_SETFL, arg);
45 }
46
47 static void
48 default_termios (struct termios *termios)
49 {
50
51   memset (termios, 0, sizeof (termios));
52
53   termios->c_iflag = ICRNL | IXON;
54   termios->c_oflag = OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0;
55   termios->c_lflag =
56     ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE;
57
58   termios->c_cc[VINTR] = 003;
59   termios->c_cc[VQUIT] = 034;
60   termios->c_cc[VERASE] = 0177;
61   termios->c_cc[VKILL] = 025;
62   termios->c_cc[VEOF] = 004;
63   termios->c_cc[VEOL] = 0;
64   termios->c_cc[VEOL2] = 0;
65   termios->c_cc[VSTART] = 021;
66   termios->c_cc[VSTOP] = 023;
67   termios->c_cc[VSUSP] = 032;
68   termios->c_cc[VLNEXT] = 026;
69   termios->c_cc[VWERASE] = 027;
70   termios->c_cc[VREPRINT] = 022;
71   termios->c_cc[VDISCARD] = 017;
72
73   termios->c_cflag = CS8 | CREAD | CLOCAL;
74
75   cfsetispeed (termios, B9600);
76   cfsetospeed (termios, B9600);
77 }
78
79
80 static int
81 open_fd_to_bash (void)          /*thump */
82 {
83   pid_t child;
84   int fd;
85   struct winsize winsize = { 0 };
86   struct termios termios;
87
88   default_termios (&termios);
89
90   winsize.ws_row = VT102_ROWS;
91   winsize.ws_col = VT102_COLS;
92
93   child = forkpty (&fd, NULL, &termios, &winsize);
94
95   switch (child)
96     {
97     case -1:                   /*boo hiss */
98       return -1;
99     case 0:                    /*waaah */
100       setenv ("TERM", "vt102", 1);
101       execl ("/bin/sh", "-", (char *) 0);
102       _exit (-1);
103     }
104
105   return fd;
106 }
107
108
109 TTY *
110 tty_new_test (void)
111 {
112   TTY *t;
113   t = (TTY *) malloc (sizeof (TTY));
114   t->fd = open_fd_to_bash ();
115
116   set_nonblocking (t->fd);
117
118   return t;
119 }
120
121 static int
122 wrap_read (int fd, void *buf, int len)
123 {
124   int red;
125
126   red = read (fd, buf, len);
127   if (!red)
128     return -1;
129
130   if ((red < 0) && (errno == EAGAIN))
131     red = 0;
132
133   return red;
134 }
135
136 static int
137 wrap_write (int fd, void *buf, int len)
138 {
139   int writ;
140
141   writ = write (fd, buf, len);
142   if (!writ)
143     return -1;
144
145   if ((writ < 0) && (errno == -EAGAIN))
146     writ = 0;
147
148   return writ;
149 }
150
151 int
152 tty_read (TTY * t, void *buf, int len)
153 {
154   int red, done = 0;
155
156
157   do
158     {
159
160       red = wrap_read (t->fd, buf, len);
161       if (red < 0)
162         return -1;
163       if (!red)
164         return done;
165
166       buf += red;
167       len -= red;
168       done += red;
169     }
170   while (len);
171
172
173   return done;
174 }
175
176
177 int
178 tty_write (TTY * t, void *buf, int len)
179 {
180   int writ, done = 0;
181
182 #if 0
183   {
184     int i;
185     uint8_t *p = buf;
186     for (i = 0; i < len; ++i)
187       fprintf (stderr, "vw: %03o %c\n", p[i], p[i] > 31 ? p[i] : 32);
188   }
189 #endif
190
191   do
192     {
193
194       writ = wrap_write (t->fd, buf, len);
195       if (writ < 0)
196         return -1;
197       if (!writ)
198         sleep (1);
199
200       buf += writ;
201       len -= writ;
202       done += writ;
203     }
204   while (len);
205
206
207   return done;
208 }
209
210 void
211 tty_free (TTY * t)
212 {
213   close (t->fd);
214   free (t);
215 }