1 #include <sys/queue.h> 2 #include <sys/socket.h> 3 #include <err.h> 4 #include <errno.h> 5 #include <fcntl.h> 6 #include <limits.h> 7 #include <stdarg.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 12 #include <imsg.h> 13 14 #include "extern.h" 15 16 static struct msgbuf httpq; 17 18 void 19 logx(const char *fmt, ...) 20 { 21 va_list ap; 22 23 va_start(ap, fmt); 24 vwarnx(fmt, ap); 25 va_end(ap); 26 } 27 28 static void 29 http_request(size_t id, const char *uri, const char *last_mod, int fd) 30 { 31 struct ibuf *b; 32 33 if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL) 34 err(1, NULL); 35 io_simple_buffer(b, &id, sizeof(id)); 36 io_str_buffer(b, uri); 37 io_str_buffer(b, last_mod); 38 /* pass file as fd */ 39 b->fd = fd; 40 ibuf_close(&httpq, b); 41 } 42 43 static const char * 44 http_result(enum http_result res) 45 { 46 switch (res) { 47 case HTTP_OK: 48 return "OK"; 49 case HTTP_NOT_MOD: 50 return "not modified"; 51 case HTTP_FAILED: 52 return "failed"; 53 default: 54 errx(1, "unknown http result: %d", res); 55 } 56 } 57 58 static void 59 http_response(int fd) 60 { 61 size_t id; 62 enum http_result res; 63 char *lastmod; 64 65 io_simple_read(fd, &id, sizeof(id)); 66 io_simple_read(fd, &res, sizeof(res)); 67 io_str_read(fd, &lastmod); 68 69 printf("transfer %s", http_result(res)); 70 if (lastmod) 71 printf(", last-modified: %s" , lastmod); 72 printf("\n"); 73 } 74 75 int 76 main(int argc, char **argv) 77 { 78 pid_t httppid; 79 int fd[2], outfd, http; 80 int fl = SOCK_STREAM | SOCK_CLOEXEC; 81 char *uri, *file, *mod; 82 size_t req = 0; 83 84 if (argc != 3 && argc != 4) { 85 fprintf(stderr, "usage: test-http uri file [last-modified]\n"); 86 return 1; 87 } 88 uri = argv[1]; 89 file = argv[2]; 90 mod = argv[3]; 91 92 if (socketpair(AF_UNIX, fl, 0, fd) == -1) 93 err(1, "socketpair"); 94 95 if ((httppid = fork()) == -1) 96 err(1, "fork"); 97 98 if (httppid == 0) { 99 close(fd[1]); 100 101 if (pledge("stdio rpath inet dns recvfd", NULL) == -1) 102 err(1, "pledge"); 103 104 proc_http(NULL, fd[0]); 105 errx(1, "http process returned"); 106 } 107 108 close(fd[0]); 109 http = fd[1]; 110 msgbuf_init(&httpq); 111 httpq.fd = http; 112 113 if ((outfd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) 114 err(1, "open %s", file); 115 116 http_request(req++, uri, mod, outfd); 117 switch (msgbuf_write(&httpq)) { 118 case 0: 119 errx(1, "write: connection closed"); 120 case -1: 121 err(1, "write"); 122 } 123 http_response(http); 124 125 return 0; 126 } 127