Add basic facility to download binary items - sacc - sacc(omys), simple console gopher client
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/sacc/
Log
Files
Refs
Tags
LICENSE
---
commit bf6e2f0c9fe5ab30bf03a99d72886b107651c0bb
parent 63737b1ffb50f53932a34001c0e6cc447d6d4e86
Author: Quentin Rameau 
Date:   Mon, 10 Jul 2017 18:18:22 +0200

Add basic facility to download binary items

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

1 file changed, 64 insertions(+), 6 deletions(-)
---
diff --git a/sacc.c b/sacc.c
@@ -1,5 +1,6 @@
 /* See LICENSE file for copyright and license details. */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -103,25 +104,25 @@ typedisplay(char t)
         case '3':
                 return "Err |";
         case '4':
-                return "Macf|";
+                return "Macf+";
         case '5':
-                return "DOSf|";
+                return "DOSf+";
         case '6':
-                return "UUEf|";
+                return "UUEf+";
         case '7':
                 return "Find+";
         case '8':
                 return "Tlnt|";
         case '9':
-                return "Binf|";
+                return "Binf+";
         case '+':
                 return "Mirr|";
         case 'T':
                 return "IBMt|";
         case 'g':
-                return "GIF |";
+                return "GIF +";
         case 'I':
-                return "Img |";
+                return "Img +";
         case 'h':
                 return "HTML|";
         case 'i':
@@ -328,6 +329,46 @@ connectto(const char *host, const char *port)
 }
 
 static int
+downloaditem(Item *item)
+{
+        char buf[BUFSIZ], *path;
+        ssize_t r, w;
+        mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP;
+        int sock, dest;
+
+        if (!(path = uiprompt("Download file to: ")))
+                return 0;
+
+        path[strlen(path)-1] = '\0';
+
+        if ((dest = open(path, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0) {
+                printf("Can't open destination file %s: %s\n",
+                       path, strerror(errno));
+                errno = 0;
+                return 0;
+        }
+
+        sock = connectto(item->host, item->port);
+        sendselector(sock, item->selector);
+
+        while ((r = read(sock, buf, BUFSIZ)) > 0) {
+                while ((w = write(dest, buf, r)) > 0)
+                        r -= w;
+        }
+
+        if (r < 0 || w < 0) {
+                printf("Error downloading file %s: %s\n",
+                       item->selector, strerror(errno));
+                errno = 0;
+        }
+
+        close(dest);
+        close(sock);
+
+        return (r == 0 && w > 0);
+}
+
+static int
 fetchitem(Item *item)
 {
         int sock;
@@ -385,6 +426,15 @@ dig(Item *entry, Item *item)
                         return 0;
                 }
                 break;
+        case '4':
+        case '5':
+        case '6':
+        case '9':
+        case 'g':
+        case 'I':
+                if (!downloaditem(item))
+                        return 0;
+                break;
         default:
                 fprintf(stderr, "Type %c (%s) not supported\n",
                         item->type, typedisplay(item->type));
@@ -421,6 +471,14 @@ delve(Item *hole)
                                 hole->selector = selector;
                         }
                         break;
+                case '4':
+                case '5':
+                case '6': /* TODO decode? */
+                case '9':
+                case 'g':
+                case 'I':
+                        dig(entry, hole);
+                        break;
                 case 0:
                         fprintf(stderr, "Couldn't get %s:%s/%c%s\n", hole->host,
                                         hole->port, hole->type, hole->selector);