Copyright (c) 1998-2000 Carson S.K. Harding $Date: 2000/12/11 23:49:45 $ THE CGL LIBRARY Introduction: ============= The cgl library is an ANSI C CGI library for various tasks associated with writing CGI programs in C, most notably handling input from CGI forms. The routines are easy to use, but if desired, access to their underlying mechanisms is also available for greater control over their behaviour. The quick first step is to call cgl_init() at the beginning of the program. This stores the CGI environment into cgl_Env, and loads any form data. Form data values can then be accessed with cgl_getvalue() or cgl_getvalues(). When finished, close up by calling cgl_freedata() to release the form and environment data. Along the way, there are a number of utility functions for generating headers, various HTML tags (hidden, headings, etc.) and a couple of general purpose functions to play catch-up to what one usually has in the syntax of a scripting language such as Perl (cgl_addstr()). The hashed list data structure used to store and access form data can be used in a fashion similar to an associative-array; hopefully this is another convenience. The library is ANSI C, but I have not tested or tried it on anything other than Unix. It runs under OpenBSD, Solaris, and AIX; on Alpha, Sparc, and RS/6000. cgl_mkpath() may need a change if building for some other OS type. Cgl functions try to avoid allocating storage. The hashed list functions do not duplicate strings they are passed, they merely store the pointers they are given. Except for the structures internal to the library, managing storage is always the caller's responsibility. It should be easy enough to create wrapper functions for, say, cgl_insertnode() that strdup() name and value and pass the new pointers if that is what is desired. Global Variables: ================= cglEnv *cgl_Env cgllist *cgl_Formdata cgllist *cgl_Cookies int cglerrno int cglsyserr extern char *cglerrlist[]; Functions: ========== Top Level Data Access Functions: -------------------------------- int cgl_init(void) cgl_init() calls cgl_initenv(), cgl_initformdata(), and cgl_initcookies() in order. If any one of these fails, cgl_init() returns -1. int cgl_initenv(void) cgl_initenv() allocates and initializes the global cgl environment structure cgl_Env (defined in cgl.h). Returns 0 on success; -1 on failure, and setting cglerrno. Members of cgl_Env are set to point to their corresponding environment variables, or to an empty string (rather than NULL) if they do not exist. int cgl_initformdata(void) cgl_initformdata() reads the form data (whether GET or POST) and parses it into the hashed list cgl_Formdata. cgl_initformdata() returns 0 on success, and -1 on error, setting cglerrno. cgl_initenv() must be called before cgl_initformdata(). int cgl_initcookies(void) cgl_initcookies() reads the cookie string (if one exists) and parses it into the hashed list cgl_Cookies. cgl_initcookies() returns 0 on success, and -1 on error, setting cglerrno. cgl_initenv() must be called before cgl_initcookies(). void cgl_freeall(void) cgl_freeall() calls cgl_freeenv(), cgl_freeformdata(), and cgl_freecookies(). void cgl_freeenv(void) cgl_freenv() frees the global structure pointed toi by cgl_Env and reinitializes cgl_Env to NULL. void cgl_freeformdata(void) cgl_freeformdata() frees the hashed list cgl_Formdata, as well as the internal buffer cgl_Buf (where the form data strings are stored). It reinitializes cgl_Formdata to NULL. void cgl_freecookies(void) cgl_freecookies() frees the hashed list cgl_Cookies, as well as the internal buffer cgl_Cookiebuf (where the cookie values are stored). It reinitializes cgl_Cookies to NULL. char *cgl_getvalue(char *name) cgl_getvalue() returns a pointer to the value string associated with name. If the name does not exist in the list, cgl_getvalue() returns NULL. char **cgl_getvalues(int *count, char *name) cgl_getvalues() returns a pointer to an array of value strings associated with name. If the name does not exist in the list, cgl_getvalues() returns NULL. The number of items found is stored into count, with -1 stored on error, and cglerrno set to the error that occured. The array of value strings that cgl_getvalues() returns can be passed to free() with no ill effects: the pointers it contains do not point to storage allocated by cgl_getvalues() but are merely copies of the value pointers in cgl_Formdata. SO DON'T TRY TO FREE IT AS YOU WOULD A NORMAL ARGV STYLE ARRAY OF POINTERS TO ALLOCATED STRINGS. char *cgl_getcookie(char *name) Like cgl_getvalue(), but searches the cookie list from HTTP_COOKIE. If the name does not exist in the list, cgl_getcookie() returns NULL. char **cgl_getcookies(int *count, char *name) Like cgl_getvalues(), but searches the cookie list from HTTP_COOKIE. If the name does not exist in the list, cgl_getcookies() returns NULL. The number of items found is stored into count, with -1 stored on error, and cglerrno set to the error that occured. The array of value strings that cgl_getvalues() returns can be passed to free() with no ill effects: the pointers it contains do not point to storage allocated by cgl_getcookies() but are merely copies of the value pointers in cgl_Cookies. Second Level Data Access Functions: ----------------------------------- Most of the top level data functions that act on the CGL global variables are wrappers for the more generalized second level functions that act on specified data structures. char * cgl_getnodevalue(cgllist *cdata, char *name) cgl_getnodevalue() returns a pointer to the value string associated with name in the hashed list cdata. If the name does not exist in the list, cgl_getnodevalue() returns NULL. char ** cgl_getnodevalues(cgllist *cdata, int *count, char *name) cgl_getvalues() returns a pointer to an array of value strings associated with name in the hashed list cdata. If the name does not exist in the list, cgl_getnodevalues() returns NULL. cglnode *cgl_fetchnode(cgllist *cdata, char *name) cgl_fetchnode() returns a pointer to the hashed list node that contains the value for name, and sets cdata->cur to point to that node. If name does not exist in the list, cgl_fetchnode() returns NULL. int cgl_insertnode(cgllist *cdata, char *name, void *value, int where) cgl_insertnode() creates a new node for name and value and inserts it into the hashed list cdata. Note that the node is created with pointers to name and value, no new storage is allocated for either name or value. Where the node is inserted in the list is controlled by "where" which may have one of the following values: CGL_INSERT_TAIL insert at head of list CGL_INSERT_HEAD insert at tail of list CGL_INSERT_PREV insert before cdata->cur CGL_INSERT_NEXT insert after cdata->cur Whether or not the node is hashed depends on the conditions described above in the description of the cgllist hashed list. cgl_insertnode() returns 0 on success, and -1 on failure. void cgl_deletenode(cgllist *cdata) cgl_deletenode deletes the node pointed to by cdata->cur from the cdata hashed list. int cgl_hashlist(cgllist *cdata, int hashsz) cgl_hashlist() creates a hash table for cdata and hashes the contents of the list into it. If the list was already hashed, the previous table is destroyed and a new one created. cgl_hashlist() is normally called internally by cgl_insertnode(). If cgl_hashlist() is called with a hashsz of 0, the hash table for cdata will be removed, and all searches will become linear. But note: if hashing control is set to CGL_HASH_AUTO, the next insertion beyond cdata->hash.h_mincount will cause the list to be rehashed, and if hashing control is set to some fixed hashsize, the very next insertion will cause the list to be rehashed. To turn hashing totally off for a list, set cdata->hash.h_control to CGL_HASH_OFF and then call cgl_hashlist() with a hashsz of 0. void cgl_freedata(cgllist *cdata) cgl_freedata() frees the hashed list cdata. cgllist * cgl_newdata(void) cgl_newdata() returns a pointer to a new, initialized hashed list structure. The maximum number of elements is set to cgl_def_maxcount (CGL_MAXCOUNT), the hashing behaviour is set to cgl_def_hcontrol (CGL_HASH_AUTO), and the minumum element count on which to start hashing is set to cgl_def_mincount (CGL_MINTOHASH). cgllist * cgl_newhash(void) cgl_newhash() returns a pointer to a new, initialized hashed list structure. The maximum number of elements is unlimited, the hashing behaviour is set to CGL_HASH_AUTO, and the minumum element count on which to start hashing is set to 0 (to force immediate hashing). hash.h_unique is set to CGL_HASH_UNIQUE to turn off support for duplicate names. If a name/value pair is inserted that has the same name of a pair existing in the list, the pair being inserted replaces the previous pair. int cgl_parsecgibuf(cgllist *cdata, char *query) cgl_parsecgibuf() parses the query string query (from either GET or POST data) into the hashed list cdata. int cgl_parsecookiebuf(cgllist *cdata, char *cookies) cgl_parsecookiebuf() parses the cookie string cookies (from HTTP_COOKIE) into the hashed list cdata. cglnode *cgl_firstnode(cgllist *cdata); cglnode *cgl_nextnode(cgllist *cdata); cglnode *cgl_prevnode(cgllist *cdata); cglnode *cgl_lastnode(cgllist *cdata); cgl_firstnode(), cgl_nextnode(), cgl_prevnode(), and cgl_lastnode() set and return cdata->cur to point to the appropriate list node. void cgl_perror(FILE *fw, char *s) cgl_perror() is like perror(), but prints a string for the internal cglerrno number, or for the system errno if cglerrno is set to CGL_SYSERR. char * cgl_strerror(void) cgl_strerror() is like strerror(), but prints a string for the internal cglerrno number, or for the system errno if cglerrno is set to CGL_SYSERR. Unlike strerror() it does not take an argument; but uses the cglerrno and the saved cglsyserrno. Header Functions: ----------------- void cgl_html_header(void); Prints "Content-type: text/html\n\n". void cgl_content_header(char *type) Prints "Content-type: %s\n\n", where %s is replaced by the string pointed to by "type". void cgl_nph_header(char *version, char *status) void cgl_status_header(char *status) void cgl_location_header(char *location) void cgl_pragma_header(char *s) int cgl_accept_image(void) Looks for the string "image" in the HTTP_ACCEPT string. cgl_initenv() must have previously been called. HTML Functions: --------------- void cgl_html_begin(char *title) Prints the following on stdout: