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