These work just like the dribbler done-functions. We're going to need
this soon.
typedef struct gobbler {
sel_file f;
typedef struct gobbler {
sel_file f;
+ void (*done)(struct gobbler *, int, void *);
+ void *p;
} gobbler;
typedef struct dribbler {
} gobbler;
typedef struct dribbler {
/*----- Gobblers ----------------------------------------------------------*
*
* A gobbler just eats everything it sees on its input descriptor.
/*----- Gobblers ----------------------------------------------------------*
*
* A gobbler just eats everything it sees on its input descriptor.
- * Eventually, when it sees end-of-file, it closes the input descriptor and
- * quits.
+ * Eventually, when it sees end-of-file, it closes the input descriptor,
+ * calls a user-supplied calback function, and quits.
*/
static void gobbler_close(gobbler *g)
*/
static void gobbler_close(gobbler *g)
break;
else {
moan("read (gobble): %s", strerror(errno));
break;
else {
moan("read (gobble): %s", strerror(errno));
+ if (g->done) g->done(g, errno, g->p);
gobbler_close(g);
break;
}
} else if (n == 0) {
gobbler_close(g);
break;
}
} else if (n == 0) {
+ if (g->done) g->done(g, 0, g->p);
gobbler_close(g);
break;
}
}
}
gobbler_close(g);
break;
}
}
}
-static gobbler *make_gobbler(int fd)
+static gobbler *make_gobbler(int fd,
+ void (*done)(gobbler *, int, void *),
+ void *p)
{
gobbler *g;
g = CREATE(gobbler);
{
gobbler *g;
g = CREATE(gobbler);
+ g->done = done;
+ g->p = p;
sel_initfile(&sel, &g->f, fd, SEL_READ, do_gobble_in, g);
sel_addfile(&g->f);
do_gobble_in(fd, SEL_READ, g);
sel_initfile(&sel, &g->f, fd, SEL_READ, do_gobble_in, g);
sel_addfile(&g->f);
do_gobble_in(fd, SEL_READ, g);
break;
case '<':
w = CREATE(waiter);
break;
case '<':
w = CREATE(waiter);
- w->g = make_gobbler(fd);
+ w->g = make_gobbler(fd, 0, 0);
w->next = 0;
w->fd = fd;
*wait_tail = w;
w->next = 0;
w->fd = fd;
*wait_tail = w;