|  | #include "a.h" | 
|  |  | 
|  | typedef struct DEntry DEntry; | 
|  | struct DEntry | 
|  | { | 
|  | CEntry ce; | 
|  | HTTPHeader hdr; | 
|  | char *tmpfile; | 
|  | int fd; | 
|  | }; | 
|  |  | 
|  | static void | 
|  | dfree(CEntry *ce) | 
|  | { | 
|  | DEntry *d; | 
|  |  | 
|  | d = (DEntry*)ce; | 
|  | if(d->tmpfile){ | 
|  | remove(d->tmpfile); | 
|  | free(d->tmpfile); | 
|  | close(d->fd); | 
|  | } | 
|  | } | 
|  |  | 
|  | static Cache *downloadcache; | 
|  |  | 
|  | static char* | 
|  | parseurl(char *url, char **path) | 
|  | { | 
|  | char *host, *p; | 
|  | int len; | 
|  |  | 
|  | if(memcmp(url, "http://", 7) != 0) | 
|  | return nil; | 
|  | p = strchr(url+7, '/'); | 
|  | if(p == nil) | 
|  | p = url+strlen(url); | 
|  | len = p - (url+7); | 
|  | host = emalloc(len+1); | 
|  | memmove(host, url+7, len); | 
|  | host[len] = 0; | 
|  | if(*p == 0) | 
|  | p = "/"; | 
|  | *path = p; | 
|  | return host; | 
|  | } | 
|  |  | 
|  | int | 
|  | download(char *url, HTTPHeader *hdr) | 
|  | { | 
|  | DEntry *d; | 
|  | char *host, *path; | 
|  | char buf[] = "/var/tmp/smugfs.XXXXXX"; | 
|  | char *req; | 
|  | int fd; | 
|  | Fmt fmt; | 
|  |  | 
|  | if(downloadcache == nil) | 
|  | downloadcache = newcache(sizeof(DEntry), 128, dfree); | 
|  |  | 
|  | host = parseurl(url, &path); | 
|  | if(host == nil) | 
|  | return -1; | 
|  |  | 
|  | d = (DEntry*)cachelookup(downloadcache, url, 1); | 
|  | if(d->tmpfile){ | 
|  | free(host); | 
|  | *hdr = d->hdr; | 
|  | return dup(d->fd, -1); | 
|  | } | 
|  | d->fd = -1;  // paranoia | 
|  |  | 
|  | if((fd = opentemp(buf, ORDWR|ORCLOSE)) < 0){ | 
|  | free(host); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | fmtstrinit(&fmt); | 
|  | fmtprint(&fmt, "GET %s HTTP/1.0\r\n", path); | 
|  | fmtprint(&fmt, "Host: %s\r\n", host); | 
|  | fmtprint(&fmt, "User-Agent: " USER_AGENT "\r\n"); | 
|  | fmtprint(&fmt, "\r\n"); | 
|  | req = fmtstrflush(&fmt); | 
|  |  | 
|  | fprint(2, "Get %s\n", url); | 
|  |  | 
|  | if(httptofile(&http, host, req, hdr, fd) < 0){ | 
|  | free(host); | 
|  | free(req); | 
|  | return -1; | 
|  | } | 
|  | free(host); | 
|  | free(req); | 
|  | d->tmpfile = estrdup(buf); | 
|  | d->fd = dup(fd, -1); | 
|  | d->hdr = *hdr; | 
|  | return fd; | 
|  | } | 
|  |  | 
|  | void | 
|  | downloadflush(char *substr) | 
|  | { | 
|  | if(downloadcache) | 
|  | cacheflush(downloadcache, substr); | 
|  | } |