Website In C
2004-07-27 02:54:00
Category: c:internet
Description: Example on how to code your own website in C using mysql.
Author: mind
Viewed: 14635
Rating: (39 votes)


/* Website in C - mind@metalshell.com
 *
 * This code was meant to show the flexibility
 * and speed of coding a site in C. [ Nobody Likes PHP! =) ]
 *
 * This example will show how to create a fully developed
 * website in C, using mysql (optional).
 *
 * I did a speed test; Printing 2,000 lines containing 100 'A's
 * per line using php and C; the results were: C (0.120s) PHP (0.605s)
 *
 * Note: I used a version of my own printing example to make
 *     the HTML output look alot nicer.. eprint() is optional.
 *
 * libmysqlclient.a: path may be different.
 * To compile: gcc example.c -o example.cgi -lz /usr/lib/mysql/libmysqlclient.a
 *
 * to view VIA web browser: turn ExecCGI on in httpd.conf
 * and move example.cgi to your html folder.
 */
 
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
/* header path may be different */
#include "/usr/include/mysql/mysql.h"
 
/* To setup your mysql db so the example will work please
 * open mysql; and paste the following:
 *
 * create database Cexample;
 *
 * use Cexample;
 * create TABLE person (
 *   id mediumint(9) NOT NULL auto_increment,
 *   name char(40) NOT NULL,
 *   birth char(40) NOT NULL,
 *   addy char(40) NOT NULL,
 *   phone char(40) NOT NULL,
 *   PRIMARY KEY  (id)
 * );
 *
 * insert into person VALUES( NULL, 'John Doe', '01-20-66',
 * 'N. Burboun ST.', '800-123-4567' );
 *
 * insert into person VALUES( NULL, 'Jane Doe', '12-09-72',
 * 'S. Burboun ST.', '800-987-6543');
 *
 */
 
/* edit USER, and PASS */
#define        MySQL_HOST    "localhost"
#define        MySQL_USER    "ChangeME"
#define        MySQL_PASS    "ChangeME"
#define        MySQL_DATA    "Cexample"
 
MYSQL_RES       *res;
MYSQL_ROW       row;
 
int    TabMe = 0;
void eprint(int b, char *fmt, ...);
void ShowError(char *x, char *e);
void StartHtml();
void GetBirth(int x);
void GetAddress(int x);
void GetPhone(int x);
void GetShowAll(int x);
int StartQuery();
 
/* This structure is for our apache string parser
 * when it parses for example id=1&0 our parser will
 * execute GetBirth(0);
 */
struct
{
    int    id;
    void    (*func)(int);
}
DefExt[]=
{
    { 1,    GetBirth   },
    { 2,    GetAddress },
    { 3,    GetPhone   },
    { 4,    GetShowAll },
    { 0,    NULL },
};
 
int main()
{
    MYSQL        mysql;
    char        query[100];
 
    /* Initial start of our site's source */
    printf("Content-Type: text/html\n\n");
 
    /* Check to see if any arguments were passed through
     * our program. If not show front page. */
    if ((StartQuery()) == -1)
    {
        StartHtml();
 
        if (!(mysql_connect(&mysql, MySQL_HOST, MySQL_USER, MySQL_PASS)))
            ShowError(NULL, "MySQL SERVER down");
 
        if (mysql_select_db(&mysql, MySQL_DATA))
            ShowError(NULL, "MySQL database error");
 
        snprintf(query, sizeof(query), "select * from person order by name");
        if (mysql_query(&mysql,query))
            ShowError(NULL, "MySQL server error");
 
        res = mysql_store_result(&mysql);
        while ((row = mysql_fetch_row(res)))
        {
            eprint( 0, "<font>%s - </font>\n", row[1]);
            eprint( 0, "<a href=\"?id=1&%s\">Birth Day</a>\n", row[0]);
            eprint( 0, "<font> - </font>\n");
            eprint( 0, "<a href=\"?id=2&%s\">Address</a>\n", row[0]);
            eprint( 0, "<font> - </font>\n");
            eprint( 0, "<a href=\"?id=3&%s\">Phone</a>\n", row[0]);
            eprint( 0, "<font> - </font>\n");
            eprint( 0, "<a href=\"?id=4&%s\">Show All</a><br>\n", row[0]);
        }
 
        mysql_close(&mysql);
        mysql_free_result(res);
 
        eprint(-1, "</html>\n");
        return 1;
    }
 
    eprint(-1, "</html>\n");
    return 1;
}
 
int StartQuery()
{
    int    i, g, b;
    char    *x, *y, *z, *e;
 
    (char *)y = malloc(100);
    (char *)z = malloc(100);
    (char *)e = malloc(100);
 
    /* Apache will set QUERY_STRING=id=x&x */
    x = getenv("QUERY_STRING");
 
    /* If it doesn't exsist return a negative value
     * to initialize our front page */
    if (x == NULL || x[0] == 0) { return -1; }
 
    /* Always perform checks on everything you write
     * to prevent program flaws and or overflows */
    if (strlen(x) >= 100)
    {
        ShowError(x, "Your request was too big");
        return 0;
    }
 
    for (i = 0, b = 0, g = 0; i < strlen(x); i++)
    {
        if (g == 1)
        {
            if (i > 8)
            {
                ShowError(x, "Id too long");
                return 0;
            }
 
            if (x[i] == '&')
            {
                if (x[i+1] == 0)
                {
                    ShowError(x, "Missing field");
                    return 0;
                }
                g++;
                b = 0;
 
                continue;
            } else {
                z[b] = x[i];
                b++;
 
                continue;
            }
        }
 
        if (g == 2)
        {
            e[b] = x[i];
            b++;
 
            continue;
        }
 
        if (x[i] == '=')
        {
            g++; b = 0;
            if (!(strncmp(y, "id", 2)))
            {
                continue;
            } else {
                ShowError(x, "Invalid extention");
                return 0;
            }
        }
 
        y[b] = x[i];
        b++;
    }
 
    if (strncmp(y, "id", 2) || z[0] == 0 || e[0] == 0)
    {
        ShowError(x, "Invalid extention");
        return 0;
    }
 
    b = atoi(z); g = atoi(e);
    for (i = 0; DefExt[i].id; i++)
    {
        if (DefExt[i].id == b)
        {
            StartHtml();
 
            DefExt[i].func(g);
            return 1;
        }
    }
 
    ShowError(x, "Invalid ID");
    return 1;
}
 
/* The mysql concept was derived from detour's mysql select
 * example found at: http://www.metalshell.com/view/source/18/
 */
void GetMysql(char *query)
{
    MYSQL           mysql;
 
    if (strlen(query) < 10)
        ShowError(NULL, "MySQL query string too low");
 
    if (!(mysql_connect(&mysql, MySQL_HOST, MySQL_USER, MySQL_PASS)))
    {
        fprintf(stderr,"mysql_connect() Failed: %s\n",mysql_error(&mysql));
        ShowError(NULL, "MySQL SERVER down");
    }
 
    if (mysql_select_db(&mysql, MySQL_DATA))
        ShowError(NULL, "MySQL database error");
 
    if (mysql_query(&mysql,query))
        ShowError(NULL, "MySQL server error");
 
    res = mysql_store_result(&mysql);
    row = mysql_fetch_row(res);
 
    mysql_close(&mysql);
    mysql_free_result(res);
}
 
void GetBirth(int x)
{
    char    query[100];
 
    snprintf(query, sizeof(query), "select * from person where id = %i", x);
    GetMysql(query);
 
    eprint( 0, "<font> %s's Birth date is: %s</font>\n", row[1], row[2]);
}
 
void GetAddress(int x)
{
    char    query[100];
 
    snprintf(query, sizeof(query), "select * from person where id = %i", x);
    GetMysql(query);
 
    eprint( 0, "<font> %s's Address is: %s</font>\n", row[1], row[3]);
}
 
void GetPhone(int x)
{
    char    query[100];
 
    snprintf(query, sizeof(query), "select * from person where id = %i", x);
    GetMysql(query);
 
    eprint( 0, "<font> %s's Phone Number is: %s</font>\n", row[1], row[4]);
}
 
void GetShowAll(int x)
{
    char    query[100];
 
    snprintf(query, sizeof(query), "select * from person where id = %i", x);
    GetMysql(query);
 
    eprint( 0, "<font> <b><u>%s</b></u> </font><br>\n", row[1]);
    eprint( 0, "<font> Birth day: %s</font><br>\n", row[2]);
    eprint( 0, "<font> Address  : %s</font><br>\n", row[3]);
    eprint( 0, "<font> Phone Num: %s</font><br>\n", row[4]);
}
 
void StartHtml()
{
    eprint( 0, "<html>\n");
    eprint( 1, "<head>\n");
    eprint( 1, "<title> Website in C - Example </title>\n");
    eprint(-1, "</head>\n\n");
}
 
/* Error printing */
void ShowError(char *x, char *e)
{
    if (e == NULL) strcpy(e, "Unknown Error!");
 
        /* Some prints resized to fit MS source code area */
    eprint( 0, "<html>\n");
    eprint( 1, "<head>\n");
    eprint( 1, "<title>An Error Occured!</title>\n");
    eprint(-1, "</head>\n\n");
    eprint( 0, "<br><br><br><br><br><br><br>\n");
    if (x != NULL)
        {
        eprint( 0, "<div align=center><font size=4>An error occured: \"%s\" ", e);
                printf("While trying to process your request of \"%s\"</font></div>\n", x);
    }else {
        eprint( 0, "<div align=center><font size=4>An error occured: \"%s\" ", e);
                printf("While trying to process your request.</font></div>\n");
        }
    eprint( 0, "<div align=center><font size=4>If this error keeps occuring please ");
        printf("email the site admin</font></div>\n");
    eprint(-1, "</html>\n");
    exit(-1);
}
 
/* eprint - mind@metalshell.com [http://www.metalshell.com]
 *
 * Example:
 *   eprint( 0, "test1\n");  No Change (just print)
 *   eprint( 1, "test2\n");  Add a tab
 *   eprint( 1, "test3\n");  Add a tab
 *   eprint(-1, "test4\n");  Remove a tab
 *   eprint(-1, "test5\n");  Remove a tab
 *   eprint( 0, "test6\n");  No Change (just print)
 *
 *   ;test1
 *   ;<tab>test2
 *   ;<tab><tab>test3
 *   ;<tab>test4
 *   ;test5
 *   ;test6
 */
void eprint(int b, char *fmt, ...)
{
    va_list        list;
    char            *p, *r;
    int             e, x;
 
    if (b == -1) TabMe--;
    if (b ==  1) TabMe++;
 
    for (x = 0; x < TabMe; x++) putc('\t', stdout);
 
    va_start( list, fmt );
    for ( p = fmt ; *p ; ++p )
    {
        if ( *p != '%' )
        {
            putc( *p, stdout );
        } else {
            switch ( *++p )
            {
                case 's':
                {
                    r = va_arg( list, char * );
 
                    printf("%s", r);
                    continue;
                }
 
                case 'i':
                {
                    e = va_arg( list, int );
 
                    printf("%i", e);
                    continue;
                }
 
                default:
                {
                    if (!x)
                        putc( *p, stdout );
                    else
                        x = 0;
                }
            }
        }
    }
    va_end(list);
    fflush(stdout);
}