10 enum{ DAY = 24*60*60 };
13 lastbefore(ulong t, char *f, char *b)
21 for(try=0; try<10; try++) {
24 sprint(b,"%.4d/%.2d%.2d/netlib/pub/%s",tm->year+1900,tm->mon+1,tm->mday,f);
34 strcpy(b, "filenotfound");
37 // create explicit file for diff, which otherwise would create a
38 // mode 0600 file that it couldn't read (because running as none)
40 gunzip(char *f, char *tmp)
42 int fd = open(tmp, OWRITE);
44 if(fd < 0) // can't happen
51 execl("/bin/gunzip", "gunzip", "-c", f, nil);
52 hprint(HO, "can't exec gunzip: %r\n");
55 hprint(HO, "fork failed: %r\n");
57 while(waitpid() != -1)
65 netlibhistory(char *file)
67 char buf[500], pair[2][500], tmpf[2][30], *f;
68 int toggle = 0, started = 0, limit;
73 if(strncmp(file, "../", 3) == 0 || strstr(file, "/../") ||
74 strlen(file) >= sizeof(buf) - strlen("1997/0204/netlib/pub/0"))
79 // create two tmp files for gunzip
80 for(i = 0, tmpcnt = 0; i < 2 && tmpcnt < 20; tmpcnt++){
81 snprint(tmpf[i], sizeof(tmpf[0]), "/tmp/d%x", tmpcnt);
82 if(access(buf, AEXIST) == 0)
84 fd = create(tmpf[i], OWRITE, 0666);
94 lastbefore(otime, file, buf);
99 while(otime <= dir->mtime){
100 lastbefore(otime-dt, file, buf);
109 if(diffb && strcmp(f+strlen(f)-3, ".gz") == 0){
110 gunzip(f, tmpf[toggle]);
111 strcpy(f, tmpf[toggle]);
113 if(diffb && started){
114 hprint(HO, "<PRE>\n");
118 execl("/bin/diff", "diff", "-nb",
119 pair[1-toggle], pair[toggle], nil);
120 hprint(HO, "can't exec diff: %r\n");
123 hprint(HO, "fork failed: %r\n");
126 while(waitpid() != -1)
130 hprint(HO, "</PRE>\n");
132 hprint(HO,"<LI><A HREF=\"/historic/%s\">%s</A> %lld bytes\n",
133 buf, 4+asctime(gmtime(dir->mtime)), dir->length);
135 hprint(HO," <FONT SIZE=-1>(%s)</FONT>\n", pair[toggle]);
141 hprint(HO,"<LI>...\n");
143 hprint(HO,"</UL>\n");
156 if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0)
157 return hunallowed(c, "GET, HEAD");
158 if(c->head.expectother || c->head.expectcont)
159 return hfail(c, HExpectFail, nil);
160 if(c->req.search == nil || !*c->req.search)
161 return hfail(c, HNoData, "netlib_history");
163 while((s = strchr(s, '+')) != nil)
166 for(q = hparsequery(c, hstrdup(c, c->req.search)); q; q = q->next){
167 if(strcmp(q->s, "file") == 0)
169 else if(strcmp(q->s, "diff") == 0)
173 return hfail(c, HNoData, "netlib_history missing file field");
174 logit(c, "netlib_hist %s%s", file, diffb?" DIFF":"");
178 hprint(HO, "Content-type: text/html\r\n");
181 if(strcmp(c->req.meth, "HEAD") == 0){
182 writelog(c, "Reply: 200 netlib_history 0\n");
187 hprint(HO, "<HEAD><TITLE>%s history</TITLE></HEAD>\n<BODY>\n",file);
188 hprint(HO, "<H2>%s history</H2>\n",file);
189 hprint(HO, "<I>Netlib's copy of %s was changed\n", file);
190 hprint(HO, "on the dates shown. <BR>Click on the date link\n");
191 hprint(HO, "to retrieve the corresponding version.</I>\n");
193 hprint(HO, "<BR><I>Lines beginning with < are for the\n");
194 hprint(HO, "newer of the two versions.</I>\n");
197 if(chdir("/usr/web/historic") < 0)
198 hprint(HO, "chdir failed: %r\n");
201 hprint(HO, "<BR><A HREF=\"http://cm.bell-labs.com/who/ehg\">Eric Grosse</A>\n");
202 hprint(HO, "</BODY></HTML>\n");
204 writelog(c, "Reply: 200 netlib_history %ld %ld\n", HO->seek, HO->seek);
209 main(int argc, char **argv)
213 c = init(argc, argv);
215 if(hparseheaders(c, HSTIMEOUT) >= 0)