sacc

sacc (saccomys): simple gopher client.
Log | Files | Refs | LICENSE

commit 3d6d241ad7c59d1a99810bd3193faa6dadd2ecf8
parent f774b7e9a296259d812a8de8066e777877e67061
Author: Quentin Rameau <quinq@fifth.space>
Date:   Fri, 23 Jun 2017 20:37:27 +0200

Better error handling, add an item parsing function

Diffstat:
sacc.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 66 insertions(+), 33 deletions(-)

diff --git a/sacc.c b/sacc.c @@ -192,34 +192,63 @@ display(Item *item) } char * -pickfield(char **s) +pickfield(char **raw, char sep) { - char *c, *f = *s; + char *c, *f = *raw; - /* loop until we reach the end of the string, or a tab, or CRLF */ - for (c = *s; *c; ++c) { + for (c = *raw; *c != sep; ++c) { switch (*c) { case '\t': - break; - case '\r': /* FALLTHROUGH */ - if (*(c+1) == '\n') { - *c++ = '\0'; - break; - } + if (sep == '\r') + *c = '\0'; + case '\n': + case '\r': + case '\0': + return NULL; default: continue; } break; } - if (!*c) - die("Can't parse directory item: %s", f); *c = '\0'; - *s = c+1; + *raw = c+1; return f; } +Item * +molditem(char **raw) +{ + Item *item; + char type, *username, *selector, *host, *port; + + if (!*raw) + return NULL; + + if (!(type = *raw[0]++) || + !(username = pickfield(raw, '\t')) || + !(selector = pickfield(raw, '\t')) || + !(host = pickfield(raw, '\t')) || + !(port = pickfield(raw, '\r')) || + *raw[0]++ != '\n') + return NULL; + + item = xmalloc(sizeof(Item)); + + item->type = type; + item->username = username; + item->selector = selector; + item->host = host; + item->port = port; + item->raw = NULL; + item->dir = NULL; + item->entry = NULL; + item->printoff = 0; + + return item; +} + Dir * molddiritem(char *raw) { @@ -233,27 +262,25 @@ molddiritem(char *raw) if (--nitems < 1) return NULL; if (strcmp(crlf-3, ".\r\n")) - return NULL; + fprintf(stderr, "Parsing error: missing .\\r\\n last line\n"); dir = xmalloc(sizeof(Dir)); items = xreallocarray(items, nitems, sizeof(Item*)); for (i = 0; i < nitems; ++i) { - item = xmalloc(sizeof(Item)); - - item->type = *raw++; - item->username = pickfield(&raw); - item->selector = pickfield(&raw); - item->host = pickfield(&raw); - item->port = pickfield(&raw); - item->printoff = 0; - item->raw = NULL; - item->entry = NULL; - item->dir = NULL; - - items[i] = item; + if (item = molditem(&raw)) { + items[i] = item; + } else { + fprintf(stderr, "Parsing error: dir entity: %d\n", i+1); + items = xreallocarray(items, i, sizeof(Item*)); + nitems = i; + break; + } } + if (!items) + return NULL; + dir->items = items; dir->nitems = nitems; @@ -349,29 +376,35 @@ dig(Item *entry, Item *item) { int sock; - if (item->raw) /* already in cache */ + if (item->raw) /* already in cache */ return 1; if (!item->entry) item->entry = entry; - if (item->type > '1') /* not supported */ + if (item->type > '1') { + fprintf(stderr, "Type %c not supported\n", item->type); return 0; + } sock = connectto(item->host, item->port); sendselector(sock, item->selector); item->raw = getrawitem(sock); close(sock); - if (!*item->raw) { /* empty read */ + if (!*item->raw) { + fputs("Empty response from server\n", stderr); free(item->raw); item->raw = NULL; return 0; } - if (item->type == '1' && - !(item->dir = molddiritem(item->raw))) - return 0; + if (item->type == '1') { + if (!(item->dir = molddiritem(item->raw))) { + fputs("Couldn't parse dir item\n", stderr); + return 0; + } + } return 1; }