Display CGI environment variables
This basic C program prints out the environment variables available to the CGI script. (Although it will compile and run on this web server, for security reasons I am not making it available to run on this public web server, so please copy it from below and compile it on your own web server.) This is a demo program for A simple guide to the Common Gateway Interface.
It uses an external global variable called environ
to
read the environment from. This variable is available on Unix
systems. See environ
.
/* Show the CGI (Common Gateway Interface) environment variables */ #include <stdio.h> #include <string.h> #include <stdlib.h> /* Print a basic HTTP header. */ static void print_http_header (const char * content_type) { printf ("Content-Type: %s\n\n", content_type); } /* Handle errors by printing a plain text message. */ static void cgi_fail (const char * message) { print_http_header ("text/plain"); printf ("%s\n", message); exit (0); } /* The external variable "environ" contains the environment variables. */ extern char ** environ; /* This structure will contain our environment variables. The nomenclature follows that of 'man getenv'. */ typedef struct { char * name; char * value; } env_var; /* Find the first equals sign ("=") in "s". Returns -1 if there is no equals sign in the string. */ static int find_equals (const char * s) { int i = 0; while (1) { if (s[i] == '=') { return i; } if (s[i] == '\0') { return -1; } i++; } } /* Split an environment variable into the part before the equals sign and the part after the equals sign. Return the result in the env_var structure called "ev". Both are returned in allocated memory. */ static void split_env_var (const char * variable, env_var * ev) { int equals_pos; int env_var_len; equals_pos = find_equals (variable); if (equals_pos == -1) { cgi_fail ("could not parse environment"); } env_var_len = strlen (variable); ev->name = strndup (variable, equals_pos); if (ev->name == 0) { cgi_fail ("out of memory"); } ev->value = strndup (variable + equals_pos + 1, env_var_len - equals_pos - 1); if (ev->value == 0) { cgi_fail ("out of memory"); } } /* Catch an environment variable overflow. */ #define _ENV_VAR_GIVE_UP 1000 /* Count the number of environment variables. */ static int count_env_vars () { int i; for (i = 0; i < _ENV_VAR_GIVE_UP; i++) { if (environ[i] == 0) { return i; } } cgi_fail ("too many environment variables"); return 0; } static void get_environment (env_var * env_vars, int n_env_vars) { int i = 0; for (i = 0; i < n_env_vars; i++) { split_env_var (environ[i], env_vars + i); } } int main () { int i; int n_env_vars; env_var * env_vars; n_env_vars = count_env_vars (); env_vars = calloc (n_env_vars, sizeof (env_var)); if (! env_vars) { cgi_fail ("out of memory"); } get_environment (env_vars, n_env_vars); print_http_header ("text/html"); printf ("<h1>Environment variables</h1>\n"); printf ("<table>\n"); for (i = 0; i < n_env_vars; i++) { printf ("<tr><td>%d", i); printf ("<td>%s<td>%s", env_vars[i].name, env_vars[i].value); } printf ("</table>"); free (env_vars); return 0; }
This is the makefile for the script on my local server. This puts the executable directly into the web directory after compiling it.
CGITARGET=/usr/local/www/data/b/cgi/env.cgi CFILE=env-cgi.c $(CGITARGET): $(CFILE) cc -Wall -o $(CGITARGET) $(CFILE) clean: -rm -f $(CGITARGET)
Please note, if you are thinking of using the above on your server, that, in order to keep the program short and demonstrative, it doesn't contain full HTML generation, and it doesn't free the allocated memory after exiting.