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