gemfetch.c (1787B)
1 #include <u.h> 2 #include <libc.h> 3 #include <mp.h> 4 #include <libsec.h> 5 #include <bio.h> 6 7 #define BSIZE 4096 8 9 char * 10 gethost(char *uri) 11 { 12 char *host, *sp, *ep; 13 long length; 14 15 sp = strstr(uri, "://"); 16 if (sp == nil) { 17 werrstr("missing scheme:// in '%s'", uri); 18 return nil; 19 } 20 else sp += 3; 21 22 ep = strchr(sp, '/'); 23 if (ep == nil) ep = sp + strlen(sp); 24 length = ep - sp; 25 host = mallocz(sizeof(char) * (length+1), 1); 26 memcpy(host, sp, length); 27 return host; 28 } 29 30 void 31 usage(void) 32 { 33 fprint(2, "usage: %s [-h host] uri\n", argv0); 34 exits("usage"); 35 } 36 37 void 38 main(int argc, char **argv) 39 { 40 char *buf, *uri, *host; 41 long n, t; 42 int fd, tlsfd; 43 Biobuf bfd; 44 TLSconn conn; 45 46 host = nil; 47 48 ARGBEGIN { 49 case 'h': 50 host = EARGF(usage()); 51 break; 52 default: 53 usage(); 54 } ARGEND 55 56 if (argc != 1) usage(); 57 58 uri = argv[0]; 59 if (host == nil) host = gethost(uri); 60 if (host == nil) sysfatal("gethost: %r"); 61 62 fprint(2, "fetching from %s\n", host); 63 fd = dial(netmkaddr(host, "tcp", "1965"), nil, nil, nil); 64 if (fd < 0) sysfatal("dial: %r"); 65 66 memset(&conn, 0, sizeof(conn)); 67 conn.serverName = host; 68 tlsfd = tlsClient(fd, &conn); 69 if (tlsfd < 0) sysfatal("tlsClient: %r"); 70 71 if (Binit(&bfd, tlsfd, OREAD) < 0) 72 sysfatal("Binit: %r"); 73 74 n = fprint(tlsfd, "%s\r\n", uri); 75 if (n < 0) sysfatal("fprint: %r"); 76 77 buf = Brdstr(&bfd, '\n', 1); 78 n = Blinelen(&bfd); 79 if (n > 1024 + 2) 80 fprint(2, "warning: header too long\n"); 81 buf[n-1] = '\0'; 82 fprint(2, "%s\n", buf); 83 84 t = 0; 85 86 buf = realloc(buf, BSIZE); 87 88 while ((n = Bread(&bfd, buf, BSIZE)) > 0) { 89 t += n; 90 write(1, buf, n); 91 } 92 // read always returns with "i/o on hangup channel" errstr 93 // TODO: find a way to deal with it 94 // if (n < 0) fprint(2, "read: %r\n"); 95 96 fprint(2, "total: %ld\n", t); 97 98 Bterm(&bfd); 99 close(tlsfd); 100 close(fd); 101 }