Listing 2: A CGI program that sends email
/* formtest.cgi.c */
char *Name = NULL;
char *Prod = NULL;
char *Rush = NULL;
/*------------------------------------------*
* CGI program processes orders from the *
* Web form page. *
*------------------------------------------*/
int main() {
checkInputHdr();
getNameValuePairs();
if (sendReply() && Rush != NULL)
sendMail();
return 0;
}
/*------------------------------------------*
* This step is just a formality, since the *
* server will always get this stuff right. *
* I guess someone might try to use this *
* program for something else (?) in which *
* case it will bomb. *
*------------------------------------------*/
void checkInputHdr (void) {
/* This function checks for a *
* REQUEST_METHOD of "post" and the *
* correct CONTENT_TYPE. */
}
/*------------------------------------------*
* Read the NAME/VALUE pairs from the form *
* and put them into into a linked list for *
* later. *
*------------------------------------------*/
void getNameValuePairs (void) {
/* As suggested, this function gets *
* name/value pairs as global variables *
* and also saves them in a log file. The *
* real program calls a few other *
* functions that I have also omitted *
* here. */
}
/*------------------------------------------*
* Send the top part of the reply page, *
* then check a few things and issue either *
* a message or an acknowledgement, then *
* send the rest of the page. *
*------------------------------------------*/
int sendReply (void) {
int ok = TRUE; /* error code */
/* send top part of page */
printf ("Content-type: text/html\n\n");
printf ("<html> <head> <title>\n");
printf ("CGI send mail test\n");
printf ("</title> </head>\n");
printf ("<body> <center>\n");
/* do a simple validation */
if (Name == NULL) {
printf ("<h1> Name required </h1>");
ok = FALSE;
}
/* send appropriate message */
if (ok) {
printf ("<h1> Thanks for \n");
printf ("your order </h1>\n");
} else {
printf ("<h1> Resubmit form </h1>");
}
/* send the message trailer */
printf ("</center>\n");
printf ("</body>\n");
printf ("</html>\n");
return ok;
}
/*------------------------------------------*
* Flush standard output, so user sees all *
* HTML. Create pipe then fork child to *
* exec sendmail. Parent writes to pipe as *
* stdout and child reads from pipe as *
* stdin. *
*------------------------------------------*/
void sendMail (void) {
int pfd [2];
if (fflush (stdout) == EOF)
err ("Can't flush stdout");
if (pipe (pfd) == -1)
err ("Can't open pipe");
switch (fork()) {
case 0:
child (pfd);
break;
default:
parent (pfd);
break;
}
}
/*------------------------------------------*
* Child process closes writing end of *
* pipe, closes stdin and dup's reading end *
* of pipe, so it becomes child's stdin. It *
* then closes reading end of pipe and *
* exec's sendmail, which ends up reading *
* from pipe (which by now is connected to *
* parent's stdout. *
*------------------------------------------*/
void child (int *pfd) {
if (close (pfd [1]) == -1)
err ("Child can't close pfd [1]");
if (close (0) == -1)
err ("Child can't close stdin");
if (dup (pfd [0]) != 0)
err ("Child can't dup stdin");
if (close (pfd [0]) == -1)
err ("Child can't close pfd [0]");
execl (MAIL, MAILTO, (char *)0);
err ("exec failed");
}
/*------------------------------------------*
* Parent closes reading end of pipe, *
* closes its stdout and dup's writing *
* end of the pipe, so it becomes stdout. *
* After closing the writing end of pipe it *
* sends mail text to stdout. *
*------------------------------------------*/
void parent (int *pfd) {
/* make the pipe into stdout */
if (close (pfd [0]) == -1)
err ("Parent can't close pfd [0]");
if (close (1) == -1)
err ("Parent can't close stdout");
if (dup (pfd [1]) != 1)
err ("Parent can't dup stdout");
if (close (pfd [1]) == -1)
err ("Parent can't close pfd [1]");
/* send the message */
printf ("To: Expediter\n");
printf ("From: Web_Server\n");
printf ("Subject: Rush Order\n");
printf ("\n");
printf ("Process the following "
"order immediately:\n\n");
printf ("Name: %s\n", Name);
printf ("Product: %s\n", Prod);
printf ("\n");
}
/* End of File */