Better error handling, add an item parsing function - sacc - sacc(omys), simple console gopher client
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/sacc/
Log
Files
Refs
Tags
LICENSE
---
commit 4691af5361b43138f257b19b23c89199cff210dc
parent 8a7bc011a62ba737e6fb1fe7c84ca2fa1a20eb31
Author: Quentin Rameau 
Date:   Fri, 23 Jun 2017 20:37:27 +0200

Better error handling, add an item parsing function

Diffstat:
  M sacc.c                              |      99 +++++++++++++++++++++-----------

1 file changed, 66 insertions(+), 33 deletions(-)
---
diff --git a/sacc.c b/sacc.c
@@ -189,34 +189,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)
 {
@@ -230,27 +259,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;
 
@@ -344,29 +371,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;
 }