pickup unistd.h and environ
[catagits/fcgi2.git] / examples / echo-cpp.cpp
1 /*\r
2  *  A simple FastCGI application example in C++.\r
3  *  \r
4  *  $Id: echo-cpp.cpp,v 1.2 2001/11/21 15:31:49 robs Exp $\r
5  *  \r
6  *  Copyright (c) 2001  Rob Saccoccio and Chelsea Networks\r
7  *  All rights reserved.\r
8  *  \r
9  *  Redistribution and use in source and binary forms, with or without\r
10  *  modification, are permitted provided that the following conditions\r
11  *  are met:\r
12  *  \r
13  *  1. Redistributions of source code must retain the above copyright\r
14  *     notice, this list of conditions and the following disclaimer.\r
15  *  2. Redistributions in binary form must reproduce the above copyright\r
16  *     notice, this list of conditions and the following disclaimer in the\r
17  *     documentation and/or other materials provided with the distribution.\r
18  *  3. The name of the author may not be used to endorse or promote products\r
19  *     derived from this software without specific prior written permission.\r
20  *  \r
21  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
22  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
23  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
24  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
25  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
26  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
30  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  */\r
32 \r
33 #include <stdlib.h>\r
34 #ifdef _WIN32\r
35 #include <process.h>\r
36 #else\r
37 #include <unistd.h>\r
38 extern const char * const * environ;\r
39 #endif\r
40 #include "fcgio.h"\r
41 \r
42 // Maximum number of bytes allowed to be read from stdin\r
43 static const unsigned long STDIN_MAX = 1000000;\r
44 \r
45 static void penv(const char * const * envp)\r
46 {\r
47     cout << "<PRE>\n";\r
48     for ( ; *envp; ++envp) \r
49     {\r
50         cout << *envp << "\n";\r
51     }\r
52     cout << "</PRE>\n";\r
53 }\r
54 \r
55 static long gstdin(FCGX_Request * request, char ** content)\r
56 {\r
57     char * clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);\r
58     unsigned long clen = STDIN_MAX;\r
59 \r
60     if (clenstr)\r
61     {\r
62         clen = strtol(clenstr, &clenstr, 10);\r
63         if (*clenstr)\r
64         {\r
65             cerr << "can't parse \"CONTENT_LENGTH=" \r
66                  << FCGX_GetParam("CONTENT_LENGTH", request->envp) \r
67                  << "\"\n";\r
68             clen = STDIN_MAX;\r
69         }\r
70     }\r
71 \r
72     // Note that *you* should not read stdin when CONTENT_LENGTH\r
73     // is missing or unparsable (this is a demo/test program).\r
74 \r
75     // *always* put a cap on the amount of data that will be read\r
76     if (clen > STDIN_MAX) clen = STDIN_MAX;\r
77 \r
78     *content = new char[clen];\r
79 \r
80     cin.read(*content, clen);\r
81     clen = cin.gcount();\r
82 \r
83     // chew up any remaining stdin - this shouldn't be necessary\r
84     // but it is because mod_fastcgi doesn't handle it correctly\r
85     do cin.ignore(1024); while (! cin.eof());\r
86 \r
87     return clen;\r
88 }\r
89 \r
90 int main (void)\r
91 {\r
92     int count = 0;\r
93     long pid = getpid();\r
94 \r
95     FCGX_Request request;\r
96 \r
97     FCGX_Init();\r
98     FCGX_InitRequest(&request, 0, 0);\r
99 \r
100     while (FCGX_Accept_r(&request) == 0) \r
101     {\r
102         fcgi_streambuf fin(request.in);\r
103         fcgi_streambuf fout(request.out);\r
104         fcgi_streambuf ferr(request.err);\r
105         \r
106 #ifdef _WIN32\r
107         cin = &fin;\r
108         cout = &fout;\r
109         cerr = &ferr;\r
110 #else\r
111         cin.rdbuf(&fin);\r
112         cout.rdbuf(&fout);\r
113         cerr.rdbuf(&ferr);\r
114 #endif\r
115 \r
116         // Although FastCGI supports writing before reading,\r
117         // many http clients (browsers) don't support it (so  \r
118         // the connection deadlocks until a timeout expires!).\r
119         char * content;\r
120         unsigned long clen = gstdin(&request, &content);\r
121 \r
122         cout << "Content-type: text/html\r\n"\r
123                 "\r\n"\r
124                 "<TITLE>echo-cpp</TITLE>\n"\r
125                 "<H1>echo-cpp</H1>\n"\r
126                 "<H4>PID: " << pid << "</H4>\n"\r
127                 "<H4>Request Number: " << ++count << "</H4>\n";\r
128 \r
129         cout << "<H4>Request Environment</H4>\n";\r
130         penv(request.envp);\r
131 \r
132         cout << "<H4>Process/Initial Environment</H4>\n";\r
133         penv(environ);\r
134 \r
135         cout << "<H4>Standard Input - " << clen;\r
136         if (clen == STDIN_MAX) cout << " (STDIN_MAX)";\r
137         cout << " bytes</H4>\n";\r
138         if (clen) cout.write(content, clen);\r
139 \r
140         if (content) delete []content;\r
141     }\r
142 \r
143     return 0;\r
144 }\r