Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 27 MySQL und C
  gp 27.1 Aufbau eines Datenbanksystems
    gp 27.1.1 Warum wurde ein Datenbanksystem (DBS) entwickelt?
    gp 27.1.2 Das Datenbank-Management-System (DBMS)
    gp 27.1.3 Relationale Datenbank
    gp 27.1.4 Eigene Clients mit C für SQL mit der ODBC-API entwickeln
  gp 27.2 MySQL installieren
    gp 27.2.1 Linux
    gp 27.2.2 Windows
    gp 27.2.3 Den Client mysql starten
  gp 27.3 Crashkurs (My)SQL
    gp 27.3.1 Was ist SQL?
    gp 27.3.2 Die Datentypen von (My)SQL
    gp 27.3.3 Eine Datenbank erzeugen
    gp 27.3.4 Eine Datenbank löschen
    gp 27.3.5 Datenbank wechseln
    gp 27.3.6 Eine Tabelle erstellen
    gp 27.3.7 Die Tabelle anzeigen
    gp 27.3.8 Tabellendefinition überprüfen
    gp 27.3.9 Tabelle löschen
    gp 27.3.10 Struktur einer Tabelle ändern
    gp 27.3.11 Datensätze eingeben
    gp 27.3.12 Datensätze auswählen
    gp 27.3.13 Ein fortgeschrittenes Szenario
    gp 27.3.14 Datensatz löschen
    gp 27.3.15 Datensatz ändern
    gp 27.3.16 Zugriffsrechte in MySQL
    gp 27.3.17 Übersicht über einige SQL-Kommandos
  gp 27.4 Die MySQL C-API
    gp 27.4.1 Grundlagen zur Programmierung eines MySQL-Clients
    gp 27.4.2 Client-Programm mit dem gcc- unter Linux und dem Cygwin gcc-Compiler unter Windows
    gp 27.4.3 MySQL Client-Programme mit dem VC++ Compiler und dem Borland Freeware Compiler
    gp 27.4.4 Troubleshooting
    gp 27.4.5 Das erste Client-Programm – Verbindung mit dem MySQL-Server herstellen
    gp 27.4.6 MySQL-Kommandozeilen-Optionen
    gp 27.4.7 Anfrage an den Server
  gp 27.5 MySQL und C mit CGI
    gp 27.5.1 HTML-Eingabeformular
    gp 27.5.2 CGI-Anwendung add_db.cgi
    gp 27.5.3 CGI-Anwendung search_db.cgi
  gp 27.6 Funktionsübersicht
  gp 27.7 Datentypenübersicht der C-API


Galileo Computing - Zum Seitenanfang

27.5 MySQL und C mit CGI  downtop

Zum Abschluss soll wie versprochen ein Beispiel erstellt werden, bei dem Sie mithilfe eines CGI-Webformulars eine Datenbank mit E-Mail-Adressen füttern. Auf diese Weise erstellen Sie quasi eine grafische Oberfläche zum Bedienen einer Datenbank mithilfe des Webbrowsers. Erzeugen Sie eine neue Datenbank mit dem Namen mail_archiv. Geben Sie dazu im mysql-Client Folgendes ein:

CREATE DATABASE mail_archiv;

Wechseln Sie in diese Datenbank mit USE und erstellen Sie eine Tabelle mit folgendem SQL-Kommando:

CREATE TABLE daten (adresse CHAR(255), name CHAR(255));

Galileo Computing - Zum Seitenanfang

27.5.1 HTML-Eingabeformular  downtop

Als Nächstes sollten Sie die HTML-Datei erstellen, mit der Sie die Daten eingeben können. Hier die Datei:

<html>
<head>
<title>Datenbank</title>
</head>
<body text="#000000" bgcolor="#FFFFFF" link="#FF0000" 
alink="#FF0000" vlink="#FF0000">
<h3>Datenbank (E-Mail-Adressen)</h3>
<hr><br>
<form action="http://localhost/cgi-bin/add_db.cgi" method=post>
Neuen Datensatz hinzufügen:
<pre>Name  : <input value="IhrName" name="Name" size="20">
E-Mail : <input value="adr@mail" name="E-Mail" size="20"></pre>
<input type=submit value="Hinzufügen">
</form>
<hr><br>
<form action=http://localhost/cgi-bin/search_db.cgi
      method=post>
In der Datenbank suchen:
<pre>Name   : <input value="IhrName" name="Name" size="20"></pre>
<input type=submit value="Suchen">
</form>
<hr>
</body>
</html>

Bei diesem HTML-Formular können zwei CGI-Anwendungen gestartet werden: zum einen das Einfügen neuer Daten in die Datenbank (add_db.cgi) und zum anderen das Suchen darin (search_db.cgi).

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 27.9   HTML-Formular zur Eingabe oder Suche von Datensätzen


Galileo Computing - Zum Seitenanfang

27.5.2 CGI-Anwendung add_db.cgi  downtop

Zuerst wird die CGI-Anwendung zum Hinzufügen neuer Datensätze in die Datenbank geschrieben. Dabei finden Sie wieder alte bekannte Funktionen aus den Abschnitten zu CGI und C. Ich habe mich entschlossen, das Listing hier vollständig zu schreiben, da ich es auch nicht mag, ständig in einem Buch hin- und her zu blättern.

/* add_db.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined __WIN32__ || _MSC_VER
    #include <windows.h>
#endif
#include <mysql.h>
// Für VC++:
//#include "c:\mysql\include\mysql.h"
#define MAX_PAARE 255
#define BUF 255
struct CGI_DATEN {
   char *variable;
   char *wert;
   struct CGI_DATEN *next;
};
struct CGI_DATEN *ende = NULL;
MYSQL *mysql;
void print_html(void);
char *getdata(void);
char *Strdup(const char *);
void hex2ascii(char *);
char convert(char *);
void loeschen(struct CGI_DATEN *);
struct CGI_DATEN *erstellen(char *);
void check_error(void);
void verbinden(void);
void verbindung_schliessen(void);
/* Weiterleitung zu einer URL
 * url ist die URL, wo Sie den User weiterleiten
 */
void print_html(void) {
   printf("<html><head>\n");
   printf("<title>Eintragsbestätigung</title>\n");
   printf("</head><body>\n");
   printf("Eintragung erfolgreich. Zurück gehts"
          " <a href=\"javascript:history.back()\">hier</a>");
   printf("</body></html>\n");
}
/*  Funktion liest Daten in der POST oder GET-Methode ein.
 *  Rückgabewert: Stringpuffer mit den Daten
 *  bei Fehler  : NULL
 */
char *getdata(void) {
   unsigned long size;
   char *puffer = NULL;
   char *request = getenv("REQUEST_METHOD");
   char *cont_len;
   char *cgi_string;
   /* Zuerst die Request-Methode überprüfen */
   if(  NULL == request )
      return NULL;
   else if( strcmp(request, "GET") == 0 ) {
      /* Die Methode GET -> Query String abholen */
      cgi_string = getenv("QUERY_STRING");
      if( NULL == cgi_string )
         return NULL;
      else {
         puffer =(char *) Strdup(cgi_string);
         return puffer; /* Rückgabewert an den Aufrufer */
      }
   }
   else if( strcmp(request, "POST") == 0 ) {
      /* Die Methode POST -> Länge des Strings
       * ermitteln (CONTENT_LENGTH) */
      cont_len = getenv("CONTENT_LENGTH");
      if( NULL == cont_len)
         return NULL;
      else {  /* String CONTENT_LENGTH in
               * unsigned long umwandeln */
         size = (unsigned long) atoi(cont_len);
         if(size <= 0)
            return NULL; /* Keine Eingabe!?!? */
      }
      /* Jetzt lesen wir die Daten von stdin ein */
      puffer =(char *) malloc(size+1);
      if( NULL == puffer )
         return NULL;
      else {
         if( NULL == fgets(puffer, size+1, stdin) ) {
            free(puffer);
            return NULL;
         }
         else   /* Rückgabewerte an den Ausrufer */
            return puffer;
      }
   }
   /* Weder GET-Methode noch die POST-Methode wurden verwendet */
   else
      return NULL;
}
/*  Da die Funktion strdup() in der Headerdatei <string.h> keine
 *  ANSI C-Funktion ist, schreiben wir eine eigene
 */
char *Strdup(const char *str) {
   char *p;
   if(NULL == str)
       return NULL;
   else {
      p =(char *) malloc(strlen(str)+1);
      if(NULL == p)
         return NULL;
      else
         strcpy(p, str);
   }
   return p;
}
/* Wandelt einzelne Hexzeichen (%xx) in ASCII-Zeichen
 * und kodierte Leerzeichen (+) in echte Leerzeichen um */
void hex2ascii(char *str) {
   int x, y;
   for(x=0,y=0; str[y] != '\0'; ++x,++y) {
      str[x] = str[y];
      /* Ein hexadezimales Zeichen ? */
      if(str[x] == '%') {
         str[x] = convert(&str[y+1]);
         y += 2;
      }
      /* Ein Leerzeichen ? */
      else if( str[x] == '+')
         str[x]=' ';
   }
   /* Geparsten String sauber terminieren */
   str[x] = '\0';
}
/* Funktion konvertiert einen String von zwei hexadezimalen
 * Zeichen und gibt das einzelne dafür stehende Zeichen zurück
 */
char convert(char *hex) {
   char ascii;
   /* erster Hexawert */
   ascii =
   (hex[0] >= 'A' ? ((hex[0] & 0xdf) – 'A')+10 : (hex[0] – '0'));
   ascii <<= 4; /* Bitverschiebung schneller als ascii*=16 */
   /* zweiter Hexawert */
   ascii +=
   (hex[1] >= 'A' ? ((hex[1] & 0xdf) – 'A')+10 : (hex[1] – '0'));
   return ascii;
}
/* Liste aus Variable/Wert-Paaren erstellen
 * Rückgabewert: Anfangsadresse der Liste
 * Bei Fehler: NULL
 */
struct CGI_DATEN *erstellen(char *str) {
   char* s;
   char* res;
   /* Irgendwo gibt es auch eine Grenze, hier sind
      MAX_PAARE erlaubt */
   char *paare[MAX_PAARE];
   struct CGI_DATEN *ptr_daten = NULL;
   struct CGI_DATEN *ptr_anfang = NULL;
   int i=0, j=0;
   /* Zuerst werden die Variablen/Werte-Paare anhand des Zeichens
    * '&' getrennt, sofern es mehrere sind */
   s=str;
   res=strtok(s,"&");
   while( res != NULL && i < MAX_PAARE) {
      /* Wert von res dynamisch in char **pair speichern */
      paare[i] = (char *)malloc(strlen(res)+1);
      if(paare[i] == NULL)
         return NULL;
      paare[i] = res;
      res=strtok(NULL,"&");
      i++;
   }
   /* Jetzt werden die Variablen von den Werten getrennt und
    * an die Struktur CGI_DATEN übergeben */
   while ( i > j ) {  /* Das erste Element ? */
      if(ptr_anfang == NULL) {
         ptr_anfang =(struct CGI_DATEN *)
           malloc(sizeof (struct CGI_DATEN *));
         if( ptr_anfang == NULL )
            return NULL;
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_anfang->variable =(char *) malloc(strlen(res)+1);
         if( ptr_anfang->variable == NULL )
            return NULL;
         ptr_anfang->variable = res;
         res = strtok(NULL, "\0");
         if(res == NULL)
            return NULL;
         ptr_anfang->wert =(char *) malloc(strlen(res)+1);
         if( ptr_anfang->wert == NULL )
            return NULL;
         ptr_anfang->wert = res;
         /* printf("%s %s<br>",
          * ptr_anfang->variable, ptr_anfang->wert); */
         ptr_anfang->next = (struct CGI_DATEN *)
            malloc(sizeof (struct CGI_DATEN *));
         if(ptr_anfang->next == NULL)
            return NULL;
         ptr_daten = ptr_anfang->next;
         j++;
      }
      else { /* Die restlichen Elemente */
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_daten->variable =(char *) malloc(strlen(res)+1);
         if(ptr_daten->variable == NULL)
            return NULL;
         ptr_daten->variable = res;
         res = strtok(NULL, "\0");
         if(res == NULL)
            return NULL;
         ptr_daten->wert =(char *) malloc(strlen(res)+1);
         if(ptr_daten->wert == NULL)
            return NULL;
         ptr_daten->wert = res;
         /* printf("%s %s<br>",
          * ptr_daten->variable, ptr_daten->wert); */
         ptr_daten->next = (struct CGI_DATEN *)
            malloc(sizeof (struct CGI_DATEN *));
         if( ptr_daten->next == NULL )
            return NULL;
         ptr_daten = ptr_daten->next;
         j++;
      }
   }
   ende = ptr_daten;
   /* Anfangsadresse der Liste struct CGI_DATEN zurückgeben */
   return ptr_anfang;
}
/* Bricht bei Fehler (mysql_error != 0) das Programm ab */
void check_error(void)  {
   if (mysql_errno(mysql) != 0) {
      fprintf(stderr, "Fehler: %s\n", mysql_error(mysql));
      exit(EXIT_FAILURE);
   }
}
/* Baut eine Verbindung zum Datenbankserver auf.
 * Passen Sie ggf. Usernamen und Passwort und, sofern
 * andere Parameter benötigt werden, diese Ihren Umständen
 * selbst an
 */
void verbinden(void)  {
   mysql= mysql_init(mysql);
   check_error();
   mysql_real_connect(mysql, "localhost", "root",
      NULL, NULL, 0, NULL, 0);
   check_error();
}
/* Serververbindung wieder schließen und den Speicher für die
 * Struktur MYSQL wieder freigeben */
void verbindung_schliessen(void)  {
   mysql_close(mysql);
}
/* Falls Datenbank bei der Funktion verbinden() nicht angegeben
 * wurde oder Sie die Datenbank wechseln wollen, dann verwenden
 * Sie diese Funktion */
void db_waehlen(char *db) {
   mysql_select_db(mysql, db);
   check_error();
}
/* Daten mit mysql_real_query() in die Datenbank schreiben */
void daten_anfuegen(struct CGI_DATEN *daten) {
   char buf[BUF] = "INSERT INTO daten (name, adresse) VALUES ('";
   strcat(buf, daten->wert);
   strcat(buf, "', '");
   daten = daten->next;
   strcat(buf, daten->wert);
   strcat(buf, "');");
   /* Jetzt die Anfrage an den Datenbankserver */
   mysql_real_query(mysql, buf, strlen(buf));
   check_error();
}
int main(void) {
   char *str;
   struct CGI_DATEN *cgi;
   struct CGI_DATEN *free_cgi;
   /* Für Fehlermeldungen */
   printf("Content-Type: text/html\n\n");
   /* Eingabe einlesen */
   str = getdata();
   if(str == NULL) {
      printf("Fehler beim Einlesen von der Formulareingabe");
      return EXIT_FAILURE;
   }
   /* Hexzeichen in ASCII-Zeichen konvertieren und aus '+'
    * Leerzeichen machen */
   hex2ascii(str);
   /* Liste der Formualar-Daten erstellen */
   cgi = erstellen(str);
   free_cgi = cgi;
   if (cgi == NULL) {
      printf("Fehler beim Erstellen der "
             "Variablen/Werte-Liste!!\n");
      return EXIT_FAILURE;
   }
   verbinden();
   db_waehlen("mail_archiv");
   daten_anfuegen(cgi);
   verbindung_schliessen();
   print_html();
   return EXIT_SUCCESS;
}

Übersetzen Sie den Quellcode wieder wie gewohnt, ändern Sie die Extension (*.cgi) und speichern Sie die ausführbare Datei im cgi-bin-Verzeichnis des (Apache-)Webservers. Unter Linux werden dafür teilweise root-Rechte benötigt. Ändern Sie außerdem unter Linux die Zugriffsrechte für diese Datei (chmod go+rx add_db.cgi). Weiteres finden Sie in Kapitel 26, CGI mit C, welches Sie bereits durchgenommen haben sollten, bevor Sie sich an dieses Programm wagen.


Galileo Computing - Zum Seitenanfang

27.5.3 CGI-Anwendung search_db.cgi  toptop

Als Nächstes folgt die CGI-Anwendung zur Suche in der Datenbank mail_archiv, welche im Großen und Ganzen ebenfalls nichts Neues mehr enthält, was nicht bereits besprochen wurde.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined __WIN32__ || _MSC_VER
    #include <windows.h>
#endif
#include <mysql.h>
// Für VC++:
//#include "c:\mysql\include\mysql.h"
#define MAX_PAARE 255
#define BUF 255
struct CGI_DATEN {
   char *variable;
   char *wert;
   struct CGI_DATEN *next;
};
struct CGI_DATEN *ende = NULL;
MYSQL *mysql;
void print_html(void);
char *getdata(void);
char *Strdup(const char *);
void hex2ascii(char *);
char convert(char *);
void loeschen(struct CGI_DATEN *);
struct CGI_DATEN *erstellen(char *);
void check_error(void);
void verbinden(void);
void verbindung_schliessen(void);
/* Weiterleitung zu einer URL
 * url ist die URL, wo Sie den User weiterleiten
 */
void print_html(void) {
   printf("<html><head>\n");
   printf("<title>Suchergebniss</title>\n");
   printf("</head><body>\n");
   printf("<br><br>Zurück gehts "
          "<a href=\"javascript:history.back()\">hier</a>");
   printf("</body></html>\n");
}
/*  Funktion liest Daten in der POST oder GET-Methode ein.
 *  Rückgabewert: Stringpuffer mit den Daten
 *  bei Fehler  : NULL
 */
char *getdata(void) {
   unsigned long size;
   char *puffer = NULL;
   char *request = getenv("REQUEST_METHOD");
   char *cont_len;
   char *cgi_string;
   /* Zuerst die Request-Methode überprüfen */
   if(  NULL == request )
      return NULL;
   else if( strcmp(request, "GET") == 0 ) {
      /* Die Methode GET -> Query String abholen */
      cgi_string = getenv("QUERY_STRING");
      if( NULL == cgi_string )
         return NULL;
      else {
         puffer =(char *) Strdup(cgi_string);
         return puffer; /* Rückgabewert an den Aufrufer */
      }
   }
   else if( strcmp(request, "POST") == 0 ) {
      /* Die Methode POST -> Länge des Strings
       * ermitteln (CONTENT_LENGTH) */
      cont_len = getenv("CONTENT_LENGTH");
      if( NULL == cont_len)
         return NULL;
      /* String CONTENT_LENGTH in unsigned long umwandeln */
      else {
         size = (unsigned long) atoi(cont_len);
         if(size <= 0)
            return NULL; /* Keine Eingabe!?!? */
      }
      /* Jetzt lesen wir die Daten von stdin ein */
      puffer =(char *) malloc(size+1);
      if( NULL == puffer )
         return NULL;
      else {
         if( NULL == fgets(puffer, size+1, stdin) ) {
            free(puffer);
            return NULL;
         }
         else   /* Rückgabewerte an den Ausrufer */
            return puffer;
      }
   }
   /* Weder GET-Methode noch die POST-Methode wurden verwendet */
   else
      return NULL;
}
/*  Da die Funktion strdup() in der Headerdatei <string.h> keine
 *  ANSI C-Funktion ist, schreiben wir eine eigene
 */
char *Strdup(const char *str) {
   char *p;
   if(NULL == str)
      return NULL;
   else {
      p = (char *)malloc(strlen(str)+1);
      if(NULL == p)
         return NULL;
      else
         strcpy(p, str);
   }
   return p;
}
/* Wandelt einzelne Hexzeichen (%xx) in ASCII-Zeichen
   und kodierte Leerzeichen (+) in echte Leerzeichen um */
void hex2ascii(char *str) {
   int x, y;
   for(x=0,y=0; str[y] != '\0'; ++x,++y) {
      str[x] = str[y];
      /* Ein hexadezimales Zeichen ? */
      if(str[x] == '%') {
         str[x] = convert(&str[y+1]);
         y += 2;
      }
      /* Ein Leerzeichen ? */
      else if( str[x] == '+')
         str[x]=' ';
   }
   /* Geparsten String sauber terminieren */
   str[x] = '\0';
}
/* Funktion konvertiert einen String von zwei hexadezimalen
 * Zeichen und gibt das einzelne dafür stehende Zeichen zurück
 */
char convert(char *hex) {
   char ascii;
   /* erster Hexawert */
   ascii =
   (hex[0] >= 'A' ? ((hex[0] & 0xdf) – 'A')+10 : (hex[0] – '0'));
   ascii <<= 4; /* Bitverschiebung schneller als ascii*=16 */
   /* zweiter Hexawert */
   ascii +=
   (hex[1] >= 'A' ? ((hex[1] & 0xdf) – 'A')+10 : (hex[1] – '0'));
   return ascii;
}
/* Liste aus Variable/Wert-Paaren erstellen
 * Rückgabewert: Anfangsadresse der Liste
 * Bei Fehler: NULL
 */
struct CGI_DATEN *erstellen(char *str) {
   char* s;
   char* res;
   /* Irgendwo gibt es auch eine Grenze, hier
      sind MAX_PAARE erlaubt */
   char *paare[MAX_PAARE];
   struct CGI_DATEN *ptr_daten = NULL;
   struct CGI_DATEN *ptr_anfang = NULL;
   int i=0, j=0;
   /* Zuerst werden die Variablen/Werte-Paare anhand des Zeichens
    * '&' getrennt, sofern es mehrere sind */
   s=str;
   res=strtok(s,"&");
   while( res != NULL && i < MAX_PAARE) {
      /* Wert von res dynamisch in char **pair speichern */
      paare[i] = (char *)malloc(strlen(res)+1);
      if(paare[i] == NULL)
         return NULL;
      paare[i] = res;
      res=strtok(NULL,"&");
      i++;
   }
   /* Jetzt werden die Variablen von den Werten getrennt und
    * an die Struktur CGI_DATEN übergeben */
   while ( i > j )  { /* Das erste Element ? */
      if(ptr_anfang == NULL) {
         ptr_anfang =(struct CGI_DATEN *) malloc
            (sizeof (struct CGI_DATEN *));
         if( ptr_anfang == NULL )
            return NULL;
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_anfang->variable = (char *) malloc(strlen(res)+1);
         if( ptr_anfang->variable == NULL )
            return NULL;
         ptr_anfang->variable = res;
         res = strtok(NULL, "\0");
         if(res == NULL)
            return NULL;
         ptr_anfang->wert = (char *) malloc(strlen(res)+1);
         if( ptr_anfang->wert == NULL )
            return NULL;
         ptr_anfang->wert = res;
         /* printf("%s %s<br>",
          * ptr_anfang->variable, ptr_anfang->wert); */
         ptr_anfang->next = (struct CGI_DATEN *)
            malloc(sizeof (struct CGI_DATEN *));
         if(ptr_anfang->next == NULL)
            return NULL;
         ptr_daten = ptr_anfang->next;
         j++;
      }
      else { /* Die restlichen Elemente */
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_daten->variable =(char *) malloc(strlen(res)+1);
         if(ptr_daten->variable == NULL)
            return NULL;
         ptr_daten->variable = res;
         res = strtok(NULL, "\0");
         if(res == NULL)
            return NULL;
         ptr_daten->wert = (char *)malloc(strlen(res)+1);
         if(ptr_daten->wert == NULL)
            return NULL;
         ptr_daten->wert = res;
         /* printf("%s %s<br>",
          * ptr_daten->variable, ptr_daten->wert); */
         ptr_daten->next = (struct CGI_DATEN *)
            malloc(sizeof (struct CGI_DATEN *));
         if( ptr_daten->next == NULL )
            return NULL;
         ptr_daten = ptr_daten->next;
         j++;
      }
   }
   ende = ptr_daten;
   /* Anfangsadresse der Liste struct CGI_DATEN zurückgeben */
   return ptr_anfang;
}
/* Bricht bei Fehler (mysql_error != 0) das Programm ab */
void check_error(void) {
   if (mysql_errno(mysql) != 0) {
      fprintf(stderr, "Fehler: %s\n", mysql_error(mysql));
      exit(EXIT_FAILURE);
   }
}
/* Baut eine Verbindung zum Datenbankserver auf.
 * Passen Sie ggf. Usernamen und Passwort und, sofern
 * andere Parameter benötigt werden, diese Ihren Umständen
 * selbst an
 */
void verbinden(void)  {
   mysql= mysql_init(mysql);
   check_error();
   mysql_real_connect(mysql, "localhost", "root",
                      NULL, NULL, 0, NULL, 0);
   check_error();
}
/* Serververbindung wieder schließen und den Speicher für die
 * Struktur MYSQL wieder freigeben */
void verbindung_schliessen(void)  {
   mysql_close(mysql);
}
/* Falls Datenbank bei der Funktion verbinden() nicht angegeben
 * wurde oder Sie die Datenbank wechseln wollen, dann verwenden
 * Sie diese Funktion */
void db_waehlen(char *db) {
   mysql_select_db(mysql, db);
   check_error();
}
/* Daten mit mysql_real_query() in die Datenbank schreiben */
void daten_suchen(struct CGI_DATEN *daten) {
   MYSQL_ROW  row;
   MYSQL_RES  *mysql_res;
   unsigned long  anzahl_reihen;
   unsigned int i;
   char buf[BUF] = "SELECT adresse FROM daten WHERE name='";
   strcat(buf, daten->wert);
   strcat(buf, "';");
   mysql_real_query(mysql, buf, strlen(buf));
   check_error();
   /* Daten der Anfrage abholen */
   mysql_res = mysql_store_result(mysql);
   check_error();
   /* Anzahl der gefundenen Datensätze ermitteln */
   anzahl_reihen = (unsigned long) mysql_num_rows (mysql_res);
   printf ("Anzahl gefunden: %lu\n\n<br><br>", anzahl_reihen);
   /* Gefundenen Datensatz bzw. Datensätze ausgeben */
   while ((row = mysql_fetch_row (mysql_res)) != NULL) {
      /* Einzelne Spalten der Zeile ausgeben */
      for (i = 0;  i < mysql_num_fields(mysql_res);  i ++)
         printf ("Addresse zu %s lautet %s<br> ",
           daten->wert,row[i]);
         printf("\n");
   }
   /* Speicherplatz wieder freigeben */
   mysql_free_result(mysql_res);
}
int main(void) {
   char *str;
   struct CGI_DATEN *cgi;
   struct CGI_DATEN *free_cgi;
   /* Für Fehlermeldungen */
   printf("Content-Type: text/html\n\n");
   /* Eingabe einlesen */
   str = getdata();
   if(str == NULL) {
      printf("Fehler beim Einlesen von der Formulareingabe");
      return EXIT_FAILURE;
   }
   /* Hexzeichen in ASCII-Zeichen konvertieren und aus '+'
    * Leerzeichen machen */
   hex2ascii(str);
   /* Liste der Formualar-Daten erstellen */
   cgi = erstellen(str);
   free_cgi = cgi;
   if (cgi == NULL) {
      printf("Fehler beim Erstellen der "
             "Variablen/Werte-Liste!!\n");
      return EXIT_FAILURE;
   }
   verbinden();
   db_waehlen("mail_archiv");
   daten_suchen(cgi);
   verbindung_schliessen();
   print_html();
   return EXIT_FAILURE;
}

Natürlich gilt auch hier: Übersetzen Sie den Quellcode wie gewohnt, ändern Sie die Extension (*.cgi) und speichern Sie die ausführbare Datei im cgi-bin-Verzeichnis des (Apache-)Webservers. Unter Linux werden dafür teilweise root-Rechte benötigt. Ändern Sie außerdem unter Linux die Zugriffsrechte für diese Datei (chmod go+rx search_db.cgi).

Das war es. Wenn Sie jetzt wollen, können Sie die CGI-Anwendungen mit MySQL in der Praxis testen. Öffnen Sie dazu mit Ihrem Webrowser das erstellte HTML-Formular. Jetzt können Sie munter Datensätze in die Datenbank einfügen oder in den Datensätzen suchen. Voraussetzung dafür, dass dies auch funktioniert, ist, dass der (Apache-)Webserver und der Datenbankserver MySQL gestartet wurden.

Mit diesem Beispiel haben Sie jetzt die Grundlagen für komplexere Aufgaben mit der MySQL-Datenbank geschaffen.


Hinweis   Noch mehr zur MySQL C-API (und auch der PostgreSQL C-API) finden Sie in meinem Buch »Linux-UNIX-Programmmierung« bzw. auf meiner Homepage und www.pronix.de.


 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de