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