Programa CGI en C que accesa una BD usando la libreria LPQ de Postgres

Ahora quiero mostrar como se usa la libreria LPQ para acceder a una base de datos de postgress. Yo le llamo la libreria LPQ a la libreria que nos permite establecer una conexion a una BD de Postgres desde un programa escrito en lenguaje C/C++.

los datos de conexion y la tabla a usar en el ejemplo son:
usuario: postgres
password: 12345
base de datos: prueba
tabla: alumnos

En la siguiente imagen se muestran los campos de la tabla alumnos:

El ejemplo que quiero mostrar esta compuesto de los archivos index.html, formularioAltas.html, formularioBajas.html, altaAlumnos.cgi, bajaAlumnos.cgi, mostrarAlumnos.cgi y a continuacion se muestra en la siguiente imagen como se relacionan entre si:

A continuacion se va a mostrar su codigo, se da una breve descripcion y se muestra una imagen de cada uno:

index.html
Este archivo es el principal y es una pagina web que esta localizada en la carpeta /usr/local/servidor_web/htdocs/lpq/index.html y se encarga de mostrar un menu con tres botones, uno para dar de alta un nuevo Alumno, el segundo para dar de baja un alumno y el tercero para consultar y mostrar el contenido de la tabla alumnos. Para no dar tantos detalles mejor muestro el codigo fuente de este archivo:

<!--		Instituto Tecnologico de Zacatepec
    Descripcion:   Indice de opciones del ejemplo que usa la libreria LPQ
    Author:     Gonzalo Silverio  gonzasilve@gmail.com
    Archivo:    index.html
-->
<HTML>
<HEAD>
   <TITLE> Ejemplo que usa la libreria LPQ </TITLE>
</HEAD>
<BODY bgcolor="#C9FF5C">
	<br>
    <h2 align="center">USO DE LA LIBRERIA LPQ DE POSTGRES</h2> <br>
    <TABLE width="80%" border="0" cellpadding="0" cellspacing="0" align="center">
    <TR>
        <TD align="center"><input type="button" name="alta" value="Dar de alta" onclick="location='formularioAltas.html'" > </TD>
        <TD align="center"><input type="button" name="baja" value="Baja de un alumno" onclick="location='http://localhost/lpq/formularioBajas.html'" ></TD>
        <TD align="center"><input type="button" name="ver" value="Ver tabla" onclick="location='http://localhost/cgi-bin/lpq/mostrarAlumnos.cgi'" ></TD>
    </TR>
    </TABLE>
</BODY>
</HTML>

Aca una imagen que muestra esta pagina en el navegador :

formularioAltas.html
Si el usuario elije el boton Dar de alta en la pagina principal, entonces se abrira este archivo que es una pagina web con un formulario. Esta pagina tiene como objetivo que el usuario rellene el formulario con datos de un nuevo alumno y mande estos datos a un programa CGI (altaAlumnos.cgi) al dar click en el boton Dar de alta!. Este archivo esta almacenado en /usr/local/servidor_web/htdocs/lpq. Bueno el contenido de este archivo es el siguiente:

<!--
		Instituto Tecnologico de Zacatepec
    Descripcion:
    Esta pagina web contiene un Formulario que se usara para enviar datos a un programa CGI
	 el cual los guardara en una tabla llamada alumnos de Postgres.
    Author:     Gonzalo Silverio   gonzasilve@gmail.com
    Archivo:    formularioAltas.html
-->
<html>
<head>
<title>Alta de un alumno</title>
</head>
<body bgcolor="#C9FF5C">
    <form name="form_altas" action="http://localhost/cgi-bin/lpq/altaAlumnos.cgi" method="GET">
        <table width="90%" border="1" align="center" bgcolor="#FFFFFF" >
            <tr>
                <td>
                    <table border="0" cellspacing="0" align="center" width="100%">
                <tr>
                    <td colspan="2" bgcolor="#6D6DFF"><h3 align="center">
                            <font color="white"><br><img src="logo_web.gif" alt="gonzasilve">
                                Alta de un nuevo alumno
                            </font></h3>
                    </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>N.C:</b> </td><td><input type="text" name="nc" size="20" maxlength="10"> </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Nombre:</b> </td><td><input type="text" name="nombre" size="40" maxlength="255"> </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Apellidos:</b> </td><td><input type="text" name="apellidos" size="40" maxlength="255"> </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Direccion:</b> </td><td><textarea COLS="50" rows="3"  name="direccion" ></textarea></td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019">
                        <b>Estatura:</b> </td><td><input type="text" name="estatura" size="10" maxlength="10">
                        <font color="#a4a2a1">mts.</font>
                    </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019">
                        <b>Peso:</b> </td><td><input type="text" name="peso" size="10" maxlength="10">
                        <font color="#a4a2a1">kgs.</font>
                    </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Fecha de ingreso:</b> </td><td>Dia
                        <select name="dia" size="1">
                            <option value="1">1</option>
                            <option value="2">2</option>
                            <option value="3">3</option>
                            <option value="4">4</option>
                            <option value="5">5</option>
                            <option value="6">6</option>
                            <option value="7">7</option>
                            <option value="8">8</option>
                            <option value="9">9</option>
                            <option value="10">10</option>
                            <option value="11">11</option>
                            <option value="12">12</option>
                            <option value="13">13</option>
                            <option value="14">14</option>
                            <option value="15">15</option>
                            <option value="16">16</option>
                            <option value="17">17</option>
                            <option value="18">18</option>
                            <option value="19">19</option>
                            <option value="20">20</option>
                            <option value="21">21</option>
                            <option value="22">22</option>
                            <option value="23">23</option>
                            <option value="24">24</option>
                            <option value="25">25</option>
                            <option value="26">26</option>
                            <option value="27">27</option>
                            <option value="28">28</option>
                            <option value="29">29</option>
                            <option value="30">30</option>
                            <option value="31">31</option>
                        </select>
                        <b>Mes</b>
                        <select name="mes" size="1">
                            <option value="01">Enero</option>
                            <option value="02">Febrero</option>
                            <option value="03">Marzo</option>
                            <option value="04">Abril</option>
                            <option value="05">Mayo</option>
                            <option value="06">Junio</option>
                            <option value="07">Julio</option>
                            <option value="08">Agosto</option>
                            <option value="09">Septiembre</option>
                            <option value="10">Octubre</option>
                            <option value="11">Noviembre</option>
                            <option value="12">Diciembre</option>
                        </select>
                        <b>a&ntilde;o</b>
                        <input type="text" size="4" maxlength="4" name="anio" value="">
                    </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Carrera:</b></td>
                    <td>
                        <select name="carrera" size="4">
                            <option value="ingSistemas">Ingenieria en Sistemas computacionales</option>
                            <option value="ingBioquimica">Ingenieria en Bioquimica</option>
                            <option value="ingCivil">Ingenieria Civil</option>
                            <option value="ingElectro">Ingenieria Electromecanica</option>
                            <option value="ingIndustrial">Ingenieria Industrial</option>
                            <option value="ingQuimica">Ingenieria en Quimica</option>
                            <option value="ingGestionEmp">Ingenieria en Gestion Empresarial</option>
                            <option value="maesQuimica">Maestr&iacute;a en Ciencias en Ingenier&iacute;a Qu&iacute;mica</option>
                            <option value="docPolimeroa">Doctorado en Ciencias en Polimeros</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td bgcolor="#ff9019"><b>Sexo:</b> </td><td>
                        <input type="radio" name="sexo" value="hombre">Masculino &nbsp;&nbsp;
                        <input type="radio" name="sexo" value="mujer">Femenino<br><br>
                    </td>
                </tr>
            </table>
            </td>
        </tr>
      </table>
      <br>
      <table border="0" width="80%" align="center">
            <tr>
                <td align="center">
                    <input type="submit" name="guardar" value="Dar de alta!">&nbsp;&nbsp;&nbsp;
                </td>
                <td align="center">
                    <input type="reset" name="limpiar" value="Limpiar">&nbsp;&nbsp;&nbsp;
                </td>
                <td align="center">
                    <input type="Button" name="cancelar" value="Cancelar alta" onClick="location='http://localhost/lpq/index.html'">
                </td>
            </tr>
       </table>
    </form>
</body>
</html>

Y aca se muestra una imagen con esta pagina en el navegador:

altaAlumnos.cgi
Este archivo es el que recibe los datos del formulario formularioAltas.html y a continuacion establece una conexion a la BD y ejecuta una operacion INSERT sobre la tabla alumnos. Este archivo esta almacenado en /usr/local/servidor_web/cgi-bin/lpq. A continuacion se muestra el codigo fuente en C de este programa CGI:


/*
		Instituto Tecnologico de Zacatepec
  Descripcion:	Programa que hacer un INSERT para dar de Alta a un nuevo 
					alumno en una tabla de alumnos de postgres
  Author:	Gonzalo Silverio  gonzasilve@gmail.com
  Archivo:	altasAlumnos.c
  Compilar con: 
		cc -c -I/usr/local/pgsql/include altaAlumnos.c
  Enlazar CGI con libreria LPQ con:
  		cc -o altaAlumnos.cgi altaAlumnos.o -L/usr/local/pgsql/lib -lpq
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "libpq-fe.h"

// Maximo 100 registros de alumnos
#define MAX 100

// Estrutura de datos que guarda los nombres de las variables CGI y sus valores de los formularios
struct 
{
  char nombre[128];
  char valor[128];
} elementos[MAX];

/* Estructura para guardar los datos del alumno */
struct datos
{
  char nc[128];
  char nombre[128];
  char apellidos[128];
  char direccion[128];
  double estatura;
  double peso;
  char fecha_ingreso[128];
  char carrera[128];
  char sexo[128];
} lista_alumnos;


void  guardar(void);

/* declaraciones de las funciones que se van a utilizar en el programa */
void splitword(char *out, char *in, char stop);
char x2c(char *x);
void unescape_url(char *url);
static void salir_bien(PGconn *conn);

/* Almacenamiento temporal de la variable de ambiente */
char *cp;
char *empty = "<vacio>";


	char *qs;	/* qs servira para guardar la cadena de consulta */

	int i,j;
	const char *conninfo;
	PGconn	   *conn;
	PGresult   *res;
	char cadSQL[8000];
	
/* Macro para desplegar las variables de ambiente */
#define safenv(a) ( (cp = getenv(a)) ? cp : empty)

int main(int argc, char **argv)
{
	/* Enviar primero el encabezado MIME */
	printf("Content-type: text/html\n\n");
	
	/* Iniciar una conexion a Postgres con los datos especificados */
	conn = PQsetdbLogin("localhost", NULL, NULL,NULL, "prueba","postgres", "12345");

	/* Comprobar si la conexion fue creada correctamente */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "La conexion a la BD ha fallado: %s",	PQerrorMessage(conn) );
		salir_bien(conn);
	}

	/* Asignar la cadena de consulta a qs, abortar si esta vacia */
	if((qs = getenv("QUERY_STRING")) == NULL )
	{
		printf("No hay cadena de consulta a decodificar!<br> ");
		exit(1);
	}

	/* Dividir cada uno de los parametros de la cadena de consulta */
	for(i=0; qs[0] != '\0'; i++)
	{
	 /* Primero dividir por '&' cada parametro */
	 splitword(elementos[i].valor,qs,'&');
	 /* Convertir la cadena para caracteres exadecimales y signos mas */
	 unescape_url(elementos[i].valor);
	 /* separar ahora name y value */
	 splitword(elementos[i].nombre,elementos[i].valor,'=');    
	 
	}

	//Titulo de la pagina web
	printf("<HTML><HEAD><TITLE>Alta de un nuevo alumno</TITLE></HEAD>\n");
	//Cuerpo de la pagina web
	printf("<BODY bgcolor='#C9FF5C'>");

	printf("<br>Guardando... ");
  	guardar();		//Realizar el insert

	printf("<font color=\"blue\">Los siguientes datos fueron guardados (excepto el boton):</font><br>");
	for(i=0; elementos[i].nombre[0]; i++)
	 printf("<b>%s</b>=%s<br>",elementos[i].nombre,elementos[i].valor);
  	
	PQclear(res);
	
	//Cerrar la conexion a la BD y limpiar
	PQfinish(conn);
	
	printf("<br><form name=\"volver_indice\" action=\"http://localhost/lpq/index.html\" method=\"POST\">");
	printf("<input type=\"submit\" name=\"volver\" value=\"Volver al menu principal\">");
	printf("</form>");
	printf("</BODY>");

	return 0;
}

/* funcion del Libro */
void splitword(char *out, char *in, char stop)
{
  int i,j;

  for(i=0; in[i] && ( in[i] != stop ); i++)  
    out[i] = in[i];
  
  out[i] = '\0'; 	/* Terminar */
  if( in[i] )
    i++;

  for( j=0; in[j]; )
    in[j++] = in[i++];
}

/* funcion del Libro */
char x2c(char *x)
{
  register char c;
  /* NOTA: (x & oxdf) cambia a mayusculas a x */
  c = ( x[0] >= 'A' ? ( (x[0] & 0xdf) - 'A') +10 : ( x[0] -'0' ));
  c *= 16;
  c += (x[1] >= 'A' ? ( (x[1] & 0xdf) - 'A') +10 : ( x[1] -'0' ));
  return(c);
}

/* funcion del Libro */
void unescape_url(char *url)
{
  register int i,j;

  for(i=0, j=0; url[j]; ++i,++j)
  {
    if( (url[i] = url[j]) =='%' )
    {
      url[i] = x2c(&url[j+1]);
      j += 2;      
    }
    else if(url[i] == '+')
	  url[i] = ' ';
  }
  
  url[i] = '\0';	/* Terminar en la nueva longitud */
}

/*
	Guardar la lista de contactos que esta en la estructura de arrays en un archivo de disco.
*/
void guardar(void)
{
	/* Salvar los datos del StringQuery en la Estructura de datos */
	strcat(lista_alumnos.nc,elementos[0].valor);
	strcat(lista_alumnos.nombre, elementos[1].valor);
  	strcat(lista_alumnos.apellidos, elementos[2].valor);
  	strcat(lista_alumnos.direccion, elementos[3].valor);
  	
	lista_alumnos.estatura = atof(elementos[4].valor); 
	lista_alumnos.peso = atof(elementos[5].valor);
  	
  	strcat(lista_alumnos.fecha_ingreso, elementos[6].valor);
  	strcat(lista_alumnos.fecha_ingreso, "-");  
  	strcat(lista_alumnos.fecha_ingreso, elementos[7].valor); 
  	strcat(lista_alumnos.fecha_ingreso, "-");
  	strcat(lista_alumnos.fecha_ingreso, elementos[8].valor); 
  	
  	strcat(lista_alumnos.carrera, elementos[9].valor);
  	strcat(lista_alumnos.sexo, elementos[10].valor);
	
	/* Unir en una sola cadena los datos a insertar (formar la operacion insert de SQL) */
	strcat(cadSQL, "INSERT INTO alumnos VALUES(");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.nc);					strcat(cadSQL, "\',");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.nombre);				strcat(cadSQL, "\',");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.apellidos);			strcat(cadSQL, "\',");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.direccion);			strcat(cadSQL, "\',");
	strcat(cadSQL, elementos[4].valor);			strcat(cadSQL, ",");
	strcat(cadSQL, elementos[5].valor);			strcat(cadSQL, ",");	
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.fecha_ingreso);		strcat(cadSQL, "\',");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.carrera);				strcat(cadSQL, "\',");
	strcat(cadSQL, "\'");	strcat(cadSQL, lista_alumnos.sexo);					strcat(cadSQL, "\'");
	strcat(cadSQL, ")");

	/*Ejecutar la operacion SQL en el servidor */
	res = PQexec(conn, cadSQL);
	
	/* Si la operacion salio bien, mostrar un MSG, sino tbn (jejeje) */
	if ( PQresultStatus(res) == PGRES_COMMAND_OK )
	{
	printf(" ok");
		printf("<br>Estado de comando INSERT: %s<br><br>", PQresStatus(PQresultStatus(res)));
	}
	else
	{
		printf("Estado de la operacion SQL (insert): %s<br>", PQresStatus(PQresultStatus(res)));
	}
}

static void salir_bien(PGconn *conn)
{
	PQfinish(conn);
	exit(1);
}

Y aca se muestra una imagen con la pagina que muestra este programa en el navegador, despues de haber realizado la operacion INSERT en la tabla:


Como es de suponerse el usuario debe dar click en el boton para volver a la pagina principal.

formularioBajas.html
Por otra parte si en el menu de la pagina principal (index.html) el usuario da click en el boton Dar de baja entonces se abrira la pagina web de este achivo. Esta pagina tiene como objetivo capturar el Numero de control (n.c.) de un alumno al cual se desea dar de baja. Al dar click en el boton Dar de baja se enviara este numero de control a un programa CGI llamado bajaAlumnos.cgi que sera el que borrara al alumno con ese n.c. Este archivo esta almacenado en /usr/local/servidor_web/htdocs/lpq. Bueno a continuacion muestro el contenido de este este archivo:

<!--		Instituto Tecnologico de Zacatepec
    Descripcion:
    Formulario de datos que se usara para leer el NC del alumno que se dara de baja	 y enviarlo a un programa CGI
    Author:     Gonzalo Silverio  gonzasilve@gmail.com
    Archivo:    formularioBajas.html
-->
<html>
<head>
<title>Baja de un alumno</title>
</head>
<body bgcolor="#C9FF5C">
    <br>
    <form name="form_bajas" action="http://localhost/cgi-bin/lpq/bajaAlumnos.cgi" method="GET">
        <br>
        <table width="90%" border="1" align="center" bgcolor="#FFFFFF" >
            <tr>
                <td>
                    <table border="0" cellspacing="0" align="center" width="100%">
                        <tr>
                            <td colspan="2" bgcolor="#6D6DFF"><h2 align="center">
                                <font color="white"><br><img src="logo_web.gif" alt="gonzasilve">
                                    Baja de un alumno
                                </font></h2>
                            </td>
                        </tr>
                        <tr>
                            <td align="center"><br><br>
                                <b>Escriba el N.C del alumno<br> que desea dar de baja:</b><br>
                                <input type="text" name="nc" size="30" maxlength="10"><br><br>
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
        </table>
      <br><br>
      <table border="0" width="80%" align="center">
            <tr>
                <td colspan="2" align="center">
                    <input type="submit" name="baja" value="Dar de baja">&nbsp;&nbsp;&nbsp;
                </td>
                <td colspan="2" align="center">
                    <input type="reset" name="limpiar" value="Limpiar">&nbsp;&nbsp;&nbsp;
                </td>
                <td colspan="2" align="center">
                    <input type="Button" name="cancelar" value="Cancelar baja" onClick="location='http://localhost/lpq/index.html'">
                </td>
            </tr>
       </table>
    </form>
</body>
</html>

Y ahora la siguiente imagen muestra esta pagina en el navegador:

bajaAlumnos.cgi
Este archivo es un programa CGI y recibe a travez del formulario del archivo formularioBajas.html el n.c. de un alumno que se desea dar de baja. Despues de que recibe el n.c. establece una conexion con la BD y ejecuta una operacion DELETE sobre la tabla alumnos.Este archivo esta almacenado en /usr/local/servidor_web/cgi-bin/lpq. A continuacion A continuacion se muestra el codigo fuente en C de este programa CGI:


/*
	Instituto Tecnologico de Zacatepec
  Descripcion:	Programa que hace un DELETE para dar de baja a un alumno en una tabla de postgres
  Author:	Gonzalo Silverio  gonzasilve@gmail.com
  Archivo:	bajaAlumnos.c
  Compilar con: 
		cc -c -I/usr/local/pgsql/include bajaAlumnos.c
  Enlazar CGI con libreria LPQ con:
  		cc -o bajaAlumnos.cgi bajaAlumnos.o -L/usr/local/pgsql/lib -lpq
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "libpq-fe.h"

// Maximo 100 registros de alumnos
#define MAX 100

// Estrutura de datos que guarda los nombres de las variables CGI y sus valores de los formularios
struct 
{
  char nombre[128];
  char valor[128];
} elementos[MAX];


void  baja(void);

// declaraciones de las funciones que se van a utilizar en el programa
void splitword(char *out, char *in, char stop);
char x2c(char *x);
void unescape_url(char *url);
static void salir_bien(PGconn *conn);

// Almacenamiento temporal de la variable de ambiente
char *cp;
char *empty = "<vacio>";


	char *qs;	/* qs servira para guardar la cadena de consulta */

	int i,j;
	PGconn	   *conn;
	PGresult   *res;
	char cadSQL[8000];

int main(int argc, char **argv)
{
	// Enviar primero el encabezado MIME
	printf("Content-type: text/html\n\n");
	
	// Iniciar una conexion a Postgres con los datos especificados 
	conn = PQsetdbLogin("localhost", NULL, NULL,NULL, "prueba","postgres", "12345");

	// Comprobar si la conexion fue creada correctamente 
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "La conexion a la BD ha fallado: %s",	PQerrorMessage(conn) );
		salir_bien(conn);
	}

	// Asignar la cadena de consulta a qs, abortar si esta vacia
	if((qs = getenv("QUERY_STRING")) == NULL )
	{
		printf("No hay cadena de consulta a decodificar!<br> ");
		exit(1);
	}

	// Dividir cada uno de los parametros de la cadena de consulta
	for(i=0; qs[0] != '\0'; i++)
	{
	 // Primero dividir por '&' cada parametro
	 splitword(elementos[i].valor,qs,'&');
	 // Convertir la cadena para caracteres exadecimales y signos mas
	 unescape_url(elementos[i].valor);
	 // separar ahora name y value 
	 splitword(elementos[i].nombre,elementos[i].valor,'=');    
	 
	}

	//Titulo de la pagina web
	printf("<HTML><HEAD><TITLE>baja de un alumno</TITLE></HEAD>\n");
	//Cuerpo de la pagina web
	printf("<BODY bgcolor='#C9FF5C'><br>");

  	baja();
  	
	PQclear(res);
	
	// cerrar la conexion a la BD y limpiar
	PQfinish(conn);
	
	printf("<br><form name=\"volver_indice\" action=\"http://localhost/lpq/index.html\" method=\"POST\">");
	printf("<input type=\"submit\" name=\"volver\" value=\"Volver al menu principal\">");
	printf("</form>");
	printf("</BODY>");

	return 0;
}

/// funcion del Libro 
void splitword(char *out, char *in, char stop)
{
  int i,j;

  for(i=0; in[i] && ( in[i] != stop ); i++)  
    out[i] = in[i];
  
  out[i] = '\0'; 	// Terminar
  if( in[i] )
    i++;

  for( j=0; in[j]; )
    in[j++] = in[i++];
}

// funcion del Libro 
char x2c(char *x)
{
  register char c;
  // NOTA: (x & oxdf) cambia a mayusculas a x
  c = ( x[0] >= 'A' ? ( (x[0] & 0xdf) - 'A') +10 : ( x[0] -'0' ));
  c *= 16;
  c += (x[1] >= 'A' ? ( (x[1] & 0xdf) - 'A') +10 : ( x[1] -'0' ));
  return(c);
}

// funcion del Libro 
void unescape_url(char *url)
{
  register int i,j;

  for(i=0, j=0; url[j]; ++i,++j)
  {
    if( (url[i] = url[j]) =='%' )
    {
      url[i] = x2c(&url[j+1]);
      j += 2;      
    }
    else if(url[i] == '+')
	  url[i] = ' ';
  }
  
  url[i] = '\0';	// Terminar en la nueva longitud 
}

//	Ejecutar Operacion DELETE en el DBMS Postgres
void baja(void)
{	
	// Formar la cadena de la operacion SQL que se quiere mandar al server
	strcat(cadSQL, "DELETE FROM alumnos WHERE nc=\'");
	strcat(cadSQL, elementos[0].valor);
	strcat(cadSQL, "\'");
	
	// Ejecutar la operacion SQL en el servidor 
	res = PQexec(conn, cadSQL);
	
	// Si la operacion salio bien, mostrar un MSG, sino tbn (jejeje)
	if ( PQresultStatus(res) == PGRES_COMMAND_OK )
	{
		printf("<br>baja realizada con exito: %s<br>", PQresStatus(PQresultStatus(res)));
	}
	else
	{
		printf("Estado de la operacion SQL (delete): %s<br>", PQresStatus(PQresultStatus(res)));
	}	
}

static void salir_bien(PGconn *conn)
{
	PQfinish(conn);
	exit(1);
}

Una vez que se a ejecutado la operacion DELETE exitosamente el programa bajaAlumnos.cgi muestra una pagina web, la cual es la siguiente:


y pues nuevamente, el usuario debe dar click en el boton para volver a la pagina principal.

mostrarAlumnos.cgi
Si en la pagina principal el usuario da click en el boton Ver tabla entonces se ejecuta este programa CGI, el cual tiene la funcion de conectarse a la Base de datos y hacer una operacion SELECT para mostrar una pagina web en una tabla los datos de la tabla alumnos. Este archivo esta almacenado en /usr/local/servidor_web/cgi-bin/lpq. A continuacion el codigo fuente en C del programa CGI:

/*
	Instituto Tecnologico de Zacatepec
  Descripcion:	Programa CGI que hace un SELECT para mostrar el contenido de la tabla alumnos de postgres
  Author:	Gonzalo Silverio  gonzasilve@gmail.com
  Archivo:	mostrarAlumnos.c
  Compilar con: 
		cc -c -I/usr/local/pgsql/include mostrarAlumnos.c
  Enlazar CGI con libreria LPQ con:
  		cc -o mostrarAlumnos.cgi mostrarAlumnos.o -L/usr/local/pgsql/lib -lpq
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "libpq-fe.h"

void  mostrar(void);
static void salir_bien(PGconn *conn);

int i,j;
PGconn	   *conn;
PGresult   *res;
char cadSQL[8000];

int main(int argc, char **argv)
{
	// Enviar primero el encabezado MIME
	printf("Content-type: text/html\n\n");

	//titulo de la pagina web
	printf("<HTML><HEAD><TITLE>Uso de la libreria LPQ de Postgres</TITLE></HEAD><BODY bgcolor=\'#C9FF5C\'>");
		
	// Iniciar una conexion a Postgres con los datos especificados
	conn = PQsetdbLogin("localhost", NULL, NULL,NULL, "prueba","postgres", "12345");

	// Comprobar si la conexion fue creada correctamente
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "La conexion a la BD ha fallado: %s",	PQerrorMessage(conn) );
		salir_bien(conn);
	}

	printf("<br><h1 align='center'>CGI que usa la libreria LPQ de Postgres</h1>");
	printf("Consultando tabla alumnos......<br><br>");
  	mostrar();
  	
	PQclear(res);
	
	///Cerrar la conexion a la BD y limpiar
	PQfinish(conn);
	
	printf("<br><form name=\"volver_indice\" action=\"http://localhost/lpq/index.html\" method=\"POST\">");
	printf("<center><input type=\"submit\" name=\"volver\" value=\"Volver al menu principal\"></center>");
	printf("</form>");
	printf("</BODY></HTML>");

	return 0;
}


//	Muestra el contenido de la tabla Alumnos.
void mostrar(void)
{
	// Ejecutar la operacion Select SQL en el servidor Postgres
	res = PQexec(conn, "SELECT * FROM alumnos");
	
	// Si la operacion salio bien, mostrar la tabla HTML
	if ( PQresultStatus(res) == PGRES_TUPLES_OK )
	{
		int ntup, nf;
		ntup=PQntuples(res);		
		nf=PQnfields(res);	
		printf("<TABLE width=\'90%%\' BORDER=\'1\' align=\'center\' bgcolor=\'#FFFFFF\'> <TR> <TD align=\'center\'>");
		printf("<TABLE width=\'100%%\' BORDER=\'0\'>");
		printf("<TR bgcolor=\'#c9dfef\'>");
		printf("<TD align=\'center\'><b>N.C</b></TD><TD align=\'center\'><b>Nombre</b></TD><TD align=\'center\'><b>Apellidos</b></TD><TD align=\'center\'><b>Direccion</b></TD><TD align=\'center\'><b>Estatura</b></TD><TD align=\'center\'><b>Peso</b></TD><TD align=\'center\'><b>Fecha ingreso</b></TD><TD align=\'center\'><b>Carrera</b></TD><TD align=\'center\'><b>sexo</b></TD>");
		printf("</TR>");

		for (i=0; i<ntup; i++)
		{
			printf("<TR>");
		   for (j=0; j<nf; j++)
		   {
		   	printf("<TD align=\'center\'> %s </TD>", PQgetvalue(res, i, j));
		   }
			printf("</TR>");
		}
		printf("</TABLE>");
		printf("</TD> </TR></TABLE>");
	}
	else
	{
		printf("ERROR!, Estado de la consulta: %s<br>", PQresStatus(PQresultStatus(res)));
	}
	
}

static void salir_bien(PGconn *conn)
{
	PQfinish(conn);
	exit(1);
}

y aka la imagen con la la pagina web que genera el programa anterior, como se observa previamente e insertado 3 registros para que hubiera algo que mostrar.


Ufff, hasta que al fin acabe con este ejemplo (jejejej algo largo). Como se puede apreciar no pongo mucha explicacion sobre el codigo de los programas CGI, por que el objetivo es tener un apunte a la mano por si lo ocupo despues. Ademas no esta muy complicado de entender si sabes algo de lenguaje C .

Bueno, hasta pronto y espero comentarios o dudas acerca de este ejemplo, o si quieres los fuentes…. deja tu e-mail.

Anuncios

Acerca de gonzasilve
Freelance Web Developer.

7 Responses to Programa CGI en C que accesa una BD usando la libreria LPQ de Postgres

  1. juan says:

    oye disculpa una pregunta la consulta que haces mediante el formulario en el navegador ¿ la hace atravez de internet o en forma local?
    Lo que pasa es que necisto hacer un proyecto para acceder a una baase de datos mysql pero mediante lenguaje c.
    Si me puedes dar una asesoria te lo agradeceria bastante.

    • gonzasilve says:

      lo hago en forma local

  2. juan says:

    Excelente hermano. ¿oye se puede hacer eso mismo pero en mysql?
    ¿Conoces alguna libreria para acceder a una base de datos mysql mediante lenguaje c atravez de la web?

    • gonzasilve says:

      si, si se puede hacer eso mismo con MySQL. la verdad no tengo ningun ejemplo a la mano pero te mande este archivo a tu correo, el cual lo baje de la red, es este
      xd-blog.com.ar/descargas/manuales/programacion/mysql_en_c_sEc_undersecurity.pdf
      revisalo esta muuy bueno, hojala te sirva.

  3. Antonio Trejo says:

    Muy buena aportacion y a la programacion cgi con c, los textos te dicen la teoria pero ningun ejemplo practico como el tuyo, actualmente estoy haciendo algo semejante pero con mysql, el servidor web es apache y lo estoy compilando ( c ) para linux, mac y win pero tengo un problema y espero que puedas ayudarme, no logro configurar el servidor apache para que corra ejecutables ( .exe para win ), solo permite ejecutar scripts php, pl y java ( jsp ) y en la documentacion me dice que esto es por seguridad, sin embargo se que es posible ejecutar cualquier programa y lo ideal es que se puedan correr ejecutables de c/c++, cualquier idea, comentario o sugrencia sera bienvenida, saludos y gracias por la aportacion.

    • gonzasilve says:

      Hola que tal mi amigo Antonio, mira contestando a tu pregunta; sinceramente nunca he necesitado ejecutar un exe desde el servidor apache. pero atendiendo a tu pregunta me puse a investigar un poco y te doy los siguientes enlaces que me parecieron muy interesantes y que podrian resolver tu problema de ejecutar exe’s en apache. Los revisas y me dices si pudiste sino para seguir ayudandote ok?
      http://www.todoexpertos.com/categorias/tecnologia-e-internet/desarrollo-de-sitios-web/cgi/respuestas/184450/apache, http://www.algunascosas.com/ejecutar-aplicacion-con-php-y-windows, hasta pronto y espero te sirva de algo y gracias x pasar por aqui

      • Antonio says:

        Gracias Gonzalo, el problema se resolvio con una simple configuracion en el servidor apache, anexo el codigo por si le interesa a alguien:

        Esta es la configuracion para win, en mac y linux solo cambia el nombre del directorio root

        #
        # Possible values for the Options directive are “None”, “All”,
        # or any combination of:
        # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
        #
        # Note that “MultiViews” must be named *explicitly* — “Options All”
        # doesn’t give it to you.
        #
        # The Options directive is both complicated and important. Please see
        # http://httpd.apache.org/docs/2.2/mod/core.html#options
        # for more information.
        #
        Options Indexes FollowSymLinks ExecCGI

        #
        # AllowOverride controls what directives may be placed in .htaccess files.
        # It can be “All”, “None”, or any combination of the keywords:
        # Options FileInfo AuthConfig Limit
        #
        AllowOverride None

        #
        # Controls who can get stuff from this server.
        #
        Order allow,deny
        Allow from all

        AddHandler cgi-script .exe .cgi .php

        saludos

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: