CGI-Programme in C/C++ erstellen (unter Linux mit Apache)
Andreas Schigold
- cgi
Hallo liebe Selfforumer,
irgendjemand von Euch weiß doch bestimmt, wie man CGI-Programme in C/C++ schreibt? Es wäre jedenfalls wahnsinnig nett, wenn mir jemand verraten könnte, was ich hier falsch gemacht habe oder was ich noch machen muß, damit es funzt.
folgender simpler Quellcode sollte einfach zu einer entsprechenden Anzeige im WebBrowser führen:
Datei webcgi.c:
#include <stdio.h>
int main()
{
printf("<html>\n\t<head>\n\t\t<title></title>\n\t</head>\n\t<body>\n\t\tHallo Welt!\n\t</body>\n</html>\n");
return 0;
}
mit dem gcc kompiliert...:
gcc -o webcgi webcgi.c
... und nach /usr/local/httpd/cgi-bin kopiert:
cp webcgi /usr/local/httpd/cgi-bin
Dann im Webbrowser eingegeben: "http://127.0.0.1/cgi-bin/webcgi"
Leider kam dann nicht das erhoffte "Hallo Welt!", sondern eine Meldung über einen internal Server Error.
Weiß jemand, was ich da falsch gemacht habe? Oder muß ich am Apache noch was konfigurieren? Oder brauche ich ein bestimmtes Modul dazu?
Bin für alle Anregungen dankbar, vor allem auch für Webseiten zu diesem Thema.
gruesse
Andreas Schigold
PS: Ziel ist eine Applikation, die auf ein bereits bestehendes Framework von C++ - Klassen zurückgreift und einen Webbrowser als Oberfläche nutzt, um in einer Applikation die Fähigkeiten lokal und remote anzubieten, wobei lokal ein Linux-Rechner und remote meist ein Windows-Rechner ist.
hi!
irgendjemand von Euch weiß doch bestimmt, wie man CGI-Programme in
C/C++ schreibt? Es wäre jedenfalls wahnsinnig nett, wenn mir
jemand verraten könnte, was ich hier falsch gemacht habe oder was
ich noch machen muß, damit es funzt.
Vor allem musst du am Anfang eines CGI-Programms einen passenden
HTTP-Header ausgeben. Das hast du nicht gemacht. Also sowas wie
printf("Content-type: text/html\n\n");
Ist bei Perl-Skripten, die über CGI laufen sollen, genauso, falls
du sowas schonmal gemacht hast.
bye, Frank!
Hallo Frank (und alle anderen),
erstmal vielen vielen Dank für die vielen Infos. Aber das mit dem HTTP-Header und der Minimal-info über den Content-Type war genau das, weshalb es nicht ging.
Danke nochmal
Andreas Schigold
hi!
irgendjemand von Euch weiß doch bestimmt, wie man CGI-Programme in
C/C++ schreibt? Es wäre jedenfalls wahnsinnig nett, wenn mir
jemand verraten könnte, was ich hier falsch gemacht habe oder was
ich noch machen muß, damit es funzt.
Vor allem musst du am Anfang eines CGI-Programms einen passenden
HTTP-Header ausgeben. Das hast du nicht gemacht. Also sowas wie
printf("Content-type: text/html\n\n");
Ist bei Perl-Skripten, die über CGI laufen sollen, genauso, falls
du sowas schonmal gemacht hast.
bye, Frank!
Hallo,
irgendjemand von Euch weiß doch bestimmt, wie man CGI-Programme in C/C++ schreibt? Es wäre jedenfalls wahnsinnig nett, wenn mir jemand verraten könnte, was ich hier falsch gemacht habe oder was ich noch machen muß, damit es funzt.
folgender simpler Quellcode sollte einfach zu einer entsprechenden Anzeige im WebBrowser führen:
[...]
mit dem gcc kompiliert...:
gcc -o webcgi webcgi.c
Da fehlen noch die Warnungen und Optimieren wäre auch nicht schlecht (Darüber streiten sich die Geister. Diese Geister kommen dann aber meist aus der Asssembler Gruft oder der abusing-C Krypta ;-)
Mit den o.a. Flags:
gcc -O2 -W -Wall -pedantic -ansi -o webcgi webcgi.c
... und nach /usr/local/httpd/cgi-bin kopiert:
cp webcgi /usr/local/httpd/cgi-bin
Evt müssen da noch die Rechte zurechtgestutzt werden.
Dann im Webbrowser eingegeben: "http://127.0.0.1/cgi-bin/webcgi"
Leider kam dann nicht das erhoffte "Hallo Welt!", sondern eine Meldung über einen internal Server Error.
Ja, der Apache (welcher überhaupt?) ist mitunter recht maulfaul ;-)
Weiß jemand, was ich da falsch gemacht habe? Oder muß ich am Apache noch was konfigurieren? Oder brauche ich ein bestimmtes Modul dazu?
Nein, normalerweise nichts. Nur das cgi-bin muß eingeschaltet sein (httpd.conf)
Bin für alle Anregungen dankbar, vor allem auch für Webseiten zu diesem Thema.
Da gibt es viel zu viele, als das man da eine Empfehlung aussprechen könnte.
Ein gemütlicher Abend mit Google dürfte da erfolgreich sein.
PS: Ziel ist eine Applikation, die auf ein bereits bestehendes Framework von C++ - Klassen zurückgreift und einen Webbrowser als Oberfläche nutzt, um in einer Applikation die Fähigkeiten lokal und remote anzubieten,
Da würde ich dann doch eher ein "richtiges" Modul empfehlen.
Allerdings ist es im Grunde genommen recht einfach. Statt der normalen Ausgabe ist halt noch der HTTP Header erforderlich, wie Frank schon so trefflich ausführte. Es sollte kein Problem sein, sich ein eigenes webprintf() zu basteln, das das tut.
BTW: als Zeilenende gilt im HTTP "\r\n". Bitte merken. Den meisten Browsern ist das zwar egal, aber im Header ist es wichtig und wird leicht übersehen. (Passiert mir auch oft genug ;-)
wobei lokal ein Linux-Rechner und remote meist ein Windows-Rechner ist.
Das sollte nun gar keine Rolle spielen.
Zumindest auf der Clientseite nicht.
SCNR ;-)
so short
Christoph Zurnieden
--
/*in memoriam*/
#define goto harmfull
Hi Christoph,
Leider kam dann nicht das erhoffte "Hallo Welt!", sondern eine
Meldung über einen internal Server Error.
Ja, der Apache (welcher überhaupt?) ist mitunter recht maulfaul ;-)
die Tatsache, daß der Apache nicht jedem Benutzer, sondern nur dem
Administrator genau sagt, welcher Fehler in _dessen_ Webserver aufge-
treten ist (durch einen Eintrag im error_log) betrachte ich als
security feature, nicht als Mundfaulheit.
Viele Grüße
Michael
Hallo,
Leider kam dann nicht das erhoffte "Hallo Welt!", sondern eine
Meldung über einen internal Server Error.
Ja, der Apache (welcher überhaupt?) ist mitunter recht maulfaul ;-)
die Tatsache, daß der Apache nicht jedem Benutzer, sondern nur dem
Administrator genau sagt, welcher Fehler in _dessen_ Webserver aufge-
treten ist (durch einen Eintrag im error_log) betrachte ich als
security feature, nicht als Mundfaulheit.
Ja, auf den Error-Log hätte ich hinweisen müssen, mein Fehler.
so short
Christoph Zurnieden
--
/*in memoriam*/
#define goto harmfull
Hallo Christoph,
BTW: als Zeilenende gilt im HTTP "\r\n". Bitte merken. Den
meisten Browsern ist das zwar egal, aber im Header ist es
wichtig und wird leicht übersehen. (Passiert mir auch oft
genug ;-)
Nein, es ist *nicht* "\r\n" :) Bedenke bitte, dass "\r\n"
plattformabhaengig (lib-abhaengig?) ist. Der OP schreib von
'meist ein Linux-System', nicht jedoch *immer*. Sinnvoller
waere "\015\012" (vielleicht als ein
#define CRLF "\015\012"
oder so).
Gruesse,
CK
Hallo,
BTW: als Zeilenende gilt im HTTP "\r\n". Bitte merken. Den
meisten Browsern ist das zwar egal, aber im Header ist es
wichtig und wird leicht übersehen. (Passiert mir auch oft
genug ;-)
Nein, es ist *nicht* "\r\n" :) Bedenke bitte, dass "\r\n"
plattformabhaengig (lib-abhaengig?) ist.
Das ist jetzt eine gute Frage. IMHO ist es ISO C, also platformunabhängiger (ja, ich weiß) und internationaler Standard.
5.2.2 Character display semantics
[...]
1 The active position is that location on a display device where the next character output by
the fputc or fputwc function would appear.The intent of writing a printing character
(as defined by the isprint or iswprint function) to a display device is to display a
graphic representation of that character at the active position and then advance the active
position to the next position on the current line. The direction of writing is locale-
specific. If the active position is at the final position of a line (if there is one), the
behavior is unspecified.
2 Alphabetic escape sequences representing nongraphic characters in the execution
character set are intended to produce actions on display devices as follows:
\a (alert)Produces an audible or visible alert. The active position shall not be changed.
\b (backspace)Movesthe active position to the previous position on the current line. If
the active position is at the initial position of a line, the behavior is unspecified.
\f ( form feed)Movesthe active position to the initial position at the start of the next
logical page.
\n (newline)Movesthe active position to the initial position of the next line.
\r (carriage return)Movesthe active position to the initial position of the current line.
\t (horizontal tab)Movesthe active position to the next horizontal tabulation position
on the current line. If the active position is at or past the last defined horizontal
tabulation position, the behavior is unspecified.
\v (vertical tab)Movesthe active position to the initial position of the next vertical
tabulation position. If the active position is at or past the last defined vertical
tabulation position, the behavior is unspecified.
3 Each of these escape sequences shall produce a unique implementation-defined value
which can be stored in a single char object. The external representations in a text file
need not be identical to the internal representations, and are outside the scope of this
International Standard.
Mmh... doch nicht?
RFC 2616
CR = <US-ASCII CR, carriage return (13)>
LF = <US-ASCII LF, linefeed (10)>
SP = <US-ASCII SP, space (32)>
HT = <US-ASCII HT, horizontal-tab (9)>
<"> = <US-ASCII double-quote mark (34)>
HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
protocol elements except the entity-body (see appendix 19.3 for
tolerant applications). The end-of-line marker within an entity-body
is defined by its associated media type, as described in section 3.7.
CRLF = CR LF
Aha, dann nicht.
Warum mußt Du auch immer Recht haben, ha? ;-)))
Der OP schreib von
'meist ein Linux-System', nicht jedoch *immer*. Sinnvoller
waere "\015\012" (vielleicht als ein
#define CRLF "\015\012"
oder so).
Also irgendwie kommt der mir bekannt vor, woher nur? ;-)
BTW: was ist eigentlich aus der gzip.c Version geworden? (Habe den Direktlink verschlampt und bin jetzt zu faul, mich da wieder durchzuwühlen)
Außerdem wollte ich aus dem Original ein PE-Datei bauen. Deshalb warte ich ja auch auf Deine neue Version.
so short
Christoph Zurnieden
--
/*in memoriam*/
#define goto harmfull
Hallo,
Das ist jetzt eine gute Frage. IMHO ist es ISO C, also
platformunabhängiger (ja, ich weiß) und internationaler
Standard.
Die Escape-Sequenzen. Ja. Aber nicht der Wert, den sie
letztenendes verkoerpern.
[...]
3 Each of these escape sequences shall produce a unique
implementation-defined value which can be stored in a
single char object. The external representations in a text
file need not be identical to the internal
representations, and are outside the scope of this
International Standard.
Da hast du es doch. Unter Windows nimmt '\n' ausserhalb einer
Programmumgebung 2 Bytes ein, fuer C ist es als ein Byte
definiert :) Sonst haette man ja diese bloeden ^M in
Windows-Textdateien auf Unix-Systemen auch nicht :) Die libc
wandelt (sofern die Datei im ASCII-Modus geoeffnet wurde)
die Zeilenenden beim einlesen um in die entsprechende interne
Repraesentation. Unter UNIX ist das kein Problem, da ist meist
\n == \n. Unter Windows ist das schon mehr Arbeit :) Und
aufm Mac ist es ganz verrueckt, da ist \n extern == \r :)
BTW: was ist eigentlich aus der gzip.c Version geworden?
Jaaaa... ich weiss. Ich muesste dringend deine und meine
Aenderungen zusammenbringen. Aber ich arbeite zur Zeit ca.
10 bis 12h am Tag, weil sich da jemand in der Zeitplanung
verrechnet hat *grummelgrummel*
Gruesse,
CK
Hallo,
Das ist jetzt eine gute Frage. IMHO ist es ISO C, also
platformunabhängiger (ja, ich weiß) und internationaler
Standard.
Die Escape-Sequenzen. Ja. Aber nicht der Wert, den sie
letztenendes verkoerpern.
Hatte ich nicht schon zugegeben, daß Du Recht hast und ich Unrecht? ;-)
[...]
3 Each of these escape sequences shall produce a unique
implementation-defined value which can be stored in a
single char object. The external representations in a text
file need not be identical to the internal
representations, and are outside the scope of this
International Standard.
Da hast du es doch. Unter Windows nimmt '\n' ausserhalb einer
Programmumgebung 2 Bytes ein, fuer C ist es als ein Byte
definiert :) Sonst haette man ja diese bloeden ^M in
Windows-Textdateien auf Unix-Systemen auch nicht :)
Läßt sich abstellen, 'man less' ;-)
Die libc
wandelt (sofern die Datei im ASCII-Modus geoeffnet wurde)
die Zeilenenden beim einlesen um in die entsprechende interne
Repraesentation. Unter UNIX ist das kein Problem, da ist meist
\n == \n. Unter Windows ist das schon mehr Arbeit :) Und
aufm Mac ist es ganz verrueckt, da ist \n extern == \r :)
Aha, da war ich wohl zu voreilig mit meiner Rechtverteilung.
Unter Windows ist '\n' auch nur ein Byte, nur das Zeilenende wird dort mit zwei Bytes gesetzt. Ein printf("\n") erzeugt auch unter Windows (mit GCC bzw LCCWin32 als C Compiler mit deren jeweiligen Libcs) nur ein 0x0d, kein 0x0a0d.
(Das war jetzt nicht nett von Dir, mich zu zwingen heute nochmal Windows zu starten! ;-)
Auf dem Mac ist es das Gleiche, da sind die Zeilenenden mit 0x0a markiert und ein printf("\n") ergibt trotzdem ein 0x0d. (Wobei ich mich frage, ob sich das jetzt geändert hat, da nun ein BSD unten drunter läuft)
Letzteres allerdings ohne Gewähr, ich habe schon zu lange auf keinem Mac mehr etwas gebaut.
BTW: was ist eigentlich aus der gzip.c Version geworden?
Jaaaa... ich weiss. Ich muesste dringend deine und meine
Aenderungen zusammenbringen. Aber ich arbeite zur Zeit ca.
10 bis 12h am Tag, weil sich da jemand in der Zeitplanung
verrechnet hat *grummelgrummel*
Ja, bei dem Wort "Deadline" habe ich auch immer einen Strick mit Schlinge vor dem geistigem Auge ;-)
(Ja, ist ja schon gut, 2 EUR in die Wortwitzkasse)
so short
Christoph Zurnieden, der nun seinen Blick gegen die Perseiden richtet, wenn er denn rausgefunden hat, wo die Dinger liegen
Hallo Christoph,
Hatte ich nicht schon zugegeben, daß Du Recht hast und ich Unrecht? ;-)
Ja. Aber du bist ja nicht der einzige, der mitliest. Ich wollte es nur noch mal
etwas naeher erklaeren.
Läßt sich abstellen, 'man less' ;-)
Ja, ich weiss :)
Die libc
wandelt (sofern die Datei im ASCII-Modus geoeffnet wurde)
die Zeilenenden beim einlesen um in die entsprechende interne
Repraesentation. Unter UNIX ist das kein Problem, da ist meist
\n == \n. Unter Windows ist das schon mehr Arbeit :) Und
aufm Mac ist es ganz verrueckt, da ist \n extern == \r :)
Aha, da war ich wohl zu voreilig mit meiner Rechtverteilung.
Unter Windows ist '\n' auch nur ein Byte, nur das Zeilenende wird dort mit
zwei Bytes gesetzt.
Das ist doch das, was ich gesagt habe :) '\n' ist das Zeilenende. Schreibt man
es in eine Datei, hat die Datei 2 Byte Inhalt.
Auf dem Mac ist es das Gleiche, da sind die Zeilenenden mit 0x0a markiert
und ein printf("\n") ergibt trotzdem ein 0x0d.
Seit MacOS 10, ja :)
(Wobei ich mich frage, ob sich das jetzt geändert hat, da nun ein BSD unten
drunter läuft)
Richtig.
Gruesse,
CK
Hallo,
Die libc
wandelt (sofern die Datei im ASCII-Modus geoeffnet wurde)
die Zeilenenden beim einlesen um in die entsprechende interne
Repraesentation. Unter UNIX ist das kein Problem, da ist meist
\n == \n. Unter Windows ist das schon mehr Arbeit :) Und
aufm Mac ist es ganz verrueckt, da ist \n extern == \r :)
Aha, da war ich wohl zu voreilig mit meiner Rechtverteilung.
Unter Windows ist '\n' auch nur ein Byte, nur das Zeilenende wird dort mit
zwei Bytes gesetzt.
Das ist doch das, was ich gesagt habe :) '\n' ist das Zeilenende. Schreibt man
es in eine Datei, hat die Datei 2 Byte Inhalt.
Dann arbeitest Du mit anderen LibCs. Ich habe es hier auf Win98 ausprobiert mit GCC (Cygwin Port) und LCCWin32 und deren LibCs. Beide schmissen nur ein Byte raus und beide Male auch 0x0d.
Benutzt Du etwa diesen "Visual Crap"? ;-)
Aber nach Standard wäre es (2 Byte zu setzen) eigentlich sogar korrekt, obwohl ich die Angaben etwas wiedersprüchlich finde:
\n (newline)Moves the active position to the initial position of the next line.
\r (carriage return)Moves the active position to the initial position of the current line.
Auch gibt es dann Schwierigkeiten mit Intergercast Konstrukten, wie '\n', das normalerweise genauso groß wie z.B. '\t' sein muß. Beim Schreiben noch kein Problem, aber beim Lesen.
Aber Windows war ja schon immer etwas merkwürdig ;-)
(Die uralte Schreibmschinentechnik für Computer zu benutzen ist ja doch etwas ... äh ..., nun ... ;-)
(Wobei ich mich frage, ob sich das jetzt geändert hat, da nun ein BSD unten
drunter läuft)
Richtig.
Gab/gibt das keine Schwierigkeiten mit (dem Auswurf von) alten Programmen? Oder greift da die Simulation des alten MacOS?
so short
Christoph Zurnieden
PS:
Die Perseiden habe ich gefunden, zu sehen war aber nix. Und dafür stehe ich mitten in der Nacht auf! ;-)
CZ