commit 1969331400e4c56373c16ec5cfcbd9aaceb069a8
parent a8f47feea9525af8d8e402f83443d6b74f155b20
Author: Antoine Amarilli <a3nm@a3nm.net>
Date: Mon, 18 Jun 2012 14:52:07 +0200
work on fifo_set, doesnotwork
Diffstat:
TODO | | | 7 | +++++++ |
irctk.c | | | 612 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
2 files changed, 434 insertions(+), 185 deletions(-)
diff --git a/TODO b/TODO
@@ -1,5 +1,12 @@
+debug cat fifo | while read l; do seq 3; done | ./irctk -Fvfr 127.0.0.1 \#test > fifo
+maybe debug fifo_set separately
+
http://www.iagora.com/~espel/sirc/sirc.html
handle nick following
ssl support
password support
exit when killed, advertising the signal
+use notices and errors
+si on est full unbuffered, attendre qu'un write sur stdout ait fini de
+bloquer avant de considérer que le write a été vu pour last_nick et autres
+sinon, vérifier que le delimit par lignes vides est opérationnel
diff --git a/irctk.c b/irctk.c
@@ -32,6 +32,8 @@ enum event_tos {NOTHING, COMMAND, MESSAGE};
#define MAX_NICK_LEN 4096
#define LINE_BUFFER 4096
+#define INITIAL_CHAN_ALLOC 2
+
#define max(a, b) ((b) > (a) ? (b) : (a))
const char *argp_program_version = "irctk 0.1";
@@ -165,7 +167,7 @@ struct arguments
int port;
char *password;
char **channels;
- int n_channels;
+ int n_channels; // TODO reconcile this with fifos
int verbosity;
@@ -449,20 +451,78 @@ void debug_args()
typedef struct line {
- char* line;
- char last_chan_in[MAX_LEN];
- char last_chans_out[MAX_LEN];
- char last_nick_in[MAX_LEN];
+ char *line;
+ char *full_line;
+ struct line* next_dep;
+ char is_head;
+ char is_sendable;
} line;
+typedef struct action {
+ char *line;
+ char *full_line;
+ char *destination;
+} action;
+
typedef struct fifo {
int hd;
int tl;
line queue[LINE_BUFFER];
+} fifo;
+
+typedef struct fifo_ctrl {
pthread_cond_t empty;
pthread_cond_t full;
pthread_mutex_t mutex;
-} fifo;
+} fifo_ctrl;
+
+typedef struct fifo_set {
+ int n;
+ int allocated;
+ fifo_ctrl ctrl;
+ fifo *fifos;
+ char **chans;
+ char *was_pushed;
+} fifo_set;
+
+void init_fifo_ctrl(fifo_ctrl *c) {
+ assert(!pthread_cond_init(&(c->empty), NULL));
+ assert(!pthread_cond_init(&(c->full), NULL));
+ assert(!pthread_mutex_init(&(c->mutex), NULL));
+}
+
+void init_fifo_set (fifo_set *s) {
+ s->n = 0;
+ s->allocated = INITIAL_CHAN_ALLOC;
+ s->chans = malloc(s->allocated * sizeof(char*));
+ assert(s->chans);
+ s->fifos = malloc(s->allocated * sizeof(fifo));
+ assert(s->fifos);
+ s->was_pushed = malloc(s->allocated * sizeof(char));
+ assert(s->was_pushed);
+ init_fifo_ctrl(&(s->ctrl));
+}
+
+void destroy_fifo_ctrl(fifo_ctrl *f) {
+ pthread_cond_destroy(&f->empty);
+ pthread_cond_destroy(&f->full);
+ pthread_mutex_destroy(&f->mutex);
+}
+
+void destroy_fifo_set (fifo_set *s) {
+ int i;
+ free(s->fifos);
+ for (i = 0; i < s->n ; i++)
+ free(s->chans[i]);
+ free(s->chans);
+ free(s->was_pushed);
+ destroy_fifo_ctrl(&(s->ctrl));
+}
+
+void init_fifo(fifo *f) {
+ f->hd = 0;
+ f->tl = 0;
+}
int size(fifo *f) {
return (f->tl - f->hd + LINE_BUFFER) % LINE_BUFFER;
@@ -470,84 +530,282 @@ int size(fifo *f) {
int full(fifo *f) {
return size(f) == LINE_BUFFER - 1;
}
+int full_fifo_set(fifo_set *s) {
+ // fifo_set is full if one fifo is full
+ int i;
+ for (i=0; i<s->n; i++)
+ if (full(&(s->fifos[i])))
+ return 1;
+ return 0;
+}
int empty(fifo *f) {
return size(f) == 0;
}
+int empty_fifo_set(fifo_set *s) {
+ // fifo_set is empty if all fifos are empty
+ int i;
+ for (i=0; i<s->n; i++)
+ if (!empty(&(s->fifos[i])))
+ return 0;
+ return 1;
+}
-line pop(fifo *f) {
- line result;
- int was_full;
- pthread_mutex_lock(&f->mutex);
- debug("am popping, hd %d tl %d size %d", f->hd, f->tl, size(f));
- while (empty(f)) {
- debug("wait nonempty");
- pthread_cond_wait(&f->empty, &f->mutex);
+// line pop(fifo *f, fifo_ctrl *c) {
+// line result;
+// int was_full;
+// pthread_mutex_lock(&c->mutex);
+// debug("am popping, hd %d tl %d size %d", f->hd, f->tl, size(f));
+// while (empty(f)) {
+// debug("wait nonempty");
+// pthread_cond_wait(&c->empty, &c->mutex);
+// }
+// debug("nonempty");
+// // now fifo isn't empty
+// was_full = full(f);
+// result = f->queue[f->hd];
+// debug("state POP 0:%s 1:%s 2:%s 3:%s 4:%s\n",
+// f->queue[0].line,
+// f->queue[1].line,
+// f->queue[2].line,
+// f->queue[3].line,
+// f->queue[4].line
+// );
+// debug("popped %s at %d", result.line, f->hd);
+// f->hd++;
+// f->hd %= LINE_BUFFER;
+// if (was_full)
+// pthread_cond_signal(&c->full);
+// pthread_mutex_unlock(&c->mutex);
+// return result;
+// }
+//
+// void push(fifo *f, fifo_ctrl *c, char *fl, char *dest, char *l) {
+// int was_empty;
+// pthread_mutex_lock(&c->mutex);
+// debug("am pushing, hd %d tl %d size %d", f->hd, f->tl, size(f));
+// while (full(f))
+// pthread_cond_wait(&c->full, &c->mutex);
+// // now fifo isn't full
+// was_empty = empty(f);
+// f->queue[f->tl].line = l;
+// f->queue[f->tl].full_line = fl;
+// debug("pushed %s at %d\n", l, f->tl);
+// debug("state PUSH 0:%s 1:%s 2:%s 3:%s 4:%s\n",
+// f->queue[0].line,
+// f->queue[1].line,
+// f->queue[2].line,
+// f->queue[3].line,
+// f->queue[4].line
+// );
+// f->tl++;
+// f->tl %= LINE_BUFFER;
+// if (was_empty)
+// pthread_cond_signal(&c->empty);
+// pthread_mutex_unlock(&c->mutex);
+// }
+
+void realloc_chans(fifo_set *s) {
+ s->allocated *= 2;
+ assert(!realloc(s->chans, s->allocated*sizeof(char*)));
+ assert(!realloc(s->was_pushed, s->allocated*sizeof(char*)));
+ assert(!realloc(s->fifos, s->allocated*sizeof(fifo*)));
+}
+
+int push_chan(fifo_set *s, char *chan) {
+ if (s->n == s->allocated)
+ realloc_chans(s);
+ s->chans[s->n] = malloc(MAX_LEN * sizeof(chan));
+ assert(s->chans[s->n]);
+ strncpy(s->chans[s->n], chan, MAX_LEN-1);
+ init_fifo(&s->fifos[s->n]);
+ s->was_pushed[s->n] = 0;
+ return (s->n)++;
+}
+
+int index_of_chan(fifo_set *s, char *chan) {
+ int i;
+ debug("asking for ioc for <%s>", chan);
+ for (i=0; i<s->n; i++) {
+ debug("compare to %d of %d value %s", i, s->n, s->chans[i]);
+ if (!strcmp(s->chans[i], chan)) {
+ debug("found ioc %d", i);
+ return i;
+ }
}
- debug("nonempty");
- // now fifo isn't empty
- was_full = full(f);
- result = f->queue[f->hd];
- /*debug("state 0:%s 1:%s 2:%s 3:%s 4:%s\n",
- f->queue[0].line,
- f->queue[1].line,
- f->queue[2].line,
- f->queue[3].line,
- f->queue[4].line
- );*/
- debug("popped %s at %d", result.line, f->hd);
- f->hd++;
- f->hd %= LINE_BUFFER;
- if (was_full)
- pthread_cond_signal(&f->full);
- pthread_mutex_unlock(&f->mutex);
- return result;
+ debug("must push");
+ return push_chan(s, chan);
}
-void push(fifo *f, char* l, char* li, char* lni, char* lo) {
- int was_empty;
- pthread_mutex_lock(&f->mutex);
- while (full(f))
- pthread_cond_wait(&f->full, &f->mutex);
- // now fifo isn't full
- was_empty = empty(f);
+
+line *push_one(fifo_set *s, char *fl, char *dest, char *l, line *last_ptr) {
+ int c = index_of_chan(s, dest);
+ debug("push_one %s %p ioc %d", fl, last_ptr, c);
+ fifo *f = &(s->fifos[c]);
+ line *result = &f->queue[f->tl];
+ if (s->was_pushed[c])
+ return last_ptr; // already pushed
+ s->was_pushed[c] = 1;
f->queue[f->tl].line = l;
- strncpy(f->queue[f->tl].last_chan_in, li, MAX_LEN-1);
- strncpy(f->queue[f->tl].last_nick_in, lni, MAX_LEN-1);
- strncpy(f->queue[f->tl].last_chans_out, lo, MAX_LEN-1);
- debug("pushed %s at %d\n", l, f->tl);
- /*debug("state 0:%s 1:%s 2:%s 3:%s 4:%s\n",
- f->queue[0].line,
- f->queue[1].line,
- f->queue[2].line,
- f->queue[3].line,
- f->queue[4].line
- );*/
+ f->queue[f->tl].full_line = fl;
+ f->queue[f->tl].next_dep = last_ptr;
+ f->queue[f->tl].is_head = 0;
+ f->queue[f->tl].is_sendable = 0;
f->tl++;
f->tl %= LINE_BUFFER;
- if (was_empty)
- pthread_cond_signal(&f->empty);
- pthread_mutex_unlock(&f->mutex);
+ return result;
}
-void init(fifo *f) {
- f->hd = 0;
- f->tl = 0;
- assert(!pthread_cond_init(&f->empty, NULL));
- assert(!pthread_cond_init(&f->full, NULL));
- assert(!pthread_mutex_init(&f->mutex, NULL));
+void set_last_ptr(fifo_set *s, char *chan, line *ptr) {
+ int c = index_of_chan(s, chan);
+ fifo *f = &(s->fifos[c]);
+ debug("set_last_ptr %p for %s ioc %d", ptr, f->queue[f->tl - 1 + LINE_BUFFER % LINE_BUFFER].full_line, c);
+ f->queue[f->tl - 1 + LINE_BUFFER % LINE_BUFFER].next_dep = ptr;
}
-void destroy(fifo *f) {
- pthread_cond_destroy(&f->empty);
- pthread_cond_destroy(&f->full);
- pthread_mutex_destroy(&f->mutex);
+void reset_chan_marks(fifo_set *s) {
+ int i;
+ for (i=0; i<s->n; i++)
+ s->was_pushed[i] = 0;
+}
+
+void push_fifo_set(fifo_set *s, char *fl, char *dests, char *l) {
+ debug("push_fifo_set %s", fl);
+ int was_empty;
+ pthread_mutex_lock(&s->ctrl.mutex);
+ while (full_fifo_set(s))
+ pthread_cond_wait(&s->ctrl.full, &s->ctrl.mutex);
+ // now fifo_set isn't full
+
+ int i = 0;
+ int cont = 1;
+ char *last_dest, *first_dest;
+ line *last_ptr = 0, *first_ptr = 0;
+
+ last_dest = dests;
+
+ reset_chan_marks(s);
+ was_empty = empty_fifo_set(s);
+ while (cont)
+ {
+ if (dests[i] == ',' || !dests[i])
+ {
+ if (!dests[i])
+ cont = 0;
+ if (i)
+ dests[i] = 0;
+ // only put the full line for *one* occurrence
+ last_ptr = push_one(s, !first_ptr?fl:NULL, last_dest, l, last_ptr);
+ assert(!cont);
+ if (!first_ptr) {
+ first_ptr = last_ptr;
+ first_dest = last_dest;
+ debug("first_ptr is %p full line %s, first_dest is %s", first_ptr,
+ first_ptr->full_line, first_dest);
+ }
+ last_dest = dests + i + 1;
+ }
+ i++;
+ }
+ debug("first_ptr is %p full line %s, first_dest is %s", first_ptr,
+ first_ptr->full_line, first_dest);
+ set_last_ptr(s, first_dest, first_ptr);
+
+ if (was_empty) {
+ debug("signal for empty");
+ pthread_cond_signal(&s->ctrl.empty);
+ }
+ pthread_mutex_unlock(&s->ctrl.mutex);
+}
+
+void mark_head(fifo *f) {
+ f->queue[f->hd].is_head = 1;
+ f->queue[f->hd].is_sendable = 0;
+}
+
+void mark_heads(fifo_set *s) {
+ int i;
+ for (i=0; i<s->n; i++)
+ mark_head(&s->fifos[i]);
+}
+
+int mark_sendable_line(line *l) {
+ if (!l->is_head)
+ return 0;
+ if (l->is_sendable)
+ return 1;
+ l->is_sendable = 1;
+ // TODO TODO TODO lift this when we have real deps
+ debug("i am %p depending on %p", l, l->next_dep);
+ assert(l->next_dep == l);
+ return mark_sendable_line(l->next_dep);
+}
+int mark_sendable(fifo *f) {
+ return mark_sendable_line(&f->queue[f->hd]);
+}
+void unmark_sendable_line(line *l) {
+ if (!l->is_sendable)
+ return;
+ l->is_sendable = 0;
+ unmark_sendable_line(l->next_dep);
+}
+void unmark_sendable(fifo *f) {
+ unmark_sendable_line(&f->queue[f->hd]);
+}
+void pop_if_sendable(fifo_set *s, int c, int *n_result, action *result) {
+ fifo *f = &s->fifos[c];
+ // don't push sentinel
+ if (f->queue[f->hd].is_sendable && f->queue[f->hd].line) {
+ result[*n_result].line = f->queue[f->hd].line;
+ result[*n_result].full_line = f->queue[f->hd].full_line;
+ result[*n_result].destination = s->chans[c];
+ (*n_result)++;
+ f->hd++;
+ f->hd %= LINE_BUFFER;
+ }
+}
+
+int pop_fifo_set(fifo_set *s, action **result) {
+ int n_result = 0;
+ int was_full;
+ int i;
+ pthread_mutex_lock(&s->ctrl.mutex);
+ while (empty_fifo_set(s)) {
+ debug("wait because empty");
+ pthread_cond_wait(&s->ctrl.empty, &s->ctrl.mutex);
+ }
+ // now fifo isn't empty
+ debug("now fifo isn't empty");
+ was_full = full_fifo_set(s);
+ mark_heads(s);
+ for (i=0; i<s->n; i++) {
+ debug("doing fifo for chan %s", s->chans[i]);
+ debug("fifo hd %d tl %d", s->fifos[i].hd, s->fifos[i].tl);
+ if (!mark_sendable(&s->fifos[i]))
+ unmark_sendable(&s->fifos[i]);
+ }
+ // freeing result is responsibility of callee
+ *result = malloc(s->n * sizeof(line));
+ assert(*result);
+ for (i=0; i<s->n; i++)
+ pop_if_sendable(s, i, &n_result, *result);
+ if (!n_result) {
+ // only thing left is sentinel, return sentinel
+ n_result = 1;
+ result[0]->line = NULL;
+ result[0]->full_line = NULL;
+ }
+ debug("prepared %d results to return", n_result);
+ if (was_full)
+ pthread_cond_signal(&s->ctrl.full);
+ pthread_mutex_unlock(&s->ctrl.mutex);
+ return n_result;
}
// fifo for input
// we want to read lines at the time we get them even if we are delaying writes
// on the irc channel
/* TODO fifo_out for output to avoid blocking if stdout blocks */
-fifo fifo_in;
+fifo_set fifos;
/* Our main chan is either the first CLI chan or our own chan if there are no
@@ -650,89 +908,56 @@ int do_cmd_msg(irc_session_t *s, char* chan, char* line)
return 0;
}
-// Send a message or do a command, possibly to multiple chans
-int cmd_msg_chan(irc_session_t *s, char *target, char* line)
-{
- int i = 0;
- int cont = 1;
- char tmp;
- char *one_target;
- int rsl = 0;
-
- debug("cmd_msg_chan %s %s\n", target, line);
- one_target = target;
-
- while (cont)
- {
- if (target[i] == ',' || !target[i])
- {
- if (!target[i])
- cont = 0;
- tmp = target[i];
- target[i] = 0;
- // return value is the max of seen return values, ie. some kind of "or"
- rsl = max(rsl, do_cmd_msg(s, one_target, line));
- target[i] = tmp;
- one_target = target + i + 1;
- }
- i++;
- }
-
- return rsl;
-}
-
// Handle a command request which might not specify a destination
-int cmd_msg(irc_session_t *s, char* target, line l)
+void cmd_msg(char *full_line, char *target, char *line)
{
int i = 0;
- int ret;
char *msg[2*MAX_LEN+2];
- debug("cmd_msg %s %s, last_in %s", target, l.line, l.last_chan_in);
+ debug("cmd_msg %s %s, last_in %s", target, line, args.last_chan_in);
/* Manage the fact that target may be "" */
- if (!target[0])
- {
- switch(args.default_destination)
- {
+ if (!target[0]) {
+ debug("have to infer destination\n");
+ switch(args.default_destination) {
case DEFAULT_FIRST:
- return cmd_msg_chan(s, first_chan(), l.line);
+ push_fifo_set(&fifos, full_line, first_chan(), line);
+ return;
case DEFAULT_LAST_IN:
- if (args.show_nick_prefix && l.last_nick_in[0]
- && l.last_chan_in[0] == '#')
- {
- if (l.line[0] != '\n')
- {
+ if (args.show_nick_prefix && args.last_nick_in[0]
+ && args.last_chan_in[0] == '#') {
+ if (line[0] != '\n') {
msg[0] = 0;
- strncat((char*) msg, l.last_nick_in, MAX_LEN-1);
+ strncat((char*) msg, args.last_nick_in, MAX_LEN-1);
strcat((char*) msg, ": ");
- strncat((char*) msg, l.line, MAX_LEN-1);
- l.line = (char*) msg;
+ strncat((char*) msg, line, MAX_LEN-1);
+ line = (char*) msg;
} else {
- l.last_nick_in[0] = 0;
+ args.last_nick_in[0] = 0;
}
}
- debug("will cmd_msg_chan %s %s\n", l.last_chan_in, l.line);
- return cmd_msg_chan(s, l.last_chan_in, l.line);
+ debug("last_chan_in is %s", args.last_chan_in);
+ return push_fifo_set(&fifos, full_line,
+ args.last_chan_in[0] ? args.last_chan_in : first_chan(), line);
case DEFAULT_LAST_OUT:
- return cmd_msg_chan(s, l.last_chans_out, l.line);
+ return push_fifo_set(&fifos, full_line,
+ args.last_chans_out[0] ? args.last_chans_out : first_chan(), line);
case DEFAULT_ALL:
//TODO also for chans joined at runtime
//TODO2: ugly, could have generated the comma-separated string
//like for last_chans_out!
for (i = 0; i < args.n_channels; i++)
- ret = max(ret, cmd_msg_chan(s, args.channels[i], l.line));
+ push_fifo_set(&fifos, full_line, args.channels[i], line);
/* TODO return value */
- return ret;
default:
- return 42; // won't happen
+ return; // won't happen
}
} else {
- return cmd_msg_chan(s, target, l.line);
+ push_fifo_set(&fifos, full_line, target, line);
}
}
@@ -740,7 +965,6 @@ int cmd_msg(irc_session_t *s, char* target, line l)
void manage_event (irc_session_t *session, const char *event, const char *origin,
const char **params, unsigned int count)
{
- int cnt = 0;
int rsl; // TODO use
if (atoi(event) == LIBIRC_RFC_ERR_ERRONEUSNICKNAME)
@@ -778,8 +1002,14 @@ void manage_event (irc_session_t *session, const char *event, const char *origin
info("Cannot join channel: channel is invite-only.");
}
- debug("Event \"%s\", origin: \"%s\", params: %d", event,
- origin ? origin : "NULL", cnt);
+ if (count == 2) {
+ debug("%s %s: %s %s\n", origin, event, params[0], params[1]);
+ } else if (count == 1) {
+ debug("%s %s: %s\n", origin, event, params[0]);
+ } else {
+ debug("Event \"%s\", origin: \"%s\", params: %d", event,
+ origin ? origin : "NULL", count);
+ }
}
// Handle a nick event
@@ -895,9 +1125,12 @@ void event_channel (irc_session_t *session, const char *event,
if (strcmp(params[0], args.nick))
{
for (i=0; i<strlen(args.nick); i++)
- if (args.nick[i] != params[1][i] || !params[1][i])
+ if (args.nick[i] != params[1][i] || !params[1][i]) {
ok = 0;
- /* TODO test if ',' or ':' to avoid prefix nicks */
+ break;
+ }
+ /* TODO test that the address ends with ',', ':', ' ',
+ * otherwise prefix nicks can match */
}
if (ok) {
@@ -1025,18 +1258,44 @@ static void* irc_thread (void *arg)
static void* fifo_in_thread (void *arg) {
char *line = NULL;
int res, size=100;
- line = (char*) malloc(size+1);
+ line = malloc(size+1);
+ assert(line);
while ((res = getline((char**) &line, (size_t*) &size, stdin)) != -1) {
- debug("i read and push %s\n", line);
- push(&fifo_in, line, args.last_chan_in, args.last_nick_in,
- args.last_chans_out);
+ debug("in_thread reads %s", line);
+ debug("i need to free %p", line);
+ if (line[0] == '[' && args.destination_prefix)
+ {
+ int i=0;
+ char *msg;
+ char *target = line+1;
+ if (!line[0])
+ target = NULL;
+
+ while (line[i] != ']' && line[i])
+ i++;
+ if (!line[i])
+ die(E_BADLINE, "Malformed address prefix");
+ msg = line + i + 1;
+ if (msg[0] == ' ')
+ msg++;
+ if (i)
+ line[i] = 0;
+ cmd_msg(line, target, msg);
+ strncpy(args.last_chans_out, target, MAX_LEN-1);
+ } else {
+ /* No target specified, we attempt the default */
+ cmd_msg(line, "", line);
+ }
+
// reallocate line, the popper will free the line
- line = (char*) malloc(size+1);
+ line = malloc(size+1);
+ assert(line);
}
// sentinel
- push(&fifo_in, NULL, NULL, NULL, NULL);
- free(line);
+ debug("[thread_in] pushed sentinel");
+ push_fifo_set(&fifos, NULL, "", NULL);
+ free(line); // which wasn't used
return 0;
}
@@ -1046,17 +1305,16 @@ int start (int max_wait)
{
irc_session_t * s;
pthread_t tid_irc, tid_in;
- line l;
- struct timeval tp1, tp2;
- long tp;
- int first = 1;
+ int i;
int waiting = 0;
+ int cont = 1;
+ action *results;
+ int n_results;
s = do_connect();
debug("Connection request successful!");
- debug("hd %d tl %d\n", fifo_in.hd, fifo_in.tl);
debug("Starting threads...");
if (pthread_create (&tid_irc, 0, irc_thread, (void*) s) != 0)
die(E_THREAD, "Could not create thread: %s", strerror(errno));
@@ -1068,7 +1326,7 @@ int start (int max_wait)
if (args.show_inferred && args.default_destination == DEFAULT_LAST_OUT)
fprintf(stderr, "[%s] ", args.last_chans_out);
- gettimeofday(&tp1, NULL);
+ //gettimeofday(&tp1, NULL);
if (!args.ready) {
waiting = 0;
@@ -1090,65 +1348,49 @@ int start (int max_wait)
}
}
- // initialize last_chan_in and last_chan_out
- strncpy(args.last_chan_in, first_chan(), MAX_LEN-1);
- strncpy(args.last_chans_out, first_chan(), MAX_LEN-1);
-
- while ((l = pop(&fifo_in)).line) {
- debug("startloop : got %s, waiting", l.line);
- if (!args.ready) {
+ debug("[main] Starting loop");
+ while (cont) {
+ n_results = pop_fifo_set(&fifos, &results);
+ debug("[main] I popped %d results", n_results);
+ for (i = 0; i < n_results; i++) {
+ if (!results[i].line) {
+ debug("[main] Sentinel seen, we will exit");
+ cont = 0; // sentinel
+ } else {
+ debug("[main] manage line %s %s, pointer %p",
+ results[i].destination, results[i].line, results[i].full_line );
+ do_cmd_msg(s, results[i].destination, results[i].line);
+ }
+ }
+ // now, we free stuff
+ for (i = 0; i < n_results; i++)
+ if (results[i].full_line)
+ free(results[i].full_line);
+ debug("[main] I managed my lines");
+ if (cont && !args.ready) {
info("Connection lost, reconnecting...");
return start(max_wait);
}
- debug("ready", l.line);
-
/* TODO no wait on empty lines */
/* TODO separate delay per channel */
- gettimeofday(&tp2, NULL);
- tp = 1000000*(tp2.tv_sec - tp1.tv_sec) + tp2.tv_usec - tp1.tv_usec;
- if (tp < args.interval && !first)
- usleep(args.interval - tp);
- first = 0;
-
- if (l.line[0] == '[' && args.destination_prefix)
- {
- int i=0;
- char *msg;
- char *tmp;
- char *target = l.line+1;
- if (!l.line[0])
- target = NULL;
-
- while (l.line[i] != ']' && l.line[i])
- i++;
- if (!l.line[i])
- die(E_BADLINE, "Malformed address prefix");
- msg = l.line + i + 1;
- if (msg[0] == ' ')
- msg++;
- l.line[i] = 0;
- tmp = l.line;
- l.line = msg;
- cmd_msg(s, target, l);
- l.line = tmp;
- strncpy(l.last_chans_out, target, MAX_LEN-1);
- } else {
- /* No target specified, we attempt the default */
- cmd_msg(s, "", l);
- }
+ // gettimeofday(&tp2, NULL);
+ // tp = 1000000*(tp2.tv_sec - tp1.tv_sec) + tp2.tv_usec - tp1.tv_usec;
+ // if (tp < args.interval && !first)
+ // usleep(args.interval - tp);
+ // first = 0;
if (args.show_inferred && args.default_destination == DEFAULT_LAST_OUT)
- fprintf(stderr, "[%s] ", l.last_chans_out);
- usleep(args.interval);
+ fprintf(stderr, "[%s] ", args.last_chans_out);
+
+ if (cont)
+ usleep(args.interval);
- debug("endloop");
- free(l.line);
+ debug("[main] endloop");
}
- debug("exiting");
+ debug("[main] exiting");
- usleep(2*args.interval);
irc_disconnect(s);
return 0;
@@ -1163,7 +1405,7 @@ int main (int argc, char **argv)
argp_parse (&argp, argc, argv, 0, 0, &args);
// initialize the fifo
- init(&fifo_in);
+ init_fifo_set(&fifos);
// start trying to connet with the initial retry interval
return start(args.retry_after);