chiark / gitweb /
*** empty log message ***
[sympathy.git] / src / terminal.c
1 /*
2  * terminal.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/13 01:08:18  james
14  * *** empty log message ***
15  *
16  * Revision 1.1  2008/02/12 22:36:46  james
17  * *** empty log message ***
18  *
19  * Revision 1.1  2008/02/09 15:47:28  james
20  * *** empty log message ***
21  *
22  * Revision 1.2  2008/02/07 11:11:14  staffcvs
23  * *** empty log message ***
24  *
25  * Revision 1.1  2008/02/07 01:02:52  james
26  * *** empty log message ***
27  *
28  * Revision 1.3  2008/02/06 17:53:28  james
29  * *** empty log message ***
30  *
31  * Revision 1.2  2008/02/04 02:05:06  james
32  * *** empty log message ***
33  *
34  * Revision 1.1  2008/02/04 01:32:39  james
35  * *** empty log message ***
36  *
37  */
38
39 #include "project.h"
40
41
42 typedef struct TERMINAL_struct
43 {
44   TTY_SIGNATURE;
45   struct termios orig_termios;
46   struct TERMINAL_struct *next;
47 } TERMINAL;
48
49
50 static TERMINAL terminal_list=NULL;
51 int terminal_winches;
52
53
54
55 static void
56 terminal_close (TTY * _t)
57 {
58   TERMINAL *t = (TERMINAL *) _t;
59   TERMINAL **ptr=&terminal_list;
60
61   if (!t)
62     return;
63
64   /* Take out of cleanup list */
65   while (*ptr && (*ptr != t)) ptr=&((*ptr)->next);
66
67   if (*ptr) 
68         *ptr=t->next;
69
70   tcsetattr(t->wfd,TCSANOW,&t->orig_termios);
71
72   set_blocking(t->rfd);
73   set_blocking(t->wfd);
74
75   free (t);
76 }
77
78
79 void terminal_atexit(void)
80 {
81 while (terminal_list)
82         terminal_close(terminal_list);
83 }
84
85 static void sigint(int dummy)
86 {
87 terminal_atexit();
88 exit(-1);
89 }
90
91 static void
92 sigwinch (int not)
93 {
94   terminal_winches++;
95 }
96
97
98 void
99 terminal_getsize (TTY *_t)
100 {
101 TERMINAL *t=(TTY *) _t;
102   struct winsize sz = { 0 };
103
104 if (!t) return;
105
106 if (ioctl (a->wfd, TIOCGWINSZ, &sz))
107     {
108       t->size.x = CRT_COLS;
109       t->size.y = CRT_ROWS;
110     }
111   else
112     {
113       t->size.x = sz.ws_col;
114       t->size.y = sz.ws_row;
115     }
116 }
117
118
119 void terminal_dispatch(void)
120 {
121 TERMINAL *t;
122
123
124 if (!terminal_winches) return;
125
126 terminal_winches=0;
127
128 for (t=terminal_list;t;t=t->next)
129 terminal_getsize(t);
130
131 }
132
133
134 static int
135 terminal_read (TTY * _t, void *buf, int len)
136 {
137   TERMINAL *t = (TERMINAL *) _t;
138   int red, done = 0;
139
140   terminal_dispatch();
141
142   do
143     {
144
145       red = wrap_read (t->fd, buf, len);
146       if (red < 0)
147         return -1;
148       if (!red)
149         return done;
150
151       buf += red;
152       len -= red;
153       done += red;
154     }
155   while (len);
156
157
158   return done;
159 }
160
161
162 static int
163 terminal_write (TTY * _t, void *buf, int len)
164 {
165   int writ, done = 0;
166   TERMINAL *t = (TERMINAL *) _t;
167
168   terminal_dispatch();
169
170   do
171     {
172
173       writ = wrap_write (t->fd, buf, len);
174       if (writ < 0)
175         return -1;
176       if (!writ)
177         sleep (1);
178
179       buf += writ;
180       len -= writ;
181       done += writ;
182     }
183   while (len);
184
185
186   return done;
187 }
188
189
190 void terminal_register_handlers(void)
191 {
192  struct sigaction sa = { 0 };
193
194     sa.sa_handler = sigwinch;
195     sa.sa_flags = SA_RESTART;
196     sigaction (SIGWINCH, &sa, NULL);
197
198     sa.sa_handler = sigint;
199     sa.sa_flags = SA_RESTART;
200     sigaction (SIGINT, &sa, NULL);
201 }
202
203 TTY *
204 terminal_open (int rfd,int wfd)
205 {
206   TERMINAL *t;
207   pid_t child;
208   char name[1024];
209   struct termios termios;
210
211   t = (TERMINAL *) malloc (sizeof (TERMINAL));
212
213   t->rfd = rfd;
214   t->wfd = wfd;
215
216   tcgetattr(wfd,&t->orig_termios);
217
218   t->next=terminal_list;
219   terminal_list=t;
220
221   tcgetattr(tfd,&termios);
222
223   set_nonblocking (rfd);
224   set_nonblocking (wfd);
225
226
227   raw_termios (&termios);
228
229   tcsetattr(wfd,TCSANOW,&termios);
230
231   t->read = terminal_read;
232   t->write = terminal_write;
233   t->close = terminal_close;
234
235
236   terminal_getsize((TTY*) t);
237
238   return (TTY *) t;
239 }
240