chiark / gitweb /
bc272de697ba1000aba52dcaa20e20031ba7fe0f
[trains.git] / hostside / obc.c
1 /**/
2
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <stdarg.h>
7 #include <string.h>
8
9 #include "hostside.h"
10 #include "../layout/dlist.h"
11
12 struct OutBuffer {
13   OutBuffer *back, *next;
14   char *m;
15   int l;
16 };
17
18 static void *writeable(oop_source *evts, int fd,
19                        oop_event evt, void *ch_v) {
20   OutBufferChain *ch= ch_v;
21   OutBuffer *ob;
22   int r;
23   
24   assert(fd == ch->fd);
25   assert(evt == OOP_WRITE);
26
27   for (;;) {
28     ob= ch->obs.head;
29     if (!ob) {
30       events->cancel_fd(events, fd, OOP_WRITE);
31       return OOP_CONTINUE;
32     }
33     if (ch->done_of_head == ob->l) {
34       LIST_UNLINK(ch->obs, ob);
35       free(ob);
36       free(ob->m);
37       ch->done_of_head= 0;
38       continue;
39     }
40     r= write(ch->fd, ob->m + ch->done_of_head, ob->l - ch->done_of_head);
41     if (r==-1) {
42       if (errno==EINTR) continue;
43       if (errno==EWOULDBLOCK) return OOP_CONTINUE;
44       ch->error(ch,"write",strerror(errno));
45     }
46     assert(r>=0);
47     ch->done_of_head += r;
48     assert(ch->done_of_head <= ob->l);
49   }
50 }
51
52 static void addlink(OutBufferChain *ch, OutBuffer *ob) {
53   if (!ch->obs.head)
54     events->on_fd(events, ch->fd, OOP_WRITE, writeable, ch);
55   LIST_LINK_TAIL(ch->obs, ob);
56 }
57
58 void obc_init(OutBufferChain *ch) {
59   ch->done_of_head= 0;
60   LIST_INIT(ch->obs);
61 }
62
63 void ovprintf(OutBufferChain *ch, const char *fmt, va_list al) {
64   OutBuffer *ob;
65
66   ob= mmalloc(sizeof(*ob));
67   ob->l= vasprintf(&ob->m, fmt, al);  if (ob->l <= 0) diem();
68   addlink(ch, ob);
69 }
70
71 void oprintf(OutBufferChain *ch, const char *msg, ...) {
72   va_list al;
73   va_start(al,msg);
74   ovprintf(ch,msg,al);
75   va_end(al);
76 }
77
78 void owrite(OutBufferChain *ch, const char *data, int l) {
79   OutBuffer *ob;
80   ob= mmalloc(sizeof(*ob));
81   ob->l= l;
82   ob->m= mmalloc(l);
83   memcpy(ob->m, data, l);
84   addlink(ch,ob);
85 }