chiark / gitweb /
a4b5fce562f25ce2dd434563eeab0d3f5cd74e9c
[sympathy.git] / apps / clients.c
1 /*
2  * clients.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.13  2008/02/28 16:37:16  james
14  * *** empty log message ***
15  *
16  * Revision 1.12  2008/02/28 12:12:24  james
17  * *** empty log message ***
18  *
19  * Revision 1.11  2008/02/23 11:48:51  james
20  * *** empty log message ***
21  *
22  * Revision 1.10  2008/02/22 17:06:59  james
23  * *** empty log message ***
24  *
25  * Revision 1.9  2008/02/20 18:49:11  staffcvs
26  * *** empty log message ***
27  *
28  * Revision 1.8  2008/02/20 18:31:44  james
29  * *** empty log message ***
30  *
31  * Revision 1.7  2008/02/15 23:52:12  james
32  * *** empty log message ***
33  *
34  * Revision 1.6  2008/02/15 03:32:07  james
35  * *** empty log message ***
36  *
37  * Revision 1.5  2008/02/14 10:34:47  james
38  * *** empty log message ***
39  *
40  * Revision 1.4  2008/02/14 10:34:30  james
41  * *** empty log message ***
42  *
43  * Revision 1.3  2008/02/14 02:46:44  james
44  * *** empty log message ***
45  *
46  * Revision 1.2  2008/02/14 00:57:58  james
47  * *** empty log message ***
48  *
49  * Revision 1.1  2008/02/13 18:05:06  james
50  * *** empty log message ***
51  *
52  */
53
54 #include <sympathy.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <strings.h>
59 #include <malloc.h>
60 #include "clients.h"
61
62 void
63 client_msg (IPC_Msg * m, Context * c)
64 {
65   switch (m->hdr.type)
66     {
67
68     case IPC_MSG_TYPE_NOOP:
69       break;
70     case IPC_MSG_TYPE_DEBUG:
71       fprintf (stderr, "%p [%d] %s\n", m, m->hdr.size, m->debug.msg);
72       break;
73     case IPC_MSG_TYPE_KEY:
74       vt102_send (c, m->key.key);
75       break;
76     case IPC_MSG_TYPE_SETBAUD:
77       tty_set_baud (c->t, m->setbaud.baud);
78       tty_parse_reset (c);
79
80       log_f (c->l, "<baud changed to %d>", m->setbaud.baud);
81       break;
82     case IPC_MSG_TYPE_SENDBREAK:
83       tty_send_break (c->t);
84       break;
85     case IPC_MSG_TYPE_SETFLOW:
86       tty_set_flow (c->t, m->setflow.flow);
87       break;
88     case IPC_MSG_TYPE_SETANSI:
89       vt102_set_ansi (c->v, m->setansi.ansi);
90       break;
91     case IPC_MSG_TYPE_HANGUP:
92       tty_hangup (c->t);
93       break;
94     case IPC_MSG_TYPE_SETSIZE:
95       vt102_resize(c,m->setsize.winsize);
96       break;
97     case IPC_MSG_TYPE_RESET:
98       vt102_reset(c);
99       break;
100     default:
101       fprintf (stderr, "Unhandeled message type %d\n", m->hdr.type);
102     }
103 }
104
105 void
106 client_free (Client * c)
107 {
108   if (c->s)
109     socket_free (c->s);
110
111   free (c);
112 #if 0
113   fprintf (stderr, "Client at %p freed\n", c);
114 #endif
115 }
116
117 Client *
118 clients_new_client (Clients * cs, Socket * s, Context * ctx)
119 {
120   Client *c;
121
122   c = (Client *) malloc (sizeof (Client));
123
124   c->dead = 0;
125   c->s = s;
126   c->next = cs->head;
127
128   cs->head = c;
129   cs->n++;
130
131 #if 0
132   fprintf (stderr, "Client at %p created\n", c);
133 #endif
134
135
136   if (ipc_msg_send_debug (s, "new_client"))
137     c->dead++;
138
139   return c;
140 }
141
142 void
143 clients_reap (Clients * cs)
144 {
145   Client **p, *c;
146
147
148   for (p = &cs->head; *p;)
149     {
150       Client *c = *p;
151
152       if (c->dead)
153         {
154           *p = c->next;
155           client_free (c);
156           cs->n--;
157         }
158       else
159         {
160           p = &(c->next);
161         }
162     }
163 }
164
165 Clients *
166 clients_new (void)
167 {
168   Clients *ret = (Clients *) malloc (sizeof (Clients));
169
170   ret->n = 0;
171   ret->head = NULL;
172
173   return ret;
174 }
175
176 void
177 clients_pre_select (Clients * cs, fd_set * rfds, fd_set * wfds)
178 {
179   Client *c;
180
181   for (c = cs->head; c; c = c->next)
182     {
183       socket_pre_select (c->s, rfds, wfds);
184     }
185 }
186
187 void
188 clients_post_select (Clients * cs, Context * ctx, fd_set * rfds,
189                      fd_set * wfds)
190 {
191   Client *c;
192   int deaded = 0;
193
194   for (c = cs->head; c; c = c->next)
195     {
196       if (socket_post_select (c->s, rfds, wfds))
197         {
198           c->dead++;
199           deaded++;
200         }
201
202       if (c->s->msg)
203         {
204           client_msg (c->s->msg, ctx);
205           socket_consume_msg (c->s);
206         }
207
208     }
209
210   if (deaded)
211     clients_reap (cs);
212 }
213
214
215 void
216 clients_shutdown (Clients * cs)
217 {
218   Client *c;
219
220   for (c = cs->head; c; c = c->next)
221     {
222       c->dead++;
223     }
224
225
226   clients_reap (cs);
227 }
228
229
230
231
232
233
234 int
235 send_status (Clients * cs, char *msg)
236 {
237   char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_status)];
238   IPC_Msg_status *m = (IPC_Msg_status *) mbuf;
239   int len;
240
241   Client *c;
242
243   if (!msg)
244     return;
245   len = strlen (msg) + 1;
246
247   if (!len)
248     return;
249   if (len > IPC_MAX_BUF)
250     len = IPC_MAX_BUF;
251
252   m->size = len + sizeof (IPC_Msg_status);
253   m->type = IPC_MSG_TYPE_STATUS;
254   strncpy (m->status, msg, IPC_MAX_BUF);
255   m->status[IPC_MAX_BUF - 1] = 0;
256
257   for (c = cs->head; c; c = c->next)
258     {
259       if (!c->dead)
260         if (ipc_msg_send (c->s, (IPC_Msg *) m))
261           c->dead++;
262     }
263
264   return len;
265 }
266
267
268 int
269 send_output (Clients * cs, void *buf, int len)
270 {
271   char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_term)];
272   IPC_Msg_term *m = (IPC_Msg_term *) mbuf;
273
274   Client *c;
275
276   if (!len)
277     return;
278   if (len > IPC_MAX_BUF)
279     len = IPC_MAX_BUF;
280
281   m->size = len + sizeof (IPC_Msg_term);
282   m->type = IPC_MSG_TYPE_TERM;
283   m->len = len;
284   memcpy (m->term, buf, len);
285
286   for (c = cs->head; c; c = c->next)
287     {
288       if (!c->dead)
289         if (ipc_msg_send (c->s, (IPC_Msg *) m))
290           c->dead++;
291     }
292
293
294   return len;
295 }
296
297 void
298 send_history (History * h, Client * c)
299 {
300   int rptr = h->wptr;
301
302   HISTORY_INC (h, rptr);
303
304   HISTORY_INC (h, rptr);
305   while (rptr != h->wptr)
306     {
307       History_ent *l = &h->lines[rptr];
308       if (l->valid)
309         {
310
311           if (ipc_msg_send_history (c->s, l))
312             c->dead++;
313
314         }
315       HISTORY_INC (h, rptr);
316     }
317 }
318
319 void
320 send_vt102 (VT102 * v, Client * c)
321 {
322   if (ipc_msg_send_vt102 (c->s, v))
323     c->dead++;
324
325 }