Annotation of loncom/lonhttpd, revision 1.11
1.1 www 1: #!/usr/bin/perl
1.11 ! raeburn 2: # $Id: lonhttpd,v 1.10 2005/02/14 00:18:03 albertel Exp $
1.1 www 3:
1.6 albertel 4: $VERSION = "1.3.2 (Demonic/Linux/LON-CAPA Derivative $Revison$)";
1.1 www 5:
1.3 www 6: # HTTPi Hypertext Tiny Truncated Process Implementation
7: # Copyright 1999-2001 Cameron Kaiser # All rights reserved
8: # Please read LICENSE # Do not strip this copyright message.
9: #
10: # LON-CAPA: find httpi license and readme at CVS loncom/license
11: #
12:
1.6 albertel 13: use lib '/home/httpd/lib/perl/';
14: use LONCAPA::Configuration();
15: %loncapavar=%{&LONCAPA::Configuration::read_conf('loncapa.conf')};
16: $port_to_use=$loncapavar{'lonhttpdPort'};
17: if (!defined($port_to_use)) {
18: $port_to_use='8080';
19: }
20:
21: # The main server is running on 80, so exit in this case
22: if ($port_to_use eq '80') { die('Apache is already on Port 80'); }
23:
1.3 www 24: %system_content_types =
25: ("html" => "text/html",
26: "htm" => "text/html",
27: "wml" => "text/vnd.wap.wml",
28: "wbmp" => "image/vnd.wap.wbmp",
29: "wbm" => "image/vnd.wap.wbmp",
30: "xbm" => "image/x-xbitmap",
31: "pdf" => "application/pdf",
32: "fdf" => "application/vnd.fdf",
33: "bin" => "application/octet-stream",
34: "class" => "application/octet-stream",
35: "jar" => "application/octet-stream",
36: "js" => "application/x-javascript",
37: "lnk" => "application/x-hyperlink",
38: "wav" => "audio/x-wav",
39: "mp3" => "audio/x-mpeg",
40: "tif" => "image/tiff",
41: "tiff" => "image/tiff",
42: "mid" => "audio/x-midi",
43: "txt" => "text/plain",
44: "gif" => "image/gif",
45: "sit" => "application/x-stuffit",
46: "zip" => "application/x-zip-compressed",
47: "lzh" => "application/octet-stream",
48: "lha" => "application/octet-stream",
49: "gz" => "application/x-gzip",
50: "mov" => "movie/quicktime",
51: "mpeg" => "video/mpeg",
52: "mpg" => "video/mpeg",
53: "jpeg" => "image/jpeg",
1.11 ! raeburn 54: "jpg" => "image/jpeg",
! 55: "png" => "image/png");
1.3 www 56:
57: $logfile = "/home/httpd/perl/logs/lonhttpd.log";
58:
59: # Write out PID
60:
61: $pidfile="/home/httpd/perl/logs/lonhttpd.pid";
62:
63: if (-e $pidfile) {
64: open(LFH,"$pidfile");
1.10 albertel 65: my $pide=<LFH>;
1.3 www 66: chomp($pide);
67: close(LFH);
68: if (kill 0 => $pide) { die "already running"; }
69: }
70:
71: $path = "/home/httpd/html";
72: $sockaddr = 'S n a4 x8';
1.1 www 73:
74:
1.3 www 75: %content_types =
76: ("html" => "text/html",
77: "htm" => "text/html");
78: %restrictions =
79: ("/" => "#.##", # deny everything
80: "/res/adm" => ".###", # allow /res/adm
81: "/adm" => ".###", # allow /adm
82: "/status" => ".####lonadm:oeRooOvb3HtpI");
83: # See documentation for interpreting this string.
84:
85: $headers = <<"EOF";
86: Server: HTTPi/$VERSION
87: MIME-Version: 1.0
88: EOF
89:
90: %virtual_files =
91: (
92: "/adm/lonLCDfont/0.gif" => [ "image/gif", "FILE",
93: "/home/httpd/html/adm/lonLCDfont/0.gif" ] ,
94: "/adm/lonLCDfont/1.gif" => [ "image/gif", "FILE",
95: "/home/httpd/html/adm/lonLCDfont/1.gif" ] ,
96: "/adm/lonLCDfont/2.gif" => [ "image/gif", "FILE",
97: "/home/httpd/html/adm/lonLCDfont/2.gif" ] ,
98: "/adm/lonLCDfont/3.gif" => [ "image/gif", "FILE",
99: "/home/httpd/html/adm/lonLCDfont/3.gif" ] ,
100: "/adm/lonLCDfont/4.gif" => [ "image/gif", "FILE",
101: "/home/httpd/html/adm/lonLCDfont/4.gif" ] ,
102: "/adm/lonLCDfont/5.gif" => [ "image/gif", "FILE",
103: "/home/httpd/html/adm/lonLCDfont/5.gif" ] ,
104: "/adm/lonLCDfont/6.gif" => [ "image/gif", "FILE",
105: "/home/httpd/html/adm/lonLCDfont/6.gif" ] ,
106: "/adm/lonLCDfont/7.gif" => [ "image/gif", "FILE",
107: "/home/httpd/html/adm/lonLCDfont/7.gif" ] ,
108: "/adm/lonLCDfont/8.gif" => [ "image/gif", "FILE",
109: "/home/httpd/html/adm/lonLCDfont/8.gif" ] ,
110: "/adm/lonLCDfont/9.gif" => [ "image/gif", "FILE",
111: "/home/httpd/html/adm/lonLCDfont/9.gif" ] ,
112: "/adm/lonLCDfont/a.gif" => [ "image/gif", "FILE",
113: "/home/httpd/html/adm/lonLCDfont/a.gif" ] ,
114: "/adm/lonLCDfont/b.gif" => [ "image/gif", "FILE",
115: "/home/httpd/html/adm/lonLCDfont/b.gif" ] ,
116: "/adm/lonLCDfont/c.gif" => [ "image/gif", "FILE",
117: "/home/httpd/html/adm/lonLCDfont/c.gif" ] ,
118: "/adm/lonLCDfont/d.gif" => [ "image/gif", "FILE",
119: "/home/httpd/html/adm/lonLCDfont/d.gif" ] ,
120: "/adm/lonLCDfont/e.gif" => [ "image/gif", "FILE",
121: "/home/httpd/html/adm/lonLCDfont/e.gif" ] ,
122: "/adm/lonLCDfont/f.gif" => [ "image/gif", "FILE",
123: "/home/httpd/html/adm/lonLCDfont/f.gif" ] ,
124: "/adm/lonLCDfont/g.gif" => [ "image/gif", "FILE",
125: "/home/httpd/html/adm/lonLCDfont/g.gif" ] ,
126: "/adm/lonLCDfont/h.gif" => [ "image/gif", "FILE",
127: "/home/httpd/html/adm/lonLCDfont/h.gif" ] ,
128: "/adm/lonLCDfont/i.gif" => [ "image/gif", "FILE",
129: "/home/httpd/html/adm/lonLCDfont/i.gif" ] ,
130: "/adm/lonLCDfont/j.gif" => [ "image/gif", "FILE",
131: "/home/httpd/html/adm/lonLCDfont/j.gif" ] ,
132: "/adm/lonLCDfont/k.gif" => [ "image/gif", "FILE",
133: "/home/httpd/html/adm/lonLCDfont/k.gif" ] ,
134: "/adm/lonLCDfont/l.gif" => [ "image/gif", "FILE",
135: "/home/httpd/html/adm/lonLCDfont/l.gif" ] ,
136: "/adm/lonLCDfont/m.gif" => [ "image/gif", "FILE",
137: "/home/httpd/html/adm/lonLCDfont/m.gif" ] ,
138: "/adm/lonLCDfont/n.gif" => [ "image/gif", "FILE",
139: "/home/httpd/html/adm/lonLCDfont/n.gif" ] ,
140: "/adm/lonLCDfont/o.gif" => [ "image/gif", "FILE",
141: "/home/httpd/html/adm/lonLCDfont/o.gif" ] ,
142: "/adm/lonLCDfont/p.gif" => [ "image/gif", "FILE",
143: "/home/httpd/html/adm/lonLCDfont/p.gif" ] ,
144: "/adm/lonLCDfont/q.gif" => [ "image/gif", "FILE",
145: "/home/httpd/html/adm/lonLCDfont/q.gif" ] ,
146: "/adm/lonLCDfont/r.gif" => [ "image/gif", "FILE",
147: "/home/httpd/html/adm/lonLCDfont/r.gif" ] ,
148: "/adm/lonLCDfont/s.gif" => [ "image/gif", "FILE",
149: "/home/httpd/html/adm/lonLCDfont/s.gif" ] ,
150: "/adm/lonLCDfont/t.gif" => [ "image/gif", "FILE",
151: "/home/httpd/html/adm/lonLCDfont/t.gif" ] ,
152: "/adm/lonLCDfont/u.gif" => [ "image/gif", "FILE",
153: "/home/httpd/html/adm/lonLCDfont/u.gif" ] ,
154: "/adm/lonLCDfont/v.gif" => [ "image/gif", "FILE",
155: "/home/httpd/html/adm/lonLCDfont/v.gif" ] ,
156: "/adm/lonLCDfont/w.gif" => [ "image/gif", "FILE",
157: "/home/httpd/html/adm/lonLCDfont/w.gif" ] ,
158: "/adm/lonLCDfont/x.gif" => [ "image/gif", "FILE",
159: "/home/httpd/html/adm/lonLCDfont/x.gif" ] ,
160: "/adm/lonLCDfont/y.gif" => [ "image/gif", "FILE",
161: "/home/httpd/html/adm/lonLCDfont/y.gif" ] ,
162: "/adm/lonLCDfont/z.gif" => [ "image/gif", "FILE",
163: "/home/httpd/html/adm/lonLCDfont/z.gif" ] ,
164: "/adm/lonLCDfont/colon.gif" => [ "image/gif", "FILE",
165: "/home/httpd/html/adm/lonLCDfont/colon.gif" ] ,
166: "/adm/lonLCDfont/slash.gif" => [ "image/gif", "FILE",
167: "/home/httpd/html/adm/lonLCDfont/slash.gif" ] ,
168: "/adm/lonLCDfont/hyphen.gif" => [ "image/gif", "FILE",
169: "/home/httpd/html/adm/lonLCDfont/hyphen.gif" ] ,
170: "/adm/lonLCDfont/space.gif" => [ "image/gif", "FILE",
171: "/home/httpd/html/adm/lonLCDfont/space.gif" ] ,
172: );
173:
174: %content_types = (%system_content_types, %content_types);
175: undef %system_content_types;
176:
177: while (($file, $arrayref) = each(%virtual_files)) {
178: my ($mime, $type, $block) = (@{ $arrayref });
179: next if ($type ne 'FILE');
180: if(open(S, "$block")) {
181: $j = $/; undef $/; $virtual_files{$file}->[2] = scalar(<S>);
182: $/ = $j; close(S);
183: } else {
184: warn "while getting virtual file $file: $!\n";
185: map_delete(%virtual_files, $file);
186: }
187: }
188: if ($pid = fork()) { exit; }
189:
190: #
191: # Store parent PID
192: #
1.1 www 193:
1.3 www 194: open (PIDSAVE,">$pidfile");
1.1 www 195: print PIDSAVE "$$\n";
196: close(PIDSAVE);
197:
1.5 albertel 198: $0 = "lonhttpd: (dhttpi) binding port ...";
1.6 albertel 199: $bindthis = pack($sockaddr, 2, $port_to_use,
200: pack('l', chr(0).chr(0).chr(0).chr(0)));
1.3 www 201: socket(S, 2, 1, 6);
202: setsockopt(S, 1, 2, 1);
1.6 albertel 203: bind(S, $bindthis) || die("$0: while binding port $port_to_use:\n\"$!\"\n");
1.3 www 204: listen(S, 128);
1.6 albertel 205: $0 = "lonhttpd: (dhttpi) connected and waiting ANY:$port_to_use";
1.3 www 206:
207: $statiosuptime = time();
208:
209: ###############################################################
210: # WHITE HATS ONLY BELOW THIS POINT -- SEE DOCUMENTATION FIRST #
211: ###############################################################
212:
213: sub sock_to_host {
214: local($sock) = getpeername(STDIN);
215:
216: return (undef, undef, undef) if (!$sock);
217: local($AFC, $port, $thataddr, $zero) = unpack($sockaddr, $sock);
218: local($ip) = join('.', unpack("C4", $thataddr));
219: return ($ip, $port, $ip);
220: }
221:
222: sub htsponse {
223: ($currentcode, $currentstring) = (@_);
224: return if (0+$httpver < 1);
225: local($what) = <<"EOF";
226: HTTP/$httpver $currentcode $currentstring
227: ${headers}Date: $rfcdate
228: EOF
229: $what =~ s/\n/\r\n/g;
230: print stdout $what;
231: &hthead("Connection: close") if (0+$httpver > 1);
232: }
233:
234: sub hthead {
235: local($header, $term) = (@_);
236: return if (0+$httpver < 1);
237: print stdout "$header\r\n" , ($term) ? "\r\n" : "";
238: }
239:
240: sub htcontent {
241: local($what, $ctype, $mode) = (@_);
242: ($contentlength) = $mode || length($what);
243: &hthead("Content-Length: $contentlength");
244: &hthead("Content-Type: $ctype", 1);
245: return if ($method eq 'HEAD' || $mode);
246: print stdout $what;
247: }
248:
249: sub log {
250: if (open(J, ">>$logfile")) {
251: local $q = $address . (($variables) ? "?$variables" : "");
252: $contentlength += 0;
253: $contentlength = 0 if ($method eq 'HEAD');
254: local ($hostname, $port, $ip) = &sock_to_host();
255: $hostname = $hostname || "-";
256: $httpuser = $httpuser || "-";
257: print J <<"EOF";
258: $hostname - $httpuser [$date] "$method $q HTTP/$httpver" $currentcode $contentlength "$httpref" "$httpua"
259: EOF
260: close(J); }
261: }
262:
263:
1.9 www 264: sub bye { exit; }
265:
266: sub goodbye { unlink($pidfile); exit; }
1.3 www 267:
268: sub dead {
269: &htsponse(500, "Server Error");
270: &hterror("Server Error", <<"EOF");
271: While handling a request for resource $address, the server crashed. Please
272: attempt to notify the administrators.
273: <p>Useful(?) debugging information:
274: <pre>
275: @_
276: </pre>
277: EOF
278: &log; unlink($pidfile); exit;
279: }
280:
281: $SIG{'__DIE__'} = \&dead;
1.9 www 282: $SIG{'ALRM'} = \&bye;
283: $SIG{'TERM'} = $SIG{'INT'} = \&goodbye;
1.3 www 284:
285: sub master {
1.5 albertel 286: $0 = "lonhttpd: (dhttpi) handling request";
1.3 www 287: # $sock = getpeername(STDIN);
288: $rfcdate = scalar gmtime;
289: ($dow, $mon, $dt, $tm, $yr) = ($rfcdate =~
290: m/(...) (...) (..) (..:..:..) (....)/);
291: $dt += 0; $yr += 0;
292: $rfcdate = "$dow, $dt $mon $yr $tm GMT";
293: $date = scalar localtime;
294: ($dow, $mon, $dt, $tm, $yr) = ($date =~
295: m/(...) (...) (..) (..:..:..) (....)/);
296: $dt += 0;
297: $dt = substr("0$dt", length("0$dt") - 2, 2);
298: $date = "$dt/$mon/$yr:$tm +0000";
299:
300: select(STDOUT); $|=1; $address = 0;
301: alarm 1;
302: while (<STDIN>) {
1.8 albertel 303: if(/^([A-Z]+)\s+(\S+)\s+(\S*)/) {
1.3 www 304: $method = $1;
305: $address = $2;
306: $httpver = $3;
307: $httpref = '';
308: $httpua = '';
309: $httpver = ($httpver =~ m#HTTP/([0-9]\.[0-9]+)#) ?
310: ($1) : (0.9);
311: $address =~ s#^http://[^/]+/#/#;
312: next unless ($httpver < 1);
313: } else {
314: s/[\r\l\n\s]+$//;
315: (/^Host: (.+)/i) && ($httphost = $1) && ($httphost =~
316: s/:\d+$//);
317: (/^Referer: (.+)/i) && ($httpref = $1);
318: (/^User-agent: (.+)/i) && ($httpua = $1);
319: (/^Content-length: (\d+)/i) && ($ENV{'CONTENT_LENGTH'} =
320: $httpcl = $1);
321: (/^Content-type: (.+)/i) && ($ENV{'CONTENT_TYPE'} =
322: $httpct = $1);
323: (/^Expect: /) && ($expect = 1);
324: (/^Authorization: Basic (.+)/i) && ($httprawu = $1);
325: (/^Range: (.+)/i) && ($ENV{'CONTENT_RANGE'} = $1);
326: next unless (/^$/);
327: }
328: if ($expect) {
329: &htsponse(417, "Expectation Failed");
330: &hterror("Expectation Failed",
331: "The server does not support this method.");
332: &log; exit;
333: }
334: if (!$address || (0+$httpver > 1 && !$httphost)) {
335: &htsponse(400, "Bad Request");
336: &hterror("Bad Request",
337: "The server cannot understand your request.");
338: &log; exit;
339: }
340: if ($method !~ /^(GET|HEAD|POST)$/) {
341: &htsponse(501, "Illegal Method");
342: &hterror("Illegal Method",
343: "Only GET, HEAD and POST are supported.");
344: &log; exit;
345: }
346: ($address, $variables) = split(/\?/, $address);
347: $address =~ s/%([0-9a-fA-F]{2})/pack("H2", $1)/eg;
348: $address=~ s#^/?#/#;
349: 1 while $address =~ s#/\.(/|$)#\1#;
350: 1 while $address =~ s#/[^/]*/\.\.(/|$)#\1#;
351: 1 while $address =~ s#^/\.\.(/|$)#\1#;
1.11 ! raeburn 352: $fail = 1;
1.3 www 353: #
354: # Heavily customized for LON-CAPA
355: #
1.4 www 356: $address=~s/\/+/\//g;
1.11 ! raeburn 357: if ($address=~/^\/(status|adm\/|res\/adm\/)/) {
! 358: $fail = 0;
! 359: } elsif ($address =~ /^\/res\/([^\/]+)\/([^\/]+)\-domainconfig\/(logo|domlogo|img)\/[^\/]+$/) {
! 360: # FIXME - should check $1 is a real domain here - need a lightweight
! 361: # domain checker.
! 362: # @alldomains = &Apache::lonnet::get_domains();
! 363: # if (grep(/^\Q$1\E$/,@alldomains)) {
! 364: $fail = 0;
! 365: # }
! 366: }
! 367:
1.3 www 368: #
369: # because existing restriction matrix would not do precedence across rules
370: #
371: # J: foreach(sort { length $a <=> length $b }
372: # keys %restrictions) {
373: # next if ($address !~ /^$_/);
374: # ($allowip, $denyip, $allowua, $denyua, $auser) =
375: # split(/#/, $restrictions{$_});
376: # if ($allowip || $denyip) {
377: # ($hostname, $port, $ip) = &sock_to_host();
378: # ($allowip && $ip !~ /$allowip/) && ($fail = 1,
379: # last J);
380: # ($denyip && $ip =~ /$denyip/) && ($fail = 1,
381: # last J);
382: # }
383: # ($allowua && $httpua !~ /$allowua/) &&
384: # ($fail = 2, last J);
385: # ($denyua && $httpua =~ /$denyua/) &&
386: # ($fail = 2, last J);
387: # }
388: if ($fail) {
389: &htsponse(403, "Forbidden");
390: if ($fail == 1) {
1.7 www 391: &hterror("Wrong URL", <<"EOF");
392: You might want to remove the "<tt>:$port_to_use</tt>" from the web page address (URL).
1.3 www 393: EOF
394: &log; exit;
395: } else {
396: &hterror("Forbidden (Browser Disallowed)", <<"EOF");
397: The browser you are using (<i>$httpua</i>) is not capable of or
398: is not allowed access to this resource.
399: EOF
400: &log; exit;
401: }
402: }
403: if ($auser) {
404: $httprawu =~ tr#A-Za-z0-9+/##cd;
405: $httprawu =~ tr#A-Za-z0-9+/# -_#;
406: $httprawu = unpack("u", pack("c", 32+0.75*length($httprawu))
407: . $httprawu);
408: ($httpuser, $httppw) = split(/:/, $httprawu);
409: $fail = 1;
410: foreach $user (split(/,/, $auser)) {
411: ($user, $pw) = split(/:/, $user);
412: ($fail = 0, last) if ($user eq $httpuser &&
413: crypt($httppw, substr($pw, 0, 2)) eq $pw);
414: }
415: if ($fail) {
416: $httpuser = '';
417: &htsponse(401, "Authorization Required");
418: &hthead("WWW-Authenticate: Basic realm=\"$address\"");
419: &hterror("Authorization Required", <<"EOF");
420: You must provide a username and password to use this resource. Either you
421: entered this information incorrectly, or your browser does not know how to
422: present the credentials required.
423: EOF
424: &log; exit;
425: }
426: }
1.1 www 427:
1.3 www 428: alarm 0;
429:
430: if ($address eq '/status') {
431: &htsponse(200, "OK");
432: $contentlength = 0; # kludge
433: &log;
434: if(open(S, $logfile)) {
435: seek(S, -5000, 2);
436: undef $/;
437: $logsnap = <S>;
438: $logsnap =~ s/^[^\n]+\n//s if
439: (length($logsnap) > 4999);
440: close(S);
441: }
442: $p = (time() - $statiosuptime);
443: $rps = $p/$statiosreq;
444: $d = int($p / 86400); $p -= $d * 86400;
445: $h = int($p / 3600); $p -= $h * 3600;
446: $m = int($p / 60); $s = $p - ($m * 60);
447: ("0$s" =~ /(\d{2})$/) && ($s = $1);
448: ("0$m" =~ /(\d{2})$/) && ($m = $1);
449: $h +=0; $d += 0;
450: $suptime = scalar localtime $statiosuptime;
451: &htcontent(<<"EOF", "text/html");
452: <html>
453: <head>
454: <title>
1.5 albertel 455: LonHTTPD (HTTPi) Status
1.3 www 456: </title>
457: </head>
458: <body bgcolor = "#ffffff" text = "#000000" vlink = "#0000ff" link = "#0000ff">
1.5 albertel 459: <h1>LonHTTPD (HTTPi) Server Status (<code>$VERSION</code>)</h1>
1.6 albertel 460: <h3>lonhttpd on port $port_to_use</h3>
1.3 www 461: <b>Started at:</b> $suptime<br>
462: <b>Uptime:</b> $d days, $h:$m:$s<br>
463: <b>Last request time:</b> $statiosltr<p>
464: <b>Requests received:</b> $statiosreq<br>
465: <b>Average time between requests:</b> ${rps}s
466: <p>
467: <b>Most recent requests:</b>
468: <form action = "/status" method = "post">
469: <textarea name = "bletch" rows = "8" cols = "70">
470: $logsnap
471: </textarea>
472: </form>
473: <hr>
474: <address>maintained by <a href =
475: "http://httpi.floodgap.com/">httpi/$VERSION</a></address>
476: </body>
477: </html>
478: EOF
479: exit;
480: }
481: if (defined $virtual_files{$address}) {
482: $virt_buffer = 1;
483: $mtime = $statiosuptime; # thus always needed
484: goto SERVEIT; # yes, it's bad but it's fast
485: }
486: $raddress = "$path$address"
487: ;
488: &hterror301("$address/")
489: if ($address !~ m#/$# && -d $raddress);
490: $raddress = "${raddress}index.html" if (-d $raddress);
491: if(!sysopen(S, $raddress, 0)) { &hterror404; } else {
492: if (-x $raddress) {
493: $currentcode = 100;
494: &log;
495: if (!$<) {
496: ($x,$x,$x,$x,$uid,$gid) = stat(S);
497: (!$uid || !$gid) &&
498: die "executable is root-owned";
499: $> = $uid || die "can't set effuid";
500: $) = $gid || die "can't set effgid";
501: }
502: ($hostname, $port, $ip) = &sock_to_host() if (!$port);
503: $ENV{'REQUEST_METHOD'} = $method;
504: $ENV{'SERVER_NAME'} = "localhost";
505: $ENV{'SERVER_PROTOCOL'} = "HTTP/$httpver";
506: $ENV{'SERVER_SOFTWARE'} = "HTTPi/$VERSION";
1.6 albertel 507: $ENV{'SERVER_PORT'} = "$port_to_use";
508: $ENV{'SERVER_URL'} = "http://localhost:$port_to_use/";
1.3 www 509: $ENV{'SCRIPT_FILENAME'} = $raddress;
510: $ENV{'SCRIPT_NAME'} = $address;
511: $ENV{'REMOTE_HOST'} = $hostname;
512: $ENV{'REMOTE_ADDR'} = $ip;
513: $ENV{'REMOTE_PORT'} = $port;
514: $ENV{'QUERY_STRING'} = $variables;
515: $ENV{'HTTP_USER_AGENT'} = $httpua;
516: $ENV{'HTTP_REFERER'} = $httpref;
517: if ($pid = fork()) { exit; } else {
518: if ($method eq 'POST') { # needs stdin
519: open(W, "|$raddress") || die
520: "can't POST to $raddress";
521: read(STDIN, $buf, $httpcl);
522: print W $buf;
523: exit;
524: }
525: exec "$raddress", "$variables";
526: die "exec() returned -1";
527: }
528: }
529: ($x,$x,$x,$x,$x,$x,$x,$length,$x,$mtime) = stat(S);
530: $ctype = 0;
531: foreach(keys %content_types) {
532: if ($raddress =~ /\.$_$/i) {
533: $ctype = $content_types{$_};
534: }
535: }
536: SERVEIT: $ctype ||= 'text/plain';
537: &htsponse(200, "OK");
538: $mtime = scalar gmtime $mtime;
539: ($dow, $mon, $dt, $tm, $yr) =
540: ($mtime =~ m/(...) (...) (..) (..:..:..) (....)/);
541: $dt += 0; $yr += 0;
542: &hthead("Last-Modified: $dow, $dt $mon $yr $tm GMT");
543: if ($pid = fork()) { exit; }
544: if ($virt_buffer) {
545: &htcontent($virtual_files{$address}->[2],
546: $virtual_files{$address}->[0], 0);
547: } else {
548: &htcontent("", $ctype, $length);
549: unless ($method eq 'HEAD') {
550: while(!eof(S)) {
551: read(S, $q, 16384);
552: print stdout $q;
553: }
554: }
555: }
556: alarm 0;
557: }
558: &log;
559: exit;
560: }
1.1 www 561:
1.3 www 562: exit;
563: }
564:
565:
566: sub hterror {
567: local($errstr, $expl) = (@_);
568: &htcontent(<<"EOF", "text/html");
569: <html>
570: <body>
571: <h1>$errstr</h1>
572: $expl
573: <hr>
574: <address><a href = "http://httpi.floodgap.com/">httpi/$VERSION</a>
575: by Cameron Kaiser</address>
576: </body>
577: </html>
578: EOF
579: }
580:
581: sub hterror404 {
582: &htsponse(404, "File Not Found");
583: &hterror("File Not Found",
584: "The resource $address was not found on this system.");
585: }
586:
587: sub hterror301 {
588: &htsponse(301, "Moved Permanently");
589: &hthead("Location: @_");
590: &hterror("Resource Moved Permanently",
591: "This resource has moved <a href = \"@_\">here</a>.");
592: $keep = 0; &log; exit;
593: }
1.1 www 594:
595: for (;;) {
1.3 www 596: $addr=accept(NS,S);
597: $statiosltr = scalar localtime;
598: $statiosreq++;
599: if ($pid = fork()) {
1.5 albertel 600: $0 = "lonhttpd: (dhttpi) waiting for child process";
1.3 www 601: waitpid($pid, 0);
1.6 albertel 602: $0 = "lonhttpd: (dhttpi) on ANY:$port_to_use, last request " .
1.3 www 603: scalar localtime;
604: } else {
1.5 albertel 605: $0 = "lonhttpd: (dhttpi) child switching to socket";
1.3 www 606: open(STDIN, "<&NS");
607: open(STDOUT, ">&NS");
608: &master;
609: exit;
610: }
1.1 www 611: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>