If the above paragraph reads like gobbledegook, please refer yourself to the reference section for relevant reading.
JemTek CGI performs the following:
I appreciate user feedback. Problems with the software or errors in the documentation? Let me know! Every attempt will be made to address enquiries.
Direct email to Jerome Munchenberg at jerome@jemtek.com.au
Direct enquires to Jerome Munchenberg at jerome@jemtek.com.au
tar xvf jmtk_cgi.tar
unzip -d jmtk_cgi.zip
cgi.h - JemTek CGI library header file cgi.c - JemTek CGI library source code cgi.htm - Users manual in html format makefile - Makefile to build the library and sample application. test_cgi.c - Sample CGI application source code test_cgi.htm - Sample HTML document
cd jmtk_cgi makeOnce the make is complete four new files should exist; two object files cgi.o and test_cgi.o which may be removed, the JemTek CGI library, libcgi.a, and the sample CGI application binary, test_cgi.
The HTML document demonstrates the use of all the available HTML query submission methods via a number of simple examples. In response to a query submission, the CGI application returns a HTML page which shows the submitted data parsed into pairs and the values of CGI-specific environment variables. The operation of this application is so general it can be used with any HTML document submitting a request, yet the output is extensive enough to be useful as a simple debugging aid.
To try the sample application in your own environment:
#include "cgi.h"The JemTek CGI library requires you to declare the global variable cgiDebug of type character pointer. This variable makes possible the debugging of CGI applications. See the section on debugging applications for further information but for standard applications it is enough just to simply declare the variable:
#include "cgi.h" char *cgiDebug;The JemTek CGI library uses the main() function to do important initialisation tasks before passing control to your application. Instead of using the main() function, the body of your application should be placed in the cgiMain() function. Attempting to use your own main() function will result in linking problems.
#include "cgi.h" char *cgiDebug; int cgiMain() { ... your application here ... }Within cgiMain() you must indicate to the browser the MIME type of the document your application will return. This is accomplished by the various cgiHeader.. functions, one of which must be invoked. The most common response is another HTML document:
#include "cgi.h" char *cgiDebug; int cgiMain() { cgiHeaderContent("text/html"); ... your application here ... }If your application is returning a HTML document, you can use the convenient HTML wrapper functions cgiHtmlHead() and cgiHtmlTail():
#include "cgi.h" char *cgiDebug; int cgiMain() { cgiHeaderContent("text/html"); cgiHtmlHead("_your_app_title_"); ... your application here ... cgiHtmlTail(); }Without the wrappers the equivalent code would be:
#include "cgi.h" char *cgiDebug; int cgiMain() { cgiHeaderContent("text/html"); cgiPrintf("<HTML>"); cgiPrintf("<HEAD>"); cgiPrintf("<TITLE>_your_app_title_</TITLE>"); cgiPrintf("</HEAD>"); cgiPrintf("<BODY>"); ... your application here ... cgiPrintf("</BODY>"); cgiPrintf("</HTML>"); fflush(stdout); }You may have noticed the use of cgiPrintf in the above code snippet. This function should be used instead of printf as it is specifically written for use in CGI applications.
A request submitted by either the GET or POST method sends a stream of var=val pairs. The ISINDEX method only submits vals and in this instance the library automatically creates a var=val pair by setting var to isindex.
var=val pairs can be displayed with a call to cgiDisplayPairs(). A number of functions are available to retrieve and query these pairs:
int val; ... val = cgiFormCntVar("isindex");As another example, say we have a multiple select listbox with the name box. The following code retrieves each value selected by the user:
char **vals; int val, cnt; ... val = cgiFormGetValMulti("box", &vals); if (val==0) cgiPrintf("The user selected nothing from the multi select listbox!"); else { cgiPrintf("The following was selected from the multi select listbox!"); for (cnt=0; cnt<val; cnt++) cgiPrintf("%s", vals[cnt]); }There are many other available library functions to aid the creation of a CGI application. For a list of what functionality is available, please browse the library reference.
Once your code is complete and you are ready to build an executable, compile your code by linking to the JemTek CGI library:
$(CC) -Ljmtk_cgi -lcgi -o _your_exe_ _your_src_Depending on how your administrator has configured the server environment your application should have the filename extension .cgi and/or be placed in the appropriate CGI script directory, usually named cgi-bin. Furthermore, ensure the URL in your form correctly indicates the location of your CGI application.
All things being equal, submitting a request via your HTML page should result in your CGI application responding with a new page. If the response was not quite what you expected please review the sections on debugging and problem solving.
JemTek CGI provides a method of capturing an instance of this environment to file. With the environment thus preserved, a CGI application can be executed any number of times from the command-line or debugger as though it had been launched by the WEB server itself.
The following steps capture and replay an environment:
The JemTek CGI library requires you to declare the variable cgiDebug as a global character pointer. For normal operation this variable should be left uninitialised.
#include "cgi.h" char *cgiDebug; int cgiMain() { ... your application here ... }An environment can be captured by initialising this variable to the string SAVE=_env_file_ where _env_file_ is the file in which the environment is to be saved. Make sure the file path is absolute and writable by the WEB server.
#include "cgi.h" char *cgiDebug = "SAVE=_env_file_"; int cgiMain() { ... your application here ... }Build the application and place the binary in the appropriate CGI directory. Open your HTML document in a browser and submit a request. You should receive a response stating whether or not the environment was successfully captured.
Once the environment has been captured, modify the cgiDebug string by replacing SAVE with LOAD. Rebuild your application.
#include "cgi.h" char *cgiDebug = "LOAD=_env_file_"; int cgiMain() { ... your application here ... }You can now execute your application from the command-line or debugger as though launched by the WEB server!
void | cgiDisplayEnv | (); |
void | cgiDisplayPairs | (); |
char* | cgiEncodeSys | (char *data); |
char* | cgiEncodeUrl | (char *data); |
int | cgiFormCmpVal | (char *var, char *val); |
int | cgiFormCmpValMulti | (char *var, char len, char **vals); |
int | cgiFormCntVar | (char *var); |
char* | cgiFormGetVal | (char *var); |
int | cgiFormGetValMulti | (char *var, char ***vals); |
cgiHeader.. | ||
int | cgiHeaderContent | (char *mimeType); |
int | cgiHeaderLocation | (char *redirectUrl); |
int | cgiHeaderStatus | (int statusCode, char *statusReason, char *statusMesg); |
int | cgiHeaderNonParse | (int statusCode, char *statusMesg, char *mimeType); |
int | cgiHtmlHead | (char *title); |
int | cgiHtmlTail | (); |
int | cgiImageOk | (); |
int | cgiLoad | (char *file); |
extern int | cgiMain | (); |
int | cgiPrintf | (char *fmt, ...); |
Syntax | void cgiDisplayEnv(); |
---|---|
Function | Display the cgiEnv structure in HTML format. |
Remarks | A number of environment variables are set by the WEB server before launching a CGI program. These variables are placed in the cgiEnv structure during initialisation. This function displays the contents if the cgiEnv structure in HTML format. |
Return | None. |
See Also | cgiDisplayPairs() |
Syntax | void cgiDisplayPairs(); |
---|---|
Function | Display the form data pairs in HTML format. |
Remarks | CGI data is parsed into var=val pairs during initialisation. This function displays these pairs in HTML format. Square brackets are placed around the value field to help indicate any white spaces. |
Return | None. |
See Also | cgiDisplayEnv() |
Syntax | char *cgiEncodeSys(char *data); |
---|---|
Function | Escape shell metacharacters in a string. |
Remarks | This function is useful as a security precaution if user input is allowed in calls to low-level functions such as system or popen within a CGI program. All Bourne and C shell meta-characters are escaped. |
Return | Success: A pointer to the encoded string. |
Failure: NULL. |
Syntax | char *cgiEncodeUrl(char *data); |
---|---|
Function | URL-encode a string. |
Remarks | Converts space characters to plus and non alpha-numeric characters to their hexadecimal equivalent. The resultant string can be used within a URL. |
Return | Success: A pointer to the encoded string. |
Failure: NULL. |
Syntax | int cgiFormCmpVal(char *var, char *val); |
---|---|
Function | Compares the value of a variable with another value. |
Remarks | Find each occurrence of the variable, var and compare it's value with the supplied value, val. Function is successful if an exact match is made. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti() |
Syntax | int cgiFormCmpValMulti(char *var, char len, char **vals); |
---|---|
Function | Compares the value of a variable with an array of values. |
Remarks | Find each occurrence of the variable, var and compare it's value with the supplied array of values, vals, having len entries. Function is successful if an exact match is made. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti() |
Syntax | int cgiFormCntVar(char *var); |
---|---|
Function | Test for a variable. |
Remarks | Searches for all instances of the variable, var. Function is successful if an exact match is found. |
Return | Success: The number of instances of var. |
Failure: 0. | |
See Also | cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti() |
Syntax | char *cgiFormGetVal(char *var); |
---|---|
Function | Return the value of the given variable. |
Remarks | Searches for the first instance of the variable, var, and if successful, return it's associated value. |
Return | Success: A pointer to a string. |
Failure: NULL. | |
See Also | cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti() |
Syntax | int cgiFormGetValMulti(char *var, char ***vals); |
---|---|
Function | Return multiple values of the given variable. |
Remarks | Searches for all instances of the variable, var and if successful, places all it's associated values in vals, returning the number of matches. |
Return | Success: The number of strings placed into vals. |
Failure: 0, with vals set to NULL. | |
See Also | cgiFormCmpVal(), cgiFormCmpValMulti(), cgiFormGetVal(), cgiFormGetValMulti() |
Syntax | int cgiHeaderContent(char *mimeType); |
---|---|
int cgiHeaderLocation(char *redirectUrl); | |
int cgiHeaderStatus (int statusCode, char *statusReason, char *statusMesg); | |
int cgiHeaderNonParse (int statusCode, char *statusMesg, char *mimeType); | |
Function | Identify the type of document the CGI program will produce. |
Remarks | A cgiHeader.. function must be invoked before outputting any data. An attempt to invoke a cgiHeader.. function a second time will fail. As a further measure, calls to cgiPrintf will fail until a cgiHeader.. function is invoked. If a cgiHeader.. function is not invoked, the CGI program responds with an appropriate error. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderStatus(), cgiHeaderNonParse() |
Syntax | int cgiHeaderContent(char *mimeType); |
---|---|
Function | Indicate the MIME type of the document. |
Remarks | Usually a CGI program responds with a document, in which case it must be initially identified as a MIME type, typically "text/html". Common MIME types are "text/html", "text/plain", "image/gif", "audio/basic" and "video/mpeg". |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHeader.., cgiHeaderLocation(), cgiHeaderStatus(), cgiHeaderNonParse() |
Syntax | int cgiHeaderLocation(char *redirectUrl); |
---|---|
Function | Redirect the browser to a new resource. |
Remarks | Specifies that the CGI program is returning a reference to the document, redirectUrl, rather than producing a document. In this instance, no further output is required. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHeader.., cgiHeaderContent(), cgiHeaderStatus(), cgiHeaderNonParse() |
Syntax | int cgiHeaderStatus (int statusCode, char *statusReason, char *statusMesg); |
---|---|
Function | Return an error status. |
Remarks | Specifies that the CGI program is returning with an error rather
than producing a document. The statusCode (a 3-digit number) and
statusReason (a string briefly identifying the error) define the
HTTP status line (as specified in the protocol) to send to the client.
The statusMesg is a user-defined string further clarifying the
error. The output looks something like this:
Content-type: text/html Status: 500 Internal Server Error <H2>500 Internal Server Error</H2> <H3>Sorry, could not allocate memory or some such</H3> |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHeader.., cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderNonParse() |
Syntax | int cgiHeaderNonParse (int statusCode, char *statusMesg, char *mimeType); |
---|---|
Function | Indicate that the document is to be sent directly to the client with minimal buffering. |
Remarks | Usually the output of a CGI program is sent to the server and then on to the client. In this instance the server is by-passed. Server documentation specifies that non-parse documents should be named with the prefix nph-. The statusCode (a 3-digit number) and statusReason (a string briefly identifying the error) define the HTTP status line (as specified in the protocol) to send to the client. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHeader.., cgiHeaderContent(), cgiHeaderLocation(), cgiHeaderStatus() |
Syntax | int cgiHtmlHead(char *title); |
---|---|
Function | Initialises a HTML document. |
Remarks | Essentially a wrapper for the initialisation of a HTML document, the
function encapsulates the following calls:
cgiPrintf("<HTML>"); cgiPrintf("<HEAD>"); cgiPrintf("<TITLE>title</TITLE>"); cgiPrintf("</HEAD>"); cgiPrintf("<BODY>");This function will fail until a cgiHeader..() function is invoked. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHtmlTail() |
Syntax | int cgiHtmlTail(); |
---|---|
Function | Finalises a HTML document. |
Remarks | Essentially a wrapper for the finalisation of a HTML document, the
function encapsulates the following:
cgiPrintf("</BODY>"); cgiPrintf("</HTML>");This function will fail until cgiHtmlHead() has been invoked. |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiHtmlHead() |
Syntax | int cgiImageOk(); |
---|---|
Function | Determines the browser's ability to view images. |
Remarks | Examines the cgiEnv.httpAccept environment variable for an instance of the MIME type image/.... |
Return | Success: 1. |
Failure: 0. | |
See Also | cgiEnv |
Syntax | int cgiLoad(char *file); |
---|---|
Function | Copy an external file into the current document. |
Remarks | Opens a file and copies its contents to stdout. Useful for displaying existing HTML or text documents. |
Return | Success: 1. |
Failure: 0. |
Syntax | extern int cgiMain(); |
---|---|
Function | Entry point for the CGI application. |
Remarks | The JemTek CGI library uses the main() function to do
important initialisation tasks before passing control to a CGI
application. The CGI application code should instead be written within
the cgiMain function.
Initialisation tasks undertaken by the JemTek CGI library involve saving or loading debug environments, determining the request method, parsing data into var=val pairs, and setting values in the cgiEnv structure. An ISINDEX method does not submit var=val pairs, only vals. The library creates a var=val by setting var to isindex. |
Return | Success: 1. |
Failure: 0. |
Syntax | int cgiPrintf(char *fmt, ...); |
---|---|
Function | Print variable argument strings to stdout. |
Remarks | This function is identical to the standard printf but with
added functionality specifically suited to CGI applications.
|
Return | Success: 1. |
Failure: 0. |
extern char *cgiDebug;
struct { char *authType; int contentLength; char *contentType; char *gatewayInterface; char *httpAccept; char *httpHost; char *httpReferer; char *httpUserAgent; char *pathInfo; char *pathTranslated; char *queryString; char *remoteAddr; char *remoteHost; char *remoteIdent; char *remoteUser; char *requestMethod; char *scriptName; char *serverName; char *serverPort; char *serverProtocol; char *serverSoftware; } cgiEnv;
Syntax | extern char *cgiDebug; |
---|---|
Remarks | This variable must be declared globally within your CGI application and permits the debugging of the application. For normal operation this variable should be left uninitialised. However, if initialised to "SAVE=_env_file", the application will save the CGI environment to the specified file. Initialised to "LOAD=_env_file_" the application will reload a saved environment. For more information please read the section on debugging applications. |
Syntax |
struct { char *authType; int contentLength; char *contentType; char *gatewayInterface; char *httpAccept; char *httpHost; char *httpReferer; char *httpUserAgent; char *pathInfo; char *pathTranslated; char *queryString; char *remoteAddr; char *remoteHost; char *remoteIdent; char *remoteUser; char *requestMethod; char *scriptName; char *serverName; char *serverPort; char *serverProtocol; char *serverSoftware; } cgiEnv; |
||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Remarks | The programmer is provided with predefined global variables of CGI-
specific environment variables. These should be used instead of calls
to getenv. The variables are never null, but may point to
an empty string. Please note that the http... variables are not
always set by browsers. The fields are as follows:
|