Simple HTTP server in GAWK

Hi,

Not sure if this post belongs to this forum but I have been trying every so often to setup a simple http server in awk. After a couple of try and errors I finally came across this:
REMCONF - TCP/IP Internetworking With `gawk'

This tutorial is not to cut and paste without change, so here is a complete gawk snipet that creates a pseudo-server on any low-end configured *nix box running gawk.

This particular example could be used to access/modify a remote config file on a router/firewall running *nix.

Save this to a file, say myserver.awk and run it:

awk -f myserver.awk

Than from your browser:

http://localhost:8080

Amazing what you can do with gawk!

The code:

function SetUpServer() {
  TopHeader = "<html><title>Remote Configuration</title>"
  TopDoc = "<body>\
  <h2>Please choose one of the following actions:</h2>\
  <UL>\
  <li><a href=" MyPrefix "/AboutServer>About this server</a></li>\
  <li><a href=" MyPrefix "/ReadConfig>Read Configuration</a></li>\
  <li><a href=" MyPrefix "/CheckConfig>Check Configuration</a></li>\
  <li><a href=" MyPrefix "/ChangeConfig>Change Configuration</a></li>\
  <li><a href=" MyPrefix "/SaveConfig>Save Configuration</a></li>\
  </UL>"
  TopFooter  = "</body></html>"
  if (ConfigFile == "") ConfigFile = "config.asc"
}


function HandleGET() {
  if(MENU[2] == "AboutServer") {
    Document  = "This is a GUI for remote configuration of an\
    embedded system. It is is implemented as one GAWK script."
  } else if (MENU[2] == "ReadConfig") {
    RS = "\n"
    while ((getline < ConfigFile) > 0)
    config[$1] = $2;
    close(ConfigFile)
    RS = "\r\n"
    Document = "Configuration has been read."
  } else if (MENU[2] == "CheckConfig") {
    Document = "<table border=1 cellpadding=5>"
    for (i in config)
      Document = Document "<tr><td>" i "</td>" \
       "<td>" config "</td></tr>"
      Document = Document "</table>"
  } else if (MENU[2] == "ChangeConfig") {
    if ("Param" in GETARG) {           # any parameter to set?
      if (GETARG["Param"] in config) {  # is  parameter valid?
        config[GETARG["Param"]] = GETARG["Value"]
        Document = (GETARG["Param"] " = " GETARG["Value"] ".")
      } else {
        Document = "Parameter <b>" GETARG["Param"] "</b> is invalid."
      }
    } else {
    Document = "<form method=\"GET\"><h4>Change one parameter</h4>\
     <table border cellpadding=5>\
     <tr><td>Parameter</td><td>Value</td></tr>\
     <tr><td><input type=text name=Param value=\"\" size=20></td>\
       <td><input type=text name=Value value=\"\" size=40></td>\
     </tr></table><input type=submit value=\"Set\"></form>"
    }
  } else if (MENU[2] == "SaveConfig") {
    for (i in config)
    printf("%s %s\n", i, config) > ConfigFile
    close(ConfigFile)
    Document = "Configuration has been saved."
  }
}

function CGI_setup( method, uri, version, i) {
  delete GETARG;         delete MENU;        delete PARAM
  GETARG["Method"] = $1
  GETARG["URI"] = $2
  GETARG["Version"] = $3
  i = index($2, "?")
  # is there a "?" indicating a CGI request?
  if (i > 0) {
   split(substr($2, 1, i-1), MENU, "[/:]")
   split(substr($2, i+1), PARAM, "&")
   for (i in PARAM) {
    j = index(PARAM, "=")
    GETARG[substr(PARAM, 1, j-1)] =  substr(PARAM, j+1)
   }
  } else {    # there is no "?", no need for splitting PARAMs
    split($2, MENU, "[/:]")
  }
 }
 

BEGIN {
  if (MyHost == "") {
     "uname -n" | getline MyHost
     close("uname -n")
  }
  if (MyPort ==  0) MyPort = 8080
  HttpService = "/inet/tcp/" MyPort "/0/0"
  MyPrefix    = "http://" MyHost ":" MyPort
  SetUpServer()
  while ("awk" != "complex") {
    # header lines are terminated this way
    RS = ORS = "\r\n"
    Status  = 200          # this means OK
    Reason  = "OK"
    Header  = TopHeader
    Document = TopDoc
    Footer  = TopFooter
    if       (GETARG["Method"] == "GET") {
      HandleGET()
    } else if (GETARG["Method"] == "HEAD") {
      # not yet implemented
    } else if (GETARG["Method"] != "") {
      print "bad method", GETARG["Method"]
    }
    Prompt = Header Document Footer
    print "HTTP/1.0", Status, Reason      |& HttpService
    print "Connection: Close"       |& HttpService
    print "Pragma: no-cache"              |& HttpService
    len = length(Prompt) + length(ORS)
    print "Content-length:", len          |& HttpService
    print ORS Prompt                      |& HttpService
    # ignore all the header lines
    while ((HttpService |& getline) > 0)
      ;
    # stop talking to this client
    close(HttpService)
    # wait for new client request
    HttpService |& getline
    # do some logging
    print systime(), strftime(), $0
    # read request parameters
    CGI_setup($1, $2, $3)
  }
}