tAdd basic facility to download binary items - sacc - sacc (saccomys): simple gopher client.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit bf6e2f0c9fe5ab30bf03a99d72886b107651c0bb
 (DIR) parent 63737b1ffb50f53932a34001c0e6cc447d6d4e86
 (HTM) Author: Quentin Rameau <quinq@fifth.space>
       Date:   Mon, 10 Jul 2017 18:18:22 +0200
       
       Add basic facility to download binary items
       
       Diffstat:
         sacc.c                              |      70 ++++++++++++++++++++++++++++---
       
       1 file changed, 64 insertions(+), 6 deletions(-)
       ---
 (DIR) diff --git a/sacc.c b/sacc.c
       t@@ -1,5 +1,6 @@
        /* See LICENSE file for copyright and license details. */
        #include <errno.h>
       +#include <fcntl.h>
        #include <netdb.h>
        #include <stdarg.h>
        #include <stdio.h>
       t@@ -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':
       t@@ -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;
       t@@ -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));
       t@@ -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);