;-*- Mode: MIDAS -*- TITLE WEBSER ; Simple Web Server -- install as DEVICE;TCP SYN120 PORT==80. ; Official TCP port for WWW Server A=1 B=2 C=3 D=4 OC=7 U1=10 U2=11 U3=12 U4=13 T=14 TT=15 P=17 NETI==1 NETO==2 FILI==3 LOC 42 JSR TSINT LOC 100 ; Here we go PAT: BLOCK 40 ; Patch area PDL: BLOCK 40 ; Push down stack DEBUG: 0 ; Non-zero when debugging FILDEV: SIXBIT /DSK/ FILFN1: SIXBIT /MAIN/ FILFN2: SIXBIT />/ FILDIR: SIXBIT /.WWW./ FILTYP: ASCIZ /plain/ ; MIME text type BLOCK 5 ; For Justin TSINT: 0 ; Interrupt handler - for fatal conditions 0 JSR AUTPSY ; Any interrupt is cause for death. AUTPSY: 0 SKIPE DEBUG .VALUE .LOGOUT LOSE: 0 ; Tell loser what went wrong JRST ERR500 LOC 1000 ; Pure code only from here on .INSRT KSC;MACROS .INSRT KSC;OUT GO: MOVEI P,PDL ; Set up stack NETOPN: SYSCAL TCPOPN,[ MOVEI NETI MOVEI NETO MOVEI PORT [-1] [-1]] JSR AUTPSY ; Failed (should timeout!) MOVEI B,3*30. ; Try for 30 sec NETLOP: MOVEI A,10. .SLEEP A, SYSCAL WHYINT,[ MOVEI NETO MOVEM A MOVEM A] .LOSE %LSSYS CAIE A,%NSOPN CAIN A,%NSRFN CAIA SOJG B,NETLOP CAIG B, JSR AUTPSY ; Timed out... NETOK: OUT(,CH(NETO),OPEN(UC$IOT)) GETCMD: PUSHJ P,GETWRD ; Read command CAME A,[SIXBIT /GET/] ; command GET JSR LOSE ; else fail CAIE C,40 ; Whitespace JSR LOSE ; else fail PUSHJ P,GETCHR ; Read first character of name CAIE C,"/ ; Should be a leading slash JSR LOSE ; else fail MOVEI B,FILFN1 ; first fn first GETFN: PUSHJ P,GETWRD ; Get one word JUMPE A,FILOPN ; Done GETFN2: CAIN C,"; ; If it's terminated by a semicolon MOVEM A,FILDIR ; then it's a directory CAIN C,": ; If it's terminated by a colon MOVEM A,FILDEV ; then it's a device CAIE C,40 ; If it's not terminated by whitespace JRST GETFN ; then continue MOVEM A,@B ; Save FNn AOS B ; Next FNn CAMLE B,FILDIR ; If past the directory CAIA ; Then fail %%% cut off for debugging JRST GETFN ; Next word FILOPN: SYSCAL OPEN,[ ; Open target file [.UAI,,FILI] ; Unit Ascii Input FILDEV FILFN1 FILFN2 FILDIR] JRST ERR404 ; or fail GETTYP: .IOT FILI,C ; get first char CAIE C,"< ; look for JRST SNDHDR ; no, text MOVE T,[ASCIZ /html/] ; yes, html MOVEM T,FILTYP SNDHDR: OUT(,("HTTP/1.0 200"),CRLF) OUT(,("Content-Type: text/"),TZ(FILTYP),CRLF,CRLF) SNDFIL: CAIE C,^C ; Skip spurious .IOT NETO,C ; We already have the first char .IOT FILI,C ; Get another char JUMPGE C,SNDFIL ; -1,,^C is EOF DONE: .CLOSE FILI, ; Clean up. .NETS NETO, ; Force the output. .CLOSE NETO, ; Disconnect. .CLOSE NETI, ; Disconnect. .LOGOUT ERR404: OUT(,("HTTP/1.1 404 No such file or directory."),CRLF) OUT(,("Content-Type: text/html"),CRLF,CRLF) OUT(,("
"),CRLF) OUT(,("