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