PERCGI(3)                  Library Functions Manual                  PERCGI(3)


     percgi - Framework for web application servers


     #include <libpercgi/cgi.h>


     The percgi library provides the basic building blocks for building high-
     performance web application servers in C and C-based languages.  PerCGI

     o   CGI/FastCGI Interface
     o   Authentication
     o   Session Management
     o   Modular Query Processing
     o   Input/Output Content Filters
     o   Input Filter: Variable substitution
     o   HTTP Language Negotiation
     o   HTTP Content Negotiation
     o   HTTP Cookies
     o   Validation


     CGI_Init(CGI_Application *cgi);

     CGI_Exit(int exit_code, const char *errmsg_fmt, ...);

     The CGI_Init() function initializes the PerCGI library, and should be
     called prior to invoking any other percgi functions.  The CGI_Application
     argument should point to the following structure:

     typedef struct cgi_application {
             const char *name;                       /* Description */
             const char *copyright;                  /* Copyright notice */
             const char *availLangs[CGI_LANGS_MAX];  /* Available languages */
             const char *homeOp;                     /* Default operation */

             Uint     flags;
     #define CGI_PERSISTENT  0x02    /* Only run under FastCGI */
     #define CGI_PRETTY_URL  0x04    /* Use "/op?args" instead of
                                        "/path/to/prog.fcgi?op=op&args" */

             void    (*destroyFn)(void);
             void    (*logFn)(enum cgi_loglvl, const char *);
     } CGI_Application;

     The availLangs list contains the set of languages (ISO 639) which are
     supported by the application, and which should be offered for HTTP
     language negotiation.

     The homeOp field specifies the default operation to invoke after a user
     has successfully logged in (usually "home" or "index").

     CGI_PERSISTENT indicates that the application must run under FastCGI, and
     will abort if FastCGI support was not compiled in.

     The CGI_PRETTY_URL option enables URLs of the form "/op?args", instead of
     the standard "/path/to/prog.fcgi?op=op&args" form.  With Apache httpd
     2.4, it is possible to start the percgi application using fcgistarter(8)
     and simply match "/" with the ProxyPass directive, like so:

         ProxyPass / fcgi://
         ProxyPass /static/ !
         ProxyPass /images/ !

     The destroyFn() callback, if defined, will be invoked before the
     application terminates.

     The logFn() method, if defined, overrides the default behavior of

     The CGI_Exit() function frees allocated resources and terminates the CGI
     application with the given exit_code and optional error message.


     CGI_SetError(const char *fmt, ...);

     char *

     The CGI_SetError() function sets the current error message.
     CGI_GetError() retrieves the last error message.


     CGI_QueryInit(CGI_Query *q);

     CGI_QueryDestroy(CGI_Query *q);

     CGI_ReadQueryHTTP(CGI_Query *q);

     CGI_ExecQuery(CGI_Query *q, CGI_SessionOps *sess);

     CGI_QueryDestroy(CGI_Query *q);

     CGI_WriteHeader(CGI_Query *q, const char *contentType,
         const char *charset, int setCookies);

     CGI_WriteHeaderHTML(CGI_Query *q);

     CGI_WriteData(CGI_Query *q, void *data, size_t len);

     CGI_QueryInit() initializes a query structure.  CGI_QueryDestroy()
     releases resources allocated by a query structure.

     The CGI_ReadQueryHTTP() function accepts an HTTP request from the web
     server, parses any script arguments and initializes the CGI_Query
     structure argument according to the new request.  The function returns 0
     on success or -1 if an error occured.

     The CGI_ExecQuery() routine handles a query in the standard way, by
     invoking the appropriate module call.  It is assumed that standard percgi
     session management is used (see "SESSION MANAGEMENT" section).  It is not
     mandatory for queries to be processed by CGI_ExecQuery().

     The CGI_WriteHeader() function selects the specified Content-Type /
     character set, and writes HTTP response headers to the client.  If
     setCookie is 1, "Set-Cookie" headers are emitted (see CGI_SetCookie()).

     The CGI_WriteHeaderHTML() shorthand emits standard headers for text/html,
     and is equivalent to:

     CGI_WriteHeader(q, "text/html", "utf-8", 1);

     The CGI_Write() routine writes len bytes of data to the client.  If
     registered output filters match the current "Content-Type", those filters
     are applied before writing the data.


     const char *
     CGI_Get(CGI_Query *q, const char *key, size_t max);

     const char *
     CGI_GetTrim(CGI_Query *q, const char *key, size_t max);

     CGI_GetBool(CGI_Query *q, const char *key);

     CGI_GetInt(CGI_Query *q, const char *key, int *rv);

     CGI_GetIntR(CGI_Query *q, const char *key, int *rv, int min, int max);

     CGI_GetIntRange(CGI_Query *q, const char *key, int *rvMin,
         const char *sep, int *rvMax);

     CGI_GetEnum(CGI_Query *q, const char *key, Uint *rv, Uint last);

     CGI_GetFloat(CGI_Query *q, const char *key, float *rv);

     CGI_GetDouble(CGI_Query *q, const char *key, double *rv);

     char *
     CGI_EscapeURL(CGI_Query *q, const char *url);

     char *
     CGI_UnescapeURL(CGI_Query *q, const char *url);

     CGI_KeySet *
     CGI_GetKeySet(CGI_Query *q, const char *key_pattern);

     CGI_FreeKeySet(CGI_KeySet *set);

     The CGI_Get() function returns the value of the given CGI argument
     (either GET or POST).  If the argument does not exist, or it exceeds len
     - 1 bytes in size, CGI_Get() returns NULL and sets the error message
     accordingly.  The CGI_GetTrim() variant strips any leading and
     terminating whitespace from the token.  Bounds checking is performed
     against the stripped token.

     The CGI_GetBool() variant returns 1 if the given argument exists and has
     a value of "y".

     The CGI_GetInt(), CGI_GetIntR(), CGI_GetFloat() and CGI_GetDouble()
     functions parse and validate a numerical argument.  If the number is
     valid, they return 0 and write the value to rv.  If the number is
     malformed or out of range, they return -1 and set an error message.  The
     CGI_GetIntR() variant fails if the value lies outside of the specified

     The CGI_GetIntRange() function parses an argument which may be a single
     integer or a range bounded by two numbers separated by any of the
     characters in sep (typically "-").  If the range is negative (pMin >
     pMax), the function will fail returning an error.

     The CGI_GetEnum() routine is a shorthand for CGI_GetIntR() with min=0,
     which also fails if the return value is greater than the last argument.

     The CGI_EscapeURL() function substitutes illegal URL characters as
     described by RFC1738.  CGI_UnescapeURL() substitutes escape codes for the
     character they represent, except for NUL sequences which are replaced by
     underscores to avoid truncation.

     The CGI_GetKeySet() function returns the set of arguments whose key start
     with the given pattern.  It is useful for things like checkboxes in HTML
     forms.  The CGI_KeySet structure is defined as:

     typedef struct cgi_keyset {
             char    **ents;
             int      nents;
     } CGI_KeySet;

     The application should use CGI_FreeKeySet() when done with the data.


     CGI_AddFilter(CGI_Filter *filter);

     CGI_DelFilter(CGI_Filter *filter);

     The CGI_AddFilter() function registers a content filtering function which
     should process either data read by the script or data written to the
     output, which matches the given MIME type.  Filters are useful for
     compression and certain types of substitutions.

     The argument of CGI_AddFilter() is a pointer to the following structure:

     typedef struct cgi_filter {
             enum cgi_filter_type {
                     CGI_INPUT_FILTER,  /* Filter data read by the script */
                     CGI_OUTPUT_FILTER  /* Filter data written to stdout */
             } type;
             char    *content_type;     /* Apply to data of this type */
             size_t  (*func)(CGI_Query *q, void **data, size_t len);
     } CGI_Filter;

     The CGI_DelFilter() function removes the specified content filter.


     The most common operation in a PerCGI query is the servicing of
     precompiled, performatted HTML data (with "$foo" style references in it).

     HTML_SetDirectory(CGI_Query *q, const char *path)

     HTML_Output(CGI_Query *q, const char *document)

     HTML_OutputError(CGI_Query *q, const char *fmt, ...)

     HTML_SetError(const char *fmt, ...)

     HTML_SetSuccess(const char *fmt, ...)

     HTML_SetDirectory() can be used to set the default directory to search
     for HTML documents and fragments (defaults to html/).

     The HTML_Output() function writes an HTML document to the standard output
     (assuming the HTTP headers have already been emitted).

     The HTML_OutputError() function outputs an HTML document containing only
     the given error message.

     HTML_SetError() sets the built-in variable $_error to the given error
     message.  Whenever $_error is defined, the HTML template is expected to
     display a closable error dialog in a suitable location (usually on top of
     the document).  HTML_SetSuccess() works the same, except $_error is set
     to a success-type message.


     PerCGI provides one standard content filter, which is an Input filter
     named varsubst.  This filter is used by HTML_Output() to substitute
     instances of "$foo" in the HTML input, for the value of the corresponding
     percgi variable (per the interface described below).  varsubst also
     provides a handy gettext-style internationalization operator, "$_()".
     Instances of "$_(Some text)" in the sources will be replaced by the
     corresponding gettext translation (per the user's language settings).

     Variables are managed by PerCGI and described as:

     typedef struct var {
             char     key[VAR_NAME_MAX];     /* Variable name */
             char    *value;                 /* Variable value */
             size_t   len;                   /* Length in characters */
             size_t   bufSize;               /* Total buffer size */
             int      global;                /* Persist across queries */
             TAILQ_ENTRY(var) vars;
     } VAR;

     The API is as follows.  Note that the VAR_ prefix can be omitted if
     compiling with _USE_PERCGI_VAR defined.

     VAR *
     VAR_New(const char *key);

     VAR *
     VAR_Set(const char *key, const char *fmt, ...);

     VAR *
     VAR_SetS(const char *key, const char *s);

     VAR *
     VAR_SetS_NODUP(const char *key, char *s);

     VAR *
     VAR_SetGlobal(const char *key, const char *fmt, ...);

     VAR *
     VAR_SetGlobalS(const char *key, const char *s);

     VAR_Cat(VAR *v, const char *fmt, ...);

     VAR_CatS(VAR *v, const char *s);

     VAR_CatS_NODUP(VAR *v, char *s);

     VAR_Wipe(const char *key);

     VAR_Unset(const char *key);

     VAR_Defined(const char *key);

     VAR_Free(VAR *var);

     VAR_New() creates a new variable.  The variable is initially undefined.

     VAR_Set() sets the value of a variable from a format string argument.
     VAR_SetS() accepts a C string.  The VAR_SetS_NODUP() routine accepts a
     pointer to user memory (which should remain accessible as long as the
     variable is in use).

     The scope of variables set by VAR_Set() is limited to the current
     CGI_Query.  The VAR_SetGlobal() and VAR_SetGlobalS() variants set a
     "global" variable remains persistent across queries.  This is useful for
     static or semi-static content which needs to be regenerated infrequently.
     It is customary to define globals for limits such as CGI_USERNAME_MAX,
     from the init() method of a CGI_Module.

     The VAR_Cat() and VAR_CatS() functions append a string to an existing
     variable.  The VAR_CatS_NODUP() variant frees the provided string after
     it has been appended.

     For variable substitution to work, variables should be set prior to
     calling HTML_Output().  For example, the following assumes that the
     login_form HTML document contains one or more instances of "$username"
     and "$password", to be substituted:

             SetS("username", "nobody");
             SetS("password", "");

     The VAR_Wipe() routine wipes the memory currently used by the given
     variable.  It is recommended to call VAR_Wipe() on variables that have
     been storing sensitive information such as passwords, once the variable
     is no longer needed.

     VAR_Unset() searches for the named variable.  If the variable is found,
     it is deleted and freed.

     The VAR_Defined() function evaluates to 1 if the named variable exists,
     otherwise returns 0.

     The VAR_Free() routine frees all resources allocated by a variable.  Note
     that this is already done internally by PerCGI when VAR_Unset() is called
     or whenever a query has been completed.  VAR_Free() should only be used
     to free anonymous variables (variables with key = NULL which are not
     managed by PerCGI).  For example:

             VAR *v;
             v = SetS(NULL, "Foo");          /* Anonymous variable */
             VAR_CatS(v, " bar");


     CGI_Write(CGI_Query *q, const void *data, size_t len);

     CGI_Printf(CGI_Query *q, const char *fmt, ...);

     CGI_PutS(CGI_Query *q, const char *s);

     CGI_PutC(CGI_Query *q, char c);

     The CGI_Write() function writes len bytes from data to the client.  It
     returns 0 on success, or -1 if an I/O error or EOF prevented all len
     bytes from being written.

     CGI_Write() applies any output filters matching the current "Content-

     CGI_Printf() writes a printf(3) formatted string to the client,
     CGI_PutS() writes a C string, and CGI_PutC() writes a character.


     CGI_Log(enum cgi_loglvl log_level, const char *fmt, ...);

     CGI_LogErr(const char *fmt, ...);

     CGI_LogWarn(const char *fmt, ...);

     CGI_LogInfo(const char *fmt, ...);

     CGI_LogNotice(const char *fmt, ...);

     CGI_LogDebug(const char *fmt, ...);

     The CGI_Log() function appends an entry to the application's logfile.
     The log_level argument is one of:

     enum cgi_loglvl {

     The CGI_LogErr(), CGI_LogWarn(), CGI_LogInfo(), CGI_LogNotice() and
     CGI_LogDebug() shorthands are also provided.


     CGI_SessionInit(CGI_Session *sess, CGI_SessionOps *ops);

     CGI_SessionDestroy(CGI_Session *sess);

     CGI_CloseSession(CGI_Session *sess);

     CGI_SessionLoad(CGI_Session *sess, int fd);

     CGI_SessionSaveToFD(CGI_Session *sess, int fd);

     CGI_SessionSave(CGI_Session *sess);

     CGI_SetSV(CGI_Session *sess, const char *key, const char *fmt, ...);

     CGI_SetSV_S(CGI_Session *sess, const char *key, const char *s);

     CGI_SetSV_ALL(CGI_SessionOps *ops, const char *user, const char *key,
         const char *value);

     The CGI_SessionInit() routine initializes the given CGI_Session
     structure.  The ops argument should point to the following structure,
     which describes a session manager class.  All operations are optional,
     but unused methods should be initialized to NULL.

     typedef struct cgi_session_ops {
             const char *name;        /* Description */
             size_t size;             /* Structure size */
             Uint flags;
     #define CGI_SESSION_PREFORK_AUTH 0x01  /* Call auth() before fork() */

             void (*init)(void *s);
             void (*destroy)(void *s);
             int  (*load)(void *s, int fd);
             void (*save)(void *s, int fd);

             int  (*auth)(void *s, const char *user, const char *pass);

             void (*authRegister)(CGI_Query *q);   const char *authRegisterName;
             void (*authRegConfirm)(CGI_Query *q); const char *authRegConfirm;
             void (*authAssist)(CGI_Query *q);     const char *authAssistName;
             void (*authRequest)(CGI_Query *q);    const char *authRequestName;
             void (*authConfirm)(CGI_Query *q);    const char *authConfirmName;
             void (*authCommit)(CGI_Query *q);     const char *authCommitName;

             int  (*sessOpen)(void *s);
             void (*sessClose)(void *s);
             void (*sessExpired)(void *s);

             void (*beginQueryUnauth)(CGI_Query *q, const char *op);

             void (*loginPage)(CGI_Query *q);
             void (*logout)(CGI_Query *q);

             void (*addSelectFDs)(void *s, fd_set *r, fd_set *w, int *maxfds);
             void (*procSelectFDs)(void *s, fd_set *r, fd_set *w);
     } CGI_SessionOps;

     The name is an arbitrary string which identifies the session manager.
     size should be set to the size of the CGI_SessionOps structure (or
     derivative thereof).

     The flags options apply to all session manager instances.  If the
     CGI_SESSION_PREFORK_AUTH flag is set, the auth() call will be made prior
     to fork(2).  This is recommended when using local methods of
     authentication (i.e., password files), as opposed to methods that involve
     estalishing a network connection.

     The init() callback is invoked at initialization time and is expected to
     initialize any extra members of structures derived from CGI_SessionOps.

     destroy() should release all resources previously allocated by init().

     The serialization routines load() and save() are invoked whenever the
     session file is read from, or written to the disk file referenced by fd.
     They are useful for session managers which need to save other data (in
     addition to the session variables).  The extra data will follow the list
     of session variables in the session file.

     Password authentication is handled by the auth() operation, which should
     return 0 if user and pass are correct, or -1 otherwise.

     The authRegister() operation is expected to process POSTDATA from a
     subscription form where new users can request an account.  It should
     perform validation on the request data, generate a new authentication
     token and e-mail a link (a link to the authRegConfirm() operation), to
     the user.

     The authRegConfirm() operation is expected to validate the token and
     complete the registration request.

     The following methods implement password recovery, to assist users in
     recovering lost passwords.  authAssist() is expected to display a
     password recovery form (which submits to authRequest()).  The
     authRequest() should generate a random token and e-mail it to the contact
     e-mail address (or perform validation using some alternate mechanism if

     The verification e-mail should be a link to the authConfirm() operation.
     Given a valid token, this operation is expected to generate a form
     prompting for the security question (if one has been set), in addition to
     the "New password" field.  This form should submit the token, answer to
     the security question, and password to the authCommit() operation.

     The sessOpen() function is invoked after authentication and successful
     creation of a new session.  If it returns a value other than 0, the new
     session will be aborted.

     sessClose() is invoked after a session has been terminated.  If a session
     has been terminated due to an inactivity time-out, sessExpired() is also

     The beginQueryUnauth() method may be used to override the default code
     used to initialize the standard globals such as $_error, $_user, $_lang
     and $_modules in an unauthenticated session.

     The loginPage() method is expected to display the standard "Log in" form.
     When a user gracefully logs out using "Log out", the logout() method is
     called and is expected to display a confirmation message.

     addSelectFDs() and procSelectFDs() are hooks into the standard event loop
     of percgi (which is select(2) based).  addSelectFDs() can add additional
     file descriptors to rd or wr using FD_SET(2) (it should not modify the
     existing set).

     The procSelectFDs() callback is invoked following a return from
     select(2), and may test the returned sets using FD_ISSET(2).

     CGI_SessionDestroy() releases all resources allocated by a session.

     The CGI_CloseSession() routine closes the given session.

     The serialization routines CGI_SessionLoad() and CGI_SessionSave()
     respectively read and write session data (including all session
     variables) from/to file.

     The CGI_SetSV() routine sets the named session variable to the value
     (specified as a printf(3) format string).  The CGI_SetSV_S() variants
     accepts a C string argument.

     The CGI_SetSV_ALL() routine sets the named session variable similarly to
     CGI_SetSV(), except the change applies to all sessions currently opened
     by user.


     The percgi interface was first developed in 2003 (at, under
     the name of csoft-cgi.

OpenBSD 6.4                     October 9, 2004                    OpenBSD 6.4

[Unix Hosting | Open-Source | Contact Us]
[Engineering & Automation | Software Development | Server Applications]