sacc

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

commit fdae99f75651ec33854a55654887608fb4f2947c
parent 4dff6dde00bd2e8062f678d6ca2207d00119474f
Author: Quentin Rameau <quinq@fifth.space>
Date:   Fri,  7 Jul 2017 15:16:30 +0200

Handle (hopefuly) all invalid format streams

Diffstat:
sacc.c | 112+++++++++++++++++++++++++++++++++++++++----------------------------------------
ui_ti.c | 37+++++++++++++++++++------------------
ui_txt.c | 23++++++++++-------------
3 files changed, 84 insertions(+), 88 deletions(-)

diff --git a/sacc.c b/sacc.c @@ -57,6 +57,17 @@ xmalloc(const size_t n) return m; } +static void * +xcalloc(size_t n) +{ + char *m = xmalloc(n); + + while (n) + m[--n] = 0; + + return m; +} + static char * xstrdup(const char *str) { @@ -147,20 +158,8 @@ pickfield(char **raw, char sep) { char *c, *f = *raw; - for (c = *raw; *c != sep; ++c) { - switch (*c) { - case '\t': - if (sep == '\r') - *c = '\0'; - case '\n': - case '\r': - case '\0': - return NULL; - default: - continue; - } - break; - } + for (c = *raw; *c && *c != sep; ++c) + ; *c = '\0'; *raw = c+1; @@ -168,35 +167,47 @@ pickfield(char **raw, char sep) return f; } +static char * +invaliditem(char *raw) +{ + char c; + int tabs; + + for (tabs = 0; (c = *raw) && c != '\n'; ++raw) { + if (c == '\t') + ++tabs; + } + if (c) + *raw++ = '\0'; + + return (tabs == 3) ? NULL : raw; +} + static Item * molditem(char **raw) { Item *item; - char type, *username, *selector, *host, *port; + char *next; 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 = xcalloc(sizeof(Item)); - item = xmalloc(sizeof(Item)); + if ((next = invaliditem(*raw))) { + item->type = 'i'; + item->username = *raw; + *raw = next; + return 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; - item->curline = 0; + item->type = *raw[0]++; + item->username = pickfield(raw, '\t'); + item->selector = pickfield(raw, '\t'); + item->host = pickfield(raw, '\t'); + item->port = pickfield(raw, '\r'); + if (!*raw[0]) + ++*raw; return item; } @@ -204,38 +215,25 @@ molditem(char **raw) static Dir * molddiritem(char *raw) { - Item *item, **items = NULL; - char *crlf, *p; + Item **items = NULL; + char *s, *nl, *p; Dir *dir; size_t i, nitems; - for (crlf = raw, nitems = 0; p = strstr(crlf, "\r\n"); ++nitems) - crlf = p+2; - if (nitems <= 1) - return NULL; - if (!strcmp(crlf-3, ".\r\n")) + for (s = nl = raw, nitems = 0; p = strchr(nl, '\n'); ++nitems) { + s = nl; + nl = p+1; + } + if (!strcmp(s, ".\r\n") || !strcmp(s, ".\n")) --nitems; - else - fprintf(stderr, "Parsing error: missing .\\r\\n last line\n"); + if (!nitems) + return NULL; dir = xmalloc(sizeof(Dir)); items = xreallocarray(items, nitems, sizeof(Item*)); - for (i = 0; i < nitems; ++i) { - 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) { - free(dir); - return NULL; - } + for (i = 0; i < nitems; ++i) + items[i] = molditem(&raw); dir->items = items; dir->nitems = nitems; diff --git a/ui_ti.c b/ui_ti.c @@ -57,7 +57,7 @@ help(void) static void displaystatus(Item *item) { - size_t nitems = item->dir->nitems; + size_t nitems = item->dir ? item->dir->nitems : 0; putp(tparm(save_cursor)); @@ -75,13 +75,18 @@ displaystatus(Item *item) void display(Item *entry) { - Item *item, **items; + Item **items; size_t i, curln, lastln, nitems, printoff; if (entry->type != '1') return; putp(tparm(clear_screen)); + displaystatus(entry); + + if (!entry->dir) + return; + putp(tparm(save_cursor)); items = entry->dir->items; @@ -91,22 +96,19 @@ display(Item *entry) lastln = printoff + lines-1; /* one off for status bar */ for (i = printoff; i < nitems && i < lastln; ++i) { - if (item = items[i]) { - if (i != printoff) - putp(tparm(cursor_down)); - if (i == curln) { - putp(tparm(save_cursor)); - putp(tparm(enter_standout_mode)); - } - printitem(item); - putp(tparm(column_address, 0)); - if (i == curln) - putp(tparm(exit_standout_mode)); + if (i != printoff) + putp(tparm(cursor_down)); + if (i == curln) { + putp(tparm(save_cursor)); + putp(tparm(enter_standout_mode)); } + printitem(items[i]); + putp(tparm(column_address, 0)); + if (i == curln) + putp(tparm(exit_standout_mode)); } putp(tparm(restore_cursor)); - displaystatus(entry); fflush(stdout); } @@ -166,8 +168,7 @@ movecurline(Item *item, int l) Item * selectitem(Item *entry) { - Item *hole; - int item, nitems; + Dir *dir = entry->dir; for (;;) { switch (getchar()) { @@ -199,8 +200,8 @@ selectitem(Item *entry) case _key_pgnext: case '\r': pgnext: - if (entry->dir->items[entry->curline]->type < '2') - return entry->dir->items[entry->curline]; + if (dir) + return dir->items[entry->curline]; continue; case _key_lndown: lndown: diff --git a/ui_txt.c b/ui_txt.c @@ -54,7 +54,7 @@ ndigits(size_t n) static void printstatus(Item *item) { - size_t nitems = item->dir->nitems; + size_t nitems = item->dir ? item->dir->nitems : 0; printf("%3lld%%%*c %s:%s%s (h for help): ", (item->printoff + lines >= nitems) ? 100 : @@ -65,11 +65,11 @@ printstatus(Item *item) void display(Item *entry) { - Item *item, **items; + Item **items; size_t i, lines, nitems; int nd; - if (entry->type != '1') + if (entry->type != '1' || !entry->dir) return; items = entry->dir->items; @@ -78,15 +78,12 @@ display(Item *entry) nd = ndigits(nitems); for (i = entry->printoff; i < nitems && i < lines; ++i) { - if (item = items[i]) { - printf("%*zu %-4s%c %s\n", nd, i+1, - item->type != 'i' ? - typedisplay(item->type) : "", - item->type > '1' ? '|' : '+', - items[i]->username); - } else { - printf("%*zu !! |\n", nd, i+1); - } + item = items[i]; + printf("%*zu %-4s%c %s\n", nd, i+1, + item->type != 'i' ? + typedisplay(item->type) : "", + item->type > '1' ? '|' : '+', + item->username); } fflush(stdout); @@ -113,7 +110,7 @@ selectitem(Item *entry) if (!strcmp(buf, "n\n")) { lines = termlines(); - if (lines < entry->dir->nitems - entry->printoff && + if (lines < nitems - entry->printoff && lines < (size_t)-1 - entry->printoff) entry->printoff += lines; return entry;