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

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 24 MySQL und C
Pfeil 24.1 Aufbau eines Datenbanksystems
Pfeil 24.1.1 Warum wurde ein Datenbanksystem (DBS) entwickelt?
Pfeil 24.1.2 Das Datenbank-Management-System (DBMS)
Pfeil 24.1.3 Relationale Datenbank
Pfeil 24.1.4 Eigene Clients mit C für SQL mithilfe der ODBC-API entwickeln
Pfeil 24.2 MySQL installieren
Pfeil 24.2.1 Linux
Pfeil 24.2.2 Den Client »mysql« starten
Pfeil 24.3 Crashkurs (My)SQL
Pfeil 24.3.1 Was ist SQL?
Pfeil 24.3.2 Die Datentypen von (My)SQL
Pfeil 24.3.3 Eine Datenbank erzeugen
Pfeil 24.3.4 Eine Datenbank löschen
Pfeil 24.3.5 Datenbank wechseln
Pfeil 24.3.6 Eine Tabelle erstellen
Pfeil 24.3.7 Die Tabelle anzeigen
Pfeil 24.3.8 Tabellendefinition überprüfen
Pfeil 24.3.9 Tabelle löschen
Pfeil 24.3.10 Struktur einer Tabelle ändern
Pfeil 24.3.11 Datensätze eingeben
Pfeil 24.3.12 Datensätze auswählen
Pfeil 24.3.13 Ein fortgeschrittenes Szenario
Pfeil 24.3.14 Datensatz löschen
Pfeil 24.3.15 Datensatz ändern
Pfeil 24.3.16 Zugriffsrechte in MySQL
Pfeil 24.3.17 Übersicht über einige SQL-Kommandos
Pfeil 24.4 Die MySQL-C-API
Pfeil 24.4.1 Grundlagen zur Programmierung eines MySQL-Clients
Pfeil 24.4.2 Client-Programm mit dem gcc unter Linux und dem Cygwin–gcc-Compiler unter Windows
Pfeil 24.4.3 MySQL Client-Programme mit dem VC++ Compiler und dem Borland Freeware Compiler
Pfeil 24.4.4 Troubleshooting
Pfeil 24.4.5 Das erste Client-Programm – Verbindung mit dem MySQL-Server herstellen
Pfeil 24.4.6 MySQL-Kommandozeilen-Optionen
Pfeil 24.4.7 Anfrage an den Server
Pfeil 24.5 MySQL und C mit CGI
Pfeil 24.5.1 HTML-Eingabeformular
Pfeil 24.5.2 Die CGI-Anwendung »add_db.cgi«
Pfeil 24.5.3 Die CGI-Anwendung »search_db.cgi«
Pfeil 24.6 Funktionsübersicht
Pfeil 24.7 Datentypenübersicht der C-API


Rheinwerk Computing - Zum Seitenanfang

24.5 MySQL und C mit CGI Zur nächsten ÜberschriftZur vorigen Überschrift

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 mit USE in diese Datenbank, und erstellen Sie eine Tabelle mit folgendem SQL-Kommando:

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

Rheinwerk Computing - Zum Seitenanfang

24.5.1 HTML-Eingabeformular Zur nächsten ÜberschriftZur vorigen Überschrift

Als Nächstes sollten Sie die HTML-Datei erstellen, mit der Sie die Daten eingeben können. Die Datei sieht wie folgt aus:

<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 24.9 HTML-Formular zur Eingabe oder Suche von Datensätzen


Rheinwerk Computing - Zum Seitenanfang

24.5.2 Die CGI-Anwendung »add_db.cgi« Zur nächsten ÜberschriftZur vorigen Überschrift

Zuerst wird die CGI-Anwendung zum Hinzufügen neuer Datensätze in die Datenbank geschrieben. Dabei finden Sie wieder altbekannte Funktionen aus den Abschnitten zu CGI und C. Ich habe mich entschlossen, das Listing hier vollständig wiederzugeben, 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 "my_global.h"
   #include "mysql.h"
#else
   #include <mysql.h>
#endif

#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, an die 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");
}

/*  Die Funktion liest Daten mit 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 = 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 = 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 Aufrufer */
            return puffer;
      }
   }
   /* Weder die 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 = 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 =malloc(sizeof (struct CGI_DATEN));
         if( ptr_anfang == NULL )
            return NULL;
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_anfang->variable = 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 = 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 =
            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 = 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 = 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 =
            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 selbst an Ihre
 * Bedürfnisse 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 die 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 23, »CGI mit C«, das Sie bereits durchgenommen haben sollten, bevor Sie sich an dieses Programm wagen.


Rheinwerk Computing - Zum Seitenanfang

24.5.3 Die CGI-Anwendung »search_db.cgi« topZur vorigen Überschrift

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

/* search_db.c */
#include <stdio.h>
#include <stdlib.h>
#if defined __WIN32__ || _MSC_VER
   #include "my_global.h"
   #include "mysql.h"
#else
   #include <mysql.h>
#endif

#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, an die 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");
}

/*  Die Funktion liest Daten mit 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 = 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 = 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 Aufrufer */
            return puffer;
      }
   }
   /* Weder die 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 = 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';
}

/* Die 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] = 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 = malloc (sizeof (struct CGI_DATEN));
         if( ptr_anfang == NULL )
            return NULL;
         res = strtok( paare[j], "=");
         if(res == NULL)
            return NULL;
         ptr_anfang->variable = 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 = 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 =
            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 = 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 = 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 =
            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 selbst an
 * Ihre Bedürfnisse 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 die 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 ("Adresse 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. Die 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 zur PostgreSQL-C-API) finden Sie in meinem Buch »Linux-UNIX-Programmierung« (ebenfalls beim Rheinwerk Verlag erschienen).




Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: C/C++






 C/C++


Zum Katalog: Einstieg in C






 Einstieg in C


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
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.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de