chiark / gitweb /
more than one client possible
authorian <ian>
Mon, 30 May 2005 11:11:23 +0000 (11:11 +0000)
committerian <ian>
Mon, 30 May 2005 11:11:23 +0000 (11:11 +0000)
hostside/hostside.c
hostside/hostside.h
hostside/serialio.c

index 414e769fbf0fa12fd5f2d5e9c132910de4066e58..bd00f9bfc8695d3db1e31556e04aeb839408220c 100644 (file)
 oop_source *events;
 FILE *dump_stream= 0;
 
-typedef struct OutBuffer OutBuffer;
-struct OutBuffer {
-  OutBuffer *back, *next;
-  char *m;
-  int l;
-};
-typedef struct OutBufferChain OutBufferChain;
-struct OutBufferChain {
-  const char *what;
-  int fd;
-  int done_of_head;
-  struct { OutBuffer *head, *tail; } obs;
-};
-static OutBufferChain stdin_ochain= { "stdin", 0 };
-static OutBufferChain serial_ochain= { "serial", -1 };
+static void serial_error(OutBufferChain *ch, const char *e1, const char *e2) {
+  abort();
+}
+
+static void stdin_error(OutBufferChain *ch, const char *e1, const char *e2) {
+  if (!e1)
+    exit(0);
+  fprintf(stderr,"stdin: %s: %s\n", e1, e2);
+  exit(12);  
+}
+
+static OutBufferChain serial_ochain= { (char*)"serial", -1, serial_error };
+static Client stdin_client= { { (char*)"stdin", 0, stdin_error } };
 
 static void *ochain_writeable(oop_source *evts, int fd,
                              oop_event evt, void *ch_v) {
@@ -44,7 +42,6 @@ static void *ochain_writeable(oop_source *evts, int fd,
     ob= ch->obs.head;
     if (!ob) {
       events->cancel_fd(events, fd, OOP_WRITE);
-      events->cancel_fd(events, fd, OOP_EXCEPTION);
       return OOP_CONTINUE;
     }
     if (ch->done_of_head == ob->l) {
@@ -58,7 +55,7 @@ static void *ochain_writeable(oop_source *evts, int fd,
     if (r==-1) {
       if (errno==EINTR) continue;
       if (errno==EWOULDBLOCK) return OOP_CONTINUE;
-      diee(ch->what);
+      ch->error(ch,"write",strerror(errno));
     }
     assert(r>=0);
     ch->done_of_head += r;
@@ -66,44 +63,49 @@ static void *ochain_writeable(oop_source *evts, int fd,
   }
 }
 
-static void *ochain_exception(oop_source *evts, int fd,
-                             oop_event evt, void *ch_v) {
-  OutBufferChain *ch= ch_v;
-  die(ch->what);
+static void *client_exception(oop_source *evts, int fd,
+                             oop_event evt, void *cl_v) {
+  Client *cl= cl_v;
+  cl->ch.error(&cl->ch,"comms error","exception");
+  return OOP_CONTINUE;
+}
+
+static void *serial_exception(oop_source *evts, int fd,
+                             oop_event evt, void *cl_v) {
+  die("serial port - exception");
 }
 
 static void ochain_addlink(OutBufferChain *ch, OutBuffer *ob) {
-  if (!ch->obs.head) {
+  if (!ch->obs.head)
     events->on_fd(events, ch->fd, OOP_WRITE, ochain_writeable, ch);
-    events->on_fd(events, ch->fd, OOP_EXCEPTION, ochain_exception, ch);
-  }
   LIST_LINK_TAIL(ch->obs, ob);
 }
 
-static void ovprintf(const char *fmt, va_list al)
-     __attribute__((format(printf,1,0)));
-static void ovprintf(const char *fmt, va_list al) {
+static void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
+     __attribute__((format(printf,2,0)));
+static void ovprintf(OutBufferChain *ch, const char *fmt, va_list al) {
   OutBuffer *ob;
 
   ob= malloc(sizeof(*ob));  if (!ob) diem();
   ob->l= vasprintf(&ob->m, fmt, al);  if (ob->l <= 0) diem();
-  ochain_addlink(&stdin_ochain, ob);
+  ochain_addlink(&stdin_client.ch, ob);
 }
 
-static void oprintf(const char *msg, ...) __attribute__((format(printf,1,2)));
-static void oprintf(const char *msg, ...) {
+static void oprintf(OutBufferChain *ch, const char *msg, ...)
+     __attribute__((format(printf,2,3)));
+static void oprintf(OutBufferChain *ch, const char *msg, ...) {
   va_list al;
   va_start(al,msg);
-  ovprintf(msg,al);
+  ovprintf(ch,msg,al);
   va_end(al);
 }
 
-static void badcmd(const char *how) {
-  oprintf("error %s\n",how);
+static void badcmd(ParseState *ps, const char *how) {
+  oprintf(&ps->cl->ch,"error %s\n",how);
 }
 
 static void cmd_noop(ParseState *ps, const CmdInfo *ci) {
-  oprintf("noop successful\n");
+  oprintf(&ps->cl->ch,"noop successful\n");
 }
 
 static const CmdInfo toplevel_cmds[]= {
@@ -121,7 +123,7 @@ static const CmdInfo toplevel_cmds[]= {
 
 static int ps_needword(ParseState *ps) {
   const char *space;
-  if (!ps->remain) { badcmd("too few args"); return 0; }
+  if (!ps->remain) { badcmd(ps,"too few args"); return 0; }
   space= strchr(ps->remain, ' ');
   ps->thisword= ps->remain;
   if (space) {
@@ -149,32 +151,36 @@ static const CmdInfo *ps_needword_lookup(ParseState *ps, const CmdInfo *infs) {
   return ps_lookup(ps,infs);
 }
   
-static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
-                        oop_rd_event evt, const char *errmsg, int errnoval,
-                        const char *data, size_t recsz, void *u0)
-     __attribute__((noreturn));
-static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
-                        oop_rd_event evt, const char *errmsg, int errnoval,
-                        const char *data, size_t recsz, void *u0) {
-  fprintf(stderr,"stdin %s\n",
-         oop_rd_errmsg(stdin_read, evt, errnoval, OOP_RD_STYLE_GETLINE));
-  exit(4);
+static void *client_iferr(oop_source *evts, oop_read *cl_read,
+                         oop_rd_event evt, const char *errmsg, int errnoval,
+                         const char *data, size_t recsz, void *cl_v) {
+  Client *cl= cl_v;
+
+  cl->ch.error(&cl->ch, "read",
+              oop_rd_errmsg(cl_read, evt,
+                            errnoval, OOP_RD_STYLE_GETLINE));
+  return OOP_CONTINUE;
 }
 
-static void *stdin_ifok(oop_source *evts, oop_read *stdin_read,
-                       oop_rd_event evt, const char *errmsg, int errnoval,
-                       const char *data, size_t recsz, void *u0) {
+static void *client_ifok(oop_source *evts, oop_read *cl_read,
+                        oop_rd_event evt, const char *errmsg, int errnoval,
+                        const char *data, size_t recsz, void *cl_v) {
+  Client *cl= cl_v;
   ParseState ps;
   const CmdInfo *ci;
 
-  if (evt == OOP_RD_EOF)
-    exit(0);
-  if (evt != OOP_RD_OK)
-    stdin_iferr(evts,stdin_read,evt,errmsg,errnoval,data,recsz,u0);
+  if (evt == OOP_RD_EOF) {
+    cl->ch.error(&cl->ch,0,0);
+    return OOP_CONTINUE;
+  }
   
+  if (evt != OOP_RD_OK)
+    return client_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+
+  ps.cl= cl;
   ps.remain= data;
   ci= ps_needword_lookup(&ps, toplevel_cmds);
-  if (!ci) { badcmd("unknown command"); return OOP_CONTINUE; }
+  if (!ci) { badcmd(&ps,"unknown command"); return OOP_CONTINUE; }
   ci->fn(&ps,ci);
   return OOP_CONTINUE;
 }
@@ -204,10 +210,12 @@ int main(int argc, const char **argv) {
   stdin_source= oop_rd_new_fd(events, 0, 0,0);
   if (!stdin_source) diee("oop_rd_new_fd(,0,,)");
   r= oop_rd_read(stdin_source, OOP_RD_STYLE_GETLINE, 1024,
-                stdin_ifok, 0, stdin_iferr, 0);
+                client_ifok, 0, client_iferr, 0);
   if (r) diee("oop_rd_read(stdin_source,...)");
+  events->on_fd(events, 0, OOP_EXCEPTION, client_exception, &stdin_client);
 
   events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0);
+  events->on_fd(events, serial_fd, OOP_EXCEPTION, serial_exception, 0);
   oop_sys_run(sys_events);
   abort();
 }
index f3d63bf092d8edf94162a8fe575abb732f2161cc..22c8cf44ff096c4b1e4e5b3569d30e8e21e2f4ac 100644 (file)
@@ -8,9 +8,30 @@
 
 typedef unsigned char Byte;
 
+typedef struct OutBuffer OutBuffer;
+struct OutBuffer {
+  OutBuffer *back, *next;
+  char *m;
+  int l;
+};
+
+typedef struct OutBufferChain OutBufferChain;
+struct OutBufferChain {
+  char *desc;
+  int fd;
+  void (*error)(OutBufferChain *obc, const char *e1, const char *e2);
+  int done_of_head;
+  struct { OutBuffer *head, *tail; } obs;
+};
+
+typedef struct Client Client;
+struct Client {
+  OutBufferChain ch;
+};
 
 typedef struct ParseState ParseState;
 struct ParseState {
+  Client *cl;
   const char *remain;
   const char *thisword;
   int lthisword;
@@ -23,8 +44,10 @@ struct CmdInfo {
 };
 
 extern oop_source *events;
-void die(const char *m) __attribute__((noreturn));
-void diee(const char *m) __attribute__((noreturn));
+void vdie(const char *fmt, int ev, va_list al)
+     __attribute__((noreturn,format(printf,1,0)));
+void die(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2)));
+void diee(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2)));
 void diem(void) __attribute__((noreturn));
 
 
index 5d964eacaf8f9ac334f10709c60101b5d1322224..4497f691cd5f0dae05cd957d3a22981e8f49f104 100644 (file)
@@ -4,7 +4,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <string.h>
 #include <errno.h>
+#include <stdarg.h>
 
 #include <unistd.h>
 #include <fcntl.h>
 int serial_fudge_delay= 0;
 int serial_fd= -1;
 
-void die(const char *m) { fprintf(stderr,"%s\n",m); exit(8); }
-void diee(const char *m) { perror(m); exit(12); }
-void diem(void) { perror("malloc failed"); exit(16); }
+void vdie(const char *fmt, int ev, va_list al) {
+  vfprintf(stderr,fmt,al);
+  if (ev) fprintf(stderr,": %s",strerror(ev));
+  fputc('\n',stderr);
+  exit(12);
+}
+
+void die(const char *fmt, ...)
+  { va_list al; va_start(al,fmt); vdie(fmt,0,al); }
+void diee(const char *fmt, ...)
+  { va_list al; va_start(al,fmt); vdie(fmt,errno,al); }
+void diem(void)
+  { diee("malloc failed"); }
 
 void serial_open(const char *device) {
   assert(serial_fd==-1);