Commit | Line | Data |
c2a77fd4 |
1 | /*\r |
2 | * A simple FastCGI application example in C++.\r |
3 | * \r |
4c0f03cc |
4 | * $Id: echo-cpp.cpp,v 1.2 2001/11/21 15:31:49 robs Exp $\r |
c2a77fd4 |
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 |
4c0f03cc |
36 | #else\r |
37 | #include <unistd.h>\r |
38 | extern const char * const * environ;\r |
c2a77fd4 |
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 |