Minor cleanup (more needed).
[catagits/fcgi2.git] / doc / fcgi-tcl.htm
CommitLineData
0198fd3c 1<html>
2<head><title>Integrating FastCGI with Tcl</title>
3</head>
4
5<body bgcolor="#FFFFFF" text="#000000" link="#cc0000" alink="#000011"
6vlink="#555555">
7
8<center>
6791223e 9<a href="http://fastcgi.com">
0198fd3c 10 <img border=0 src="../images/fcgi-hd.gif" alt="[[FastCGI]]"></a>
11</center>
12<br clear=all>
13<h3><center>Integrating FastCGI with Tcl</center></h3>
14
15<!--Copyright (c) 1996 Open Market, Inc. -->
16<!--See the file "LICENSE.TERMS" for information on usage and redistribution-->
17<!--of this file, and for a DISCLAIMER OF ALL WARRANTIES. -->
18
19<P ALIGN=CENTER>
20Michael S. Shanzer
21<BR>
22Open Market, Inc.
23<BR>
24<EM>19 January 1995</EM>
25</P>
26
27<h5 align=center>
28Copyright &copy; 1996 Open Market, Inc. 245 First Street, Cambridge,
29 MA 02142 U.S.A.<br>
30Tel: 617-621-9500 Fax: 617-621-1703 URL:
31 <a href="http://www.openmarket.com/">http://www.openmarket.com/</a><br>
6791223e 32$Id: fcgi-tcl.htm,v 1.2 2001/05/14 13:00:30 robs Exp $ <br>
0198fd3c 33</h5>
34<hr>
35
36
37<h3><a NAME = "S1">1. Introduction</a></h3>
38
39
40Tcl (tool command language) is an embeddable scripting language
41that's often used for CGI programming. Tcl is freely available
42as a source kit.<p>
43
44We've built a Tcl interpreter that runs as a FastCGI application. Our
45purpose in doing so was twofold:
46
47<ul>
48 <li><i>Create a useful artifact.</i>
49 Open Market has written many CGI applications using Tcl.
50 Now we'd like to turn them into FastCGI applications.<p>
51 <li><i>Demonstrate how easy it is to integrate FastCGI with an
52 existing program.</i>
53 The Tcl interpreter is a substantial program, so integrating
54 FastCGI with the Tcl interpreter is a good test of the
55 <tt>fcgi_stdio</tt> compatability library.
56</ul>
57
58We've succeeded on both counts. We now have a platform for
59migrating our Tcl-based CGI applications to FastCGI. And
60the integration required a very small effort. The only source
61code change to the Tcl interpreter was the routine addition of a
62handful of new commands: <tt>FCGI_Accept</tt>, <tt>FCGI_Finish</tt>,
63<tt>FCGI_SetExitStatus</tt>, and <tt>FCGI_StartFilterData</tt>.<p>
64
65The FastCGI-integrated Tcl interpreter works as usual when run
66from a shell or as a CGI program. You don't need two Tcls,
67one for FastCGI and one for other uses.<p>
68
69The remainder of this document gives a recipe you can follow to
70build FastCGI into Tcl, explains what's happening in the recipe,
71and illustrates the use of FastCGI Tcl with
72an example program.<p>
73
74<h3><a NAME = "S2">2. Recipe</a></h3>
75
76Here are the assumptions embedded in the following recipe:
77<ul>
78 <li>You are building Tcl 7.4p3, the current stable Tcl release
79 as this is written.
80 You unpack the Tcl kit into a directory <tt>tcl7.4</tt>
81 that's a sibling of the FastCGI kit directory
82 <tt>fcgi-devel-kit</tt>.<p>
83
84 <li>You have gcc version 2.7
85 installed on your system, and use it in the build.
86 gcc is convenient because it supports the <tt>-include</tt>
87 command-line option
88 that instructs the C preprocessor to include a specific file before
89 processing any other include files. This allows you to include
90 <tt>fcgi_stdio.h</tt> without modifying Tcl source files. (The
91 reason for specifying gcc version 2.7 is that I have
92 experienced bad behavior with an earlier version and the <tt>-include</tt>
93 flag -- the C preprocessor died with SIGABRT.)<p>
94
95 <li>You have GNU autoconf
96 installed on your system. If you don't have GNU autoconf,
97 you will have to make certain edits by hand and
98 repeat these edits for each build platform.<p>
99</ul>
100
101If those are valid assumptions, follow these steps:
102<ol>
103 <li><i>Build the FastCGI Developer's Kit.</i>
104 Tcl needs to link against <tt>libfcgi.a</tt>, so
6791223e 105 <a href="fcgi-devel-kit.htm#S2">build
0198fd3c 106 the FastCGI Developer's Kit</a>
107 in order to create this library for your platform.<p>
108
109 <li><i>Pull the Tcl 7.4p3 kit.</i>
110 You'll need the files
111 <a href="ftp://ftp.smli.com/pub/tcl/tcl7.4.tar.Z">tcl7.4.tar.Z</a>,
112 <a href="ftp://ftp.smli.com/pub/tcl/tcl7.4p1.patch.gz">tcl7.4p1.patch.gz</a>,
113 <a href="ftp://ftp.smli.com/pub/tcl/tcl7.4p2.patch.gz">tcl7.4p2.patch.gz</a>,
114 and
115 <a href="ftp://ftp.smli.com/pub/tcl/tcl7.4p3.patch.gz">tcl7.4p3.patch.gz</a>.
116 (Some older Netscape browsers can't perform these
117 retrievals because of a protocol conflict between Netscape
118 and Sun's firewall.)<p>
119
120 Unpack the tar file in the parent directory of the
121 FastCGI kit directory you used in the previous step,
122 so that the directories <tt>tcl7.4</tt> and <tt>fcgi-devel-kit</tt>
123 are siblings. After unpacking the tar file, follow the directions
124 in the <tt>README</tt> to apply the patches.<p>
125
126 The <a href="http://www.sunlabs.com:80/research/tcl/">Sun Labs Tcl/Tk
127 Project Page</a> contains a wealth of information on Tcl, including
128 up to date information on the latest kits.<p>
129
130 <li><i>Copy the files <tt>tclFCGI.c</tt>, <tt>tclAppInit.c</tt>,
131 <tt>Makefile.in</tt>, and <tt>configure.in</tt> from the FastCGI kit.</i>
132 <pre>
133 > cd tcl7.4
134 > mv tclAppInit.c tclAppInit.c.orig
135 > mv Makefile.in.orig Makefile.in.orig.orig
136 > mv Makefile.in Makefile.in.orig
137 > mv configure.in configure.in.orig
138 > cp ../fcgi-devel-kit/tcl/tcl7.4/* .
139 > cp ../fcgi-devel-kit/tcl/common/* .</pre>
140
141 <li><i>Create a new <tt>configure</tt> script.</i>
142 <pre>
143 > autoconf</pre>
144
145 <li><i>Configure and build.</i>
146 <pre>
147 > ./configure
148 > make</pre>
149 The <tt>make</tt> creates the Tcl interpreter <tt>tclsh</tt>
150 and library archive <tt>libtcl.a</tt> (for embedding Tcl in
151 your own C applications). The Tcl <tt>README</tt> file
152 explains how you can experiment with <tt>tclsh</tt>
153 without installing it in a standard place.<p>
154</ol>
155
156<h3><a NAME = "S3">3. Recipe Explained</a></h3>
157
158The recipe alone is fine if you are using Tcl 7.4p3, you have gcc
159version 2.7, and you have GNU autoconf. In case one or more of these
160assumptions doesn't hold for you, and to illuminate how little work was
161involved in integrating FastCGI, here's an explanation of how
162and why you would modify the files <tt>tclAppInit.c</tt>,
163<tt>Makefile.in</tt>, and <tt>configure.in</tt> from the Tcl kit.
164
165<ul>
166 <li><tt>tclAppInit.c</tt>:<p>
167 <ul>
168 <li>Add the following three lines of code
169 to the function <tt>Tcl_AppInit</tt> after the call
170 to <tt>Tcl_Init</tt> and after the comment about calling init
171 procedures:
172 <pre>
173 if (FCGI_Init(interp) == TCL_ERROR) {
174 return TCL_ERROR;
175 }</pre>
176 This registers four Tcl commands (<tt>FCGI_Accept</tt>,
177 <tt>FCGI_Finish</tt>, <tt>FCGI_SetExitStatus</tt>, and
178 <tt>FCGI_StartFilterData</tt>), implemented in
179 <tt>tclFCGI.c</tt>, with the Tcl interpreter.<p>
180 </ul>
181
182 <li><tt>Makefile.in</tt>:<p>
183 <ul>
184 <li>Add <tt>tclFCGI.o</tt> to the <tt>GENERIC_OBJS</tt> variable, and
185 add <tt>tclFCGI.c</tt> to the <tt>SRCS</tt> variable.<p>
186
187 This builds the FastCGI Tcl commands and
188 links them into the Tcl interpreter.<p>
189
190 <li>Add <tt>-I../fcgi-devel-kit/include
191 -include ../fcgi-devel-kit/include/fcgi_stdio.h</tt>
192 to the <tt>CFLAGS</tt> variable.<p>
193
194 This includes <tt>fcgi_stdio.h</tt>
195 when compiling C code for the Tcl interpreter, overriding
196 the normal <tt>stdio</tt> types, variables, and functions.<p>
197
198 <li>Add <tt>../fcgi-devel-kit/libfcgi/libfcgi.a</tt> before the
199 <tt>@LIBS@</tt> part of the <tt>LIBS</tt> variable.<p>
200
201 This links the implementation of <tt>fcgi_stdio.h</tt>
202 into the Tcl interpreter, for use by the <tt>FCGI_accept</tt>
203 command and any code that uses <tt>stdio</tt> variables
204 or calls <tt>stdio</tt> functions.<p>
205 </ul><p>
206
207 The last two edits will vary if you use a compiler other than gcc or
208 install the <tt>tcl7.4</tt> directory
209 somewhere else in relation to the <tt>fcgi-devel-kit</tt> directory.<p>
210
211 <li><tt>configure.in</tt>:<p>
212 <ul>
213 <li>
214 Replace the lines
215 <pre>
216AC_C_CROSS
217CC=${CC-cc}</pre>
218 with the lines
219 <pre>
220AC_PROG_CC
221AC_C_CROSS</pre>
222 This selects gcc in preference to other C compilers.<p>
223
224 <li>
225 Add the following lines just after the
226 <tt>AC_SUBST(CC)</tt> line:
227 <pre>
228AC_CHECK_LIB(socket, main, [LIBS="$LIBS -lsocket"])
229AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"])
230AC_SUBST(LIBS)</pre>
231 This ensures that the socket libraries used by FastCGI
232 are linked into the Tcl interpreter.<p>
233 </ul>
234 If GNU autoconf is not available to you, you'll leave
235 <tt>configure.in</tt> alone and perform the following steps:<p>
236 <ul>
237 <li>
238 Execute
239 <pre>
240 > SETENV CC gcc</pre>
241 before running <tt>configure</tt>.<p>
242
243 <li>
244 If you are running on a SVR4-derived Unix platform,
245 edit <tt>Makefile</tt> to add
246 <tt>-lsocket -lnsl</tt> to the <tt>LIBS</tt> value
247 after running <tt>configure</tt>.<p>
248 </ul>
249 If you ever re-run <tt>configure</tt>, you'll need to repeat
250 these steps.<p>
251
252</ul>
253
254
255<h3><a NAME = "S4">4. Writing FastCGI applications in Tcl</a></h3>
256
6791223e 257The Tcl program <tt>tcl/tiny-tcl-fcgi</tt> performs the same function as the C
258program <tt>examples/tiny-fcgi.c</tt> that's used as an example in the <a href="fcgi-devel-kit.htm#S3.1.1">FastCGI
259Developer's Kit document</a>. Here's what the Tcl version looks like:
260<p>
0198fd3c 261
262<pre>
263#!./tclsh
264set count 0
265while {[FCGI_Accept] &gt;= 0 } {
266 incr count
267 puts -nonewline "Content-type: text/html\r\n\r\n"
268 puts "&lt;title&gt;FastCGI Hello! (Tcl)&lt;/title&gt;"
269 puts "&lt;h1&gt;FastCGI Hello! (Tcl)&lt;/h1&gt;"
270 puts "Request number $count running on host &lt;i&gt;$env(SERVER_NAME)&lt;/i&gt;"
271}
272</pre>
273
274If you've built Tcl according to the recipe and you have a Web server
275set up to run FastCGI applications, load the FastCGI Developer's Kit
276Index Page in that server and run this Tcl application now.<p>
277
278The script invokes Tcl indirectly via the symbolic link
279<tt>examples/tclsh</tt>. It does this because HP-UX has a limit of 32
280characters for the first line of a command-interpreter file such as
281<tt>examples/tiny-tcl-fcgi</tt>. If you run on HP-UX you won't want
282to sprinkle symbolic links to <tt>tclsh</tt> everywhere, so you should install
283<tt>tclsh</tt> with a shorter pathname than
284<tt>/usr/local/tcl7.4-fcgi/bin/tclsh7.4</tt>.<p>
285
286The Tcl command <tt>FCGI_Accept</tt> treats the initial
287environment differently than the C function <tt>FCGI_Accept</tt>. The
288first call to the
289C function <tt>FCGI_Accept</tt> replaces the initial environment with
290the environment of the first request. The first call to the Tcl command
291<tt>FCGI_Accept</tt> adds the variable bindings of the first request
292to the bindings present in the initial environment. So when the first
293call to <tt>FCGI_Accept</tt> returns, bindings from the initial
294environment are still there (unless, due to naming conflicts, some of
295them have been overwritten by the first request). The next call to
296<tt>FCGI_Accept</tt> removes the bindings made on the previous call
297before adding a new set for the request just accepted, again preserving
298the initial environment.<p>
299
300The FastCGI-integrated <tt>tclsh</tt> also includes
301commands <tt>FCGI_Finish</tt>, <tt>FCGI_SetExitStatus</tt>,
302and <tt>FCGI_StartFilterData</tt> that correspond to
303C functions in <tt>fcgi_stdio.h</tt>; see the manpages for
304full information.<p>
305
306Converting a Tcl CGI application to FastCGI is not fundamentally
307different from converting a C CGI application. You separate
308the portion of the application that performs one-time
309initialization from the portion that performs per-request
310processing. You put the per-request processing into a loop
311controlled by <tt>FCGI_Accept</tt>.<p>
312
313<HR>
314<ADDRESS><A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A></ADDRESS>
315</body>
316</html>