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 time_t 29 getmonotime(void) 30 { 31 struct timespec ts; 32 33 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) 34 err(1, "clock_gettime"); 35 return (ts.tv_sec); 36 } 37 38 static void 39 http_request(size_t id, const char *uri, const char *last_mod, int fd) 40 { 41 struct ibuf *b; 42 43 b = io_new_buffer(); 44 io_simple_buffer(b, &id, sizeof(id)); 45 io_str_buffer(b, uri); 46 io_str_buffer(b, last_mod); 47 /* pass file as fd */ 48 b->fd = fd; 49 io_close_buffer(&httpq, b); 50 } 51 52 static const char * 53 http_result(enum http_result res) 54 { 55 switch (res) { 56 case HTTP_OK: 57 return "OK"; 58 case HTTP_NOT_MOD: 59 return "not modified"; 60 case HTTP_FAILED: 61 return "failed"; 62 default: 63 errx(1, "unknown http result: %d", res); 64 } 65 } 66 67 static int 68 http_response(int fd) 69 { 70 struct ibuf *b, *httpbuf = NULL; 71 size_t id; 72 enum http_result res; 73 char *lastmod; 74 75 while ((b = io_buf_read(fd, &httpbuf)) == NULL) 76 /* nothing */ ; 77 78 io_read_buf(b, &id, sizeof(id)); 79 io_read_buf(b, &res, sizeof(res)); 80 io_read_str(b, &lastmod); 81 ibuf_free(b); 82 83 printf("transfer %s", http_result(res)); 84 if (lastmod) 85 printf(", last-modified: %s" , lastmod); 86 printf("\n"); 87 return res == HTTP_FAILED; 88 } 89 90 int 91 main(int argc, char **argv) 92 { 93 pid_t httppid; 94 int error, fd[2], outfd, http; 95 int fl = SOCK_STREAM | SOCK_CLOEXEC; 96 char *uri, *file, *mod; 97 size_t req = 0; 98 99 if (argc != 3 && argc != 4) { 100 fprintf(stderr, "usage: test-http uri file [last-modified]\n"); 101 return 1; 102 } 103 uri = argv[1]; 104 file = argv[2]; 105 mod = argv[3]; 106 107 if (socketpair(AF_UNIX, fl, 0, fd) == -1) 108 err(1, "socketpair"); 109 110 if ((httppid = fork()) == -1) 111 err(1, "fork"); 112 113 if (httppid == 0) { 114 close(fd[1]); 115 116 if (pledge("stdio rpath inet dns recvfd", NULL) == -1) 117 err(1, "pledge"); 118 119 proc_http(NULL, fd[0]); 120 errx(1, "http process returned"); 121 } 122 123 close(fd[0]); 124 http = fd[1]; 125 msgbuf_init(&httpq); 126 httpq.fd = http; 127 128 if ((outfd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) 129 err(1, "open %s", file); 130 131 http_request(req++, uri, mod, outfd); 132 switch (msgbuf_write(&httpq)) { 133 case 0: 134 errx(1, "write: connection closed"); 135 case -1: 136 err(1, "write"); 137 } 138 error = http_response(http); 139 return error; 140 } 141