CGI

The web server allows writing of pseudo-CGI programs. This is helpful in order to modify the functionality of the server without having to recompile it and reflash it.

One way to implement CGI is, of course, the C language callback mechanism described above: This assumes, of course, that all the callbacks are written by compile time and cannot be modified later on. Another way to perform the same functionality is the use of a library in the form of an object file. These object files reside in the file system and are loaded, executed and unloaded on demand.

Yet a third way is the use of a scripting language. Since full fledged implementation of the most popular scripting languages such as Python or Perl are too large for most embedded systems, a slim down implementation of tcl was chosen for this server. Most of the tcl functionality is still there, and makes writing cgi a lot easier.

In order to limit the footprint of the operating system support for both the objloader and the tcl script for dealing with cgi files can be independently selected out. Tcl support in particular increases the memory requirements considerably.

CGI via objloader

In order to use the cgi mechanism the CYGPKG_OBJLOADER must be included when building the operating system. This will enable the proper option in the configuration tool and if selected, the necessary code will be compiled in the eCos kernel. The user will then have to compile the necessary libraries and place them in the file system under a directory defined by CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR. When a request is made, the web server checks if the root directory of the requested URL is inside the CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR directory. If so, the server assumes that the user requested a cgi file and looks into the directory to see if a library by the same name is present, and if so load it and tries to execute a function inside the library with the following prototype:

void exec_cgi(CYG_HTTPD_STATE *)

The pointer CYG_HTTPD_STATE* gives access to the socket data: The user will use this pointer to access the 'outbuffer' and use it to copy data to send data out.

When using the OBJLOADER package within the HTTP server a number of functions are automatically added to the externals table of the OBJLOADER package. These functions are likely to be used inside the library and the relocator need to have a pointer to them. In order to add more functions, see the OBJLOADER documentation. The complete list of the functions automatically added is:

  • cyg_httpd_start_chunked()

  • cyg_httpd_write_chunked()

  • cyg_httpd_end_chunked()

  • cyg_httpd_write()

  • cyg_httpd_find_form_variable()

  • cyg_httpd_find_ires()

  • cyg_httpd_send_ires()

  • diag_printf()

  • cyg_httpd_format_header()

  • cyg_httpd_find_mime_string()

Every time the web client issues a GET or POST request for a file with an extension of '.o'in the /cgi-bin directory (or whatever path the user chooses to hold the libraries) then the library by that name is loaded, run and when the execution is over, it is dumped from memory. The library must be compiled separately, using the same toolchain used to compile the server and then added to the file system.

In order to reduce the footprint of the server, CGI through OBJLOADER can be compiled out by unchecking CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER in the configuration tool.

CGI via the simple tcl interpreter

A small tcl interpreter has been added to the web server, and it can be used to write simple cgi scripts. The interpreter is admittedly very minimal, and it is only useful for very simple applications, but it is an excellent starting point for further development.

In order for the scripting language to be useful, it has to access the form variables passed on during the GET or POST request. Because of this, all form variables registered with the CYG_HTTPD_FVAR_TABLE_ENTRY() macro are accessible via tcl. For example, if we have registered a form variable called foo, and during the GET request we are defining foo as being "1":

GET /myForm.cgi?foo=1

then tcl will be able to access the variable foo as $foo. The data in the body of a POST request is also accessible through the use of the variable $post_data. This is useful if the data is not in "multipart/form-data" and tcl has to perform any type of processing on the data itself.

In order to send back a response to the client a few functions have been added to the interpreter. These functions are:

start_chunked

start_chunked "extension";

"extension" is a string used to search the table of the mime types. For example, to send back to the client an HTML file, we can use: start_chunked "html";

write_chunked

write_chunked content;

content is a string to send back to the client.

end_chunked

end_chunked;

No parameters. Send back an end of frame to the client.

tcl hello world example

The following example demonstrates how to send a log file in the file /ram/log to a web client. It replaces newline characters with <br> so that it is formatted on the browser correctly.

start_chunked "html";

set fp [aio.open "/ram/log" r];
$fp seek 0 end;
set fsize [$fp tell];
$fp seek 0 start;
set data "abcxxx";
set data [$fp read $fsize];
$fp close;
set data [string map {\n <br>} $data];

set datax "";
append datax "<html><body>" $data "</body></html>";

write_chunked $datax;
end_chunked;

The above file should exist on a filesystem on the embedded target within its cgi-bin directory, for example as /cgi-bin/hello.tcl. Thereafter it may be accessed at the URL http://TARGET_NAME/cgi-bin/hello.tcl.

2017-02-09
Documentation license for this page: Open Publication License