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