Script started on Sun May 12 17:52:06 2002
ws02% cat README

README for CSCI-e215

Russell J Lowke

Assignment 6: "wsng"

______

files: wsng.h          // header file for wsng
       wsng.c          // wsng main .c code
       socklib.h       // header file for socklib
       socklib.c       // socklib .c code
       varlib.h        // header file for varlib
       varlib.c        // varlib .c code
       Makefile        // makefile to compile wsng
       Plan            // general plan for wsng
       typescript      // typescript for wsng
       README          // this file
______

Notes:          For question 6 "add one more error case" I added
                error #403 using do_403(), which checks the permissions on
                a file to see if it may be read.
ws02% cat Plan

DESIGN OUTLINE for CSCI-e215 Assignment 6
Russell J Lowke

    wsng.c
    
      AUTHOR: Russell Lowke
   CSCIE-215: Assignment Six

       Usage: wsng [portnumber [rootdir] ]

 Description: Enhance Bruces ws.c web server so it will:
                 1. Return the date, server name & version
                   see head() function.
                 2. Support the HEAD method command 
                   see process_rq() and do() functions.
                 3. reads filetype and extensions from external file
                   see initExtTable() and  readTable() functions.
                 4. Produce directory listings with links
                   see do_ls() function.
                 5. look for index.html
                   see do_ls() function.
                 6. Handle an extra error
                   see process_rq() and do_403() functions.
                 7. Cleanup Zombies
                   see initAlarm() and killZombies() functions.
                 8. handle QUERY_STRING
                   see initVarTable() and extractQuery() functions.         

             Main sends initialize calls to setup the alarm, the variable table, read
              from the external text file the filetypes, and to initalize
              the socket. Main then sits in a loop reading incoming socket
              requests, which are sent to process_rq to be delt with.
              Alarm is set to periodically trigger killZombies(), which
              cleans up any dead(finished) processes.  
              process_rq() forks to a new process, then breaks the call into
              [cmd] and [item] parts.  The [cmd] should be either a GET or
              HEAD while [item] contains the bulk of the call.
              extractQuery() is called on [item] to extract any query
              variables that may have been sent at the end of [item], these
              being delimited by a '?'.  [item] is determined to be either
              a directory, a cgi, or a file format, and sent to the
              appropriate do() to be processed.
              ...for directories:
                 do_ls() will chdir into the directory, then search for an
              index.html.  If no index.html is found then html is generated to
              describe the contents of the directory, with links to each item,
              including item size and last modified dates.
              ...for cgi:
                 do_exec() is called, which exec's the cgi
              ...for files:
                 do_cat() is called, which checks through the table
              of extension names v filetypes.  When the right filetype is
              known this information is passed to head() to be passed at
              the beginning of the reply, then the rest of the file follows,
              reading via getc() and sending via putc().
              ...for errors.  Three important errors are handled.
               501 - unimplemented command.
                      basically a syntax error
               403 - Permissions won't allow.(q 6, "add one more error case")
                      uses stat(f,&info) and (S_IRUSR & info.st_mode) to
                      check the mode of the file and see if permissionas
                      are set to allow a read
               404 - item not found.
                      item requested is not found


         General functions are...
                main - Calls four initialization functions for setting
                       the alarm, the var table, the .ext table, and to get a 
                       socket. The Main loop then waits for socket requests.
                       When a request is recieved via socket it goes to
                       process_rq for processing
           initAlarm - initialization for alarm, sets it to call killZombies
                       every 40 seconds or so (ZOMBIEFIX)
        initVarTable - initialization of environment table using varlib.c
                       Adds all the external values from [environ]
                       into the var table.  Decalres REQUEST_METHOD
                       and QUERY_STRING as vars to be exported to environ
          initSocket - Changes to the root dir, makes a server socket,
                       gets the hostname.
        initExtTable - An external text file called "txtTable" contains a
                       list of all the extension (.ext) names and their
                       corresponding file types (text/html).
                       readTextFile reads this file and tabulates
                       the data into a struct called mFileTypes.
          set_ticker - Called by initAlarm
                       arranges for the interval timer to issue
                       SIGALRM's at regular intervals
         killZombies - Called periodically via alarm ( see set_ticker() )
                       uses waitpid with a WNOHANG option. This will return a 
                       positive pid for all zombies,
                       and clean them in the process.
        extractQuery - Str [item] might contain a '?', after which a
                       query string is passed as typically used for cgi
                       scripts. extractQuery() finds the '?' delimeter and,
                       if found sets the environment var QUERY_STRING =
                       whatever is after the '?'
          process_rq - Process all requests.
                       Request is handled in a new child process (fork)
                       the parent simply returns and looks for the next 
                       request. The child must exit, so the exit(0); 
                       calls are very important here. Scanf is used to
                       break the request into command [cmd] and argument [arg]
                       the arg is further passed through modify_argument,
                       to verify path, and extractQuery, to extract cgi?query
                       information at end of the request.
                       A flag called cmdType stores if cmd is of type
                       HEAD or GET. Finallly, [item] is passed to one of
                       various "do" functions that handle the request.
     modify_argument - For security, remove all ".." components in paths
                       and cleanup, if arg is "/" convert to "."
              header - Use by all the "do" functions
                       Sends a standard header to fp as the beginning
                       of a reply.
           cannot_do - do_501 unimplemented HTTP command
              do_403 - Permisions won't allow, so block
              do_404 - Item requested is not found
              do_cat - sends back contents after a header
             do_exec - exec a program/cgi and send it down the pipe
               do_ls - Looks for index.html in directory, if found, 
                       sends a do_cat of the index. Otherwise do_ls creates 
                       a menu of links of all the items in the 
                       directory by generating html.
                       The size and last modified date
                       of each item is displayed also.
           readTable - looks through the table [mFileTypes] for .ext [str]
             usrRead - Tests if file [f] is user readable
                       determined by the st_mode permissions
                       i.e. chmod foo +r
         rfc822_time - return a time string suitable for web servers
                       such as:  Sun, 06 Nov 1994 08:49:37 GMT
                       uses gmtime() to get struct
                       then uses asctime to translate to English
                       then rearranges using sprintf

       Notes:          For question 6 "add one more error case" I added
                       do_403(), which checks the permissions on a file
                       to see if it may be read.

ws02% touch *.c

ws02% cat Makefile

#
# comments start with a # sign
#
# each item in the make file consists of
# three things:  a product, its ingredients and how to make it
#
# gcc -o test test.c -lcurses


CC = gcc -g -Wall
        
wsng: wsng.o varlib.o socklib.o
        $(CC) wsng.o socklib.o varlib.o -o wsng
        
wsng.o: wsng.c wsng.h
        $(CC) -c wsng.c

varlib.o: varlib.c varlib.h
        $(CC) -c varlib.c
        
socklib.o: socklib.c socklib.h
        $(CC) -c socklib.c
ws02% make

gcc -g -Wall -c wsng.c
gcc -g -Wall -c varlib.c
gcc -g -Wall -c socklib.c
gcc -g -Wall wsng.o socklib.o varlib.o -o wsng
ws02% ./wsng

ws1 started.  host=ws02.fas.harvard.edu port=9666
got a call: request = GET / HTTP/1.0

got a call: request = GET /dir1/ HTTP/1.0

got a call: request = GET /dir1/file1.html HTTP/1.0

got a call: request = GET /dir2/ HTTP/1.0

got a call: request = GET /dir2/picture.jpeg HTTP/1.0

got a call: request = GET /dir2/hello.c HTTP/1.0

got a call: request = GET /dir2/hello.cgi HTTP/1.0

got a call: request = GET /dir2/showcal.cgi HTTP/1.0

got a call: request = GET /dir2/months.html HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?1 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?2 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?3 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?4 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?5 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?6 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?7 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?8 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?9 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?10 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?11 HTTP/1.0

got a call: request = GET /dir2/showcal.cgi?12 HTTP/1.0

got a call: request = GET /file1.html HTTP/1.0

got a call: request = GET /file2.txt HTTP/1.0

got a call: request = GET /file3.jpg HTTP/1.0

got a call: request = GET /file4.gif HTTP/1.0

got a call: request = GET /file_list.html HTTP/1.0

got a call: request = GET /test.txt HTTP/1.0

got a call: request = GET /file_list.html HTTP/1.0

got a call: request = GET /file1.html HTTP/1.0

got a call: request = GET /file4.gif HTTP/1.0

got a call: request = GET /dir1/ HTTP/1.0

got a call: request = GET /dir2/ HTTP/1.0



ws02% 

ws02% ls

Makefile     bavckupIdea  myLib.c      socklib.o    varlib.h     ws.c         wsng.h
Plan         dobackup     rfc1945.txt  txtTable     varlib.o     ws.o         wsng.o
README       foo.html     socklib.c    typescript   web-time.c   wsng
backup       install.log  socklib.h    varlib.c     ws           wsng.c
ws02% exit

exit

script done on Sun May 12 17:54:51 2002
