1 Integrating FastCGI with Tcl
5 <center>Integrating FastCGI with Tcl</center>
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. -->
16 <EM>19 January 1995</EM>
20 Copyright © 1996 Open Market, Inc. 245 First Street, Cambridge,
22 Tel: 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>
29 <h3><a NAME = "S1">1. Introduction</a></h3>
32 Tcl (tool command language) is an embeddable scripting language
33 that's often used for CGI programming. Tcl is freely available
36 We've built a Tcl interpreter that runs as a FastCGI application. Our
37 purpose in doing so was twofold:
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
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.
50 We've succeeded on both counts. We now have a platform for
51 migrating our Tcl-based CGI applications to FastCGI. And
52 the integration required a very small effort. The only source
53 code change to the Tcl interpreter was the routine addition of a
54 handful of new commands: <tt>FCGI_Accept</tt>, <tt>FCGI_Finish</tt>,
55 <tt>FCGI_SetExitStatus</tt>, and <tt>FCGI_StartFilterData</tt>.<p>
57 The FastCGI-integrated Tcl interpreter works as usual when run
58 from a shell or as a CGI program. You don't need two Tcls,
59 one for FastCGI and one for other uses.<p>
61 The remainder of this document gives a recipe you can follow to
62 build FastCGI into Tcl, explains what's happening in the recipe,
63 and illustrates the use of FastCGI Tcl with
64 an example program.<p>
66 <h3><a NAME = "S2">2. Recipe</a></h3>
68 Here are the assumptions embedded in the following recipe:
70 <li>You are building Tcl 7.4p3, the current stable Tcl release
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>
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>
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>
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>
93 If those are valid assumptions, follow these steps:
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>
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>,
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>
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>
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>
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>
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>
133 <li><i>Create a new <tt>configure</tt> script.</i>
137 <li><i>Configure and build.</i>
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>
148 <h3><a NAME = "S3">3. Recipe Explained</a></h3>
150 The recipe alone is fine if you are using Tcl 7.4p3, you have gcc
151 version 2.7, and you have GNU autoconf. In case one or more of these
152 assumptions doesn't hold for you, and to illuminate how little work was
153 involved in integrating FastCGI, here's an explanation of how
154 and why you would modify the files <tt>tclAppInit.c</tt>,
155 <tt>Makefile.in</tt>, and <tt>configure.in</tt> from the Tcl kit.
158 <li><tt>tclAppInit.c</tt>:<p>
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
165 if (FCGI_Init(interp) == TCL_ERROR) {
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>
174 <li><tt>Makefile.in</tt>:<p>
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>
179 This builds the FastCGI Tcl commands and
180 links them into the Tcl interpreter.<p>
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>
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>
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>
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>
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>
203 <li><tt>configure.in</tt>:<p>
214 This selects gcc in preference to other C compilers.<p>
217 Add the following lines just after the
218 <tt>AC_SUBST(CC)</tt> line:
220 AC_CHECK_LIB(socket, main, [LIBS="$LIBS -lsocket"])
221 AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"])
223 This ensures that the socket libraries used by FastCGI
224 are linked into the Tcl interpreter.<p>
226 If GNU autoconf is not available to you, you'll leave
227 <tt>configure.in</tt> alone and perform the following steps:<p>
232 > SETENV CC gcc</pre>
233 before running <tt>configure</tt>.<p>
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>
241 If you ever re-run <tt>configure</tt>, you'll need to repeat
247 <h3><a NAME = "S4">4. Writing FastCGI applications in Tcl</a></h3>
249 The Tcl program <tt>tcl/tiny-tcl-fcgi</tt> performs the same
250 function as the C program <tt>examples/tiny-fcgi.c</tt>
251 that's used as an example in the
252 <a href="fcgi-devel-kit.html#S3.1.1">FastCGI Developer's Kit
253 document</a>. Here's what the Tcl version looks like:<p>
258 while {[FCGI_Accept] >= 0 } {
260 puts -nonewline "Content-type: text/html\r\n\r\n"
261 puts "<title>FastCGI Hello! (Tcl)</title>"
262 puts "<h1>FastCGI Hello! (Tcl)</h1>"
263 puts "Request number $count running on host <i>$env(SERVER_NAME)</i>"
267 If you've built Tcl according to the recipe and you have a Web server
268 set up to run FastCGI applications, load the FastCGI Developer's Kit
269 Index Page in that server and run this Tcl application now.<p>
271 The script invokes Tcl indirectly via the symbolic link
272 <tt>examples/tclsh</tt>. It does this because HP-UX has a limit of 32
273 characters 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
275 to 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>
279 The Tcl command <tt>FCGI_Accept</tt> treats the initial
280 environment differently than the C function <tt>FCGI_Accept</tt>. The
282 C function <tt>FCGI_Accept</tt> replaces the initial environment with
283 the 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
285 to the bindings present in the initial environment. So when the first
286 call to <tt>FCGI_Accept</tt> returns, bindings from the initial
287 environment are still there (unless, due to naming conflicts, some of
288 them have been overwritten by the first request). The next call to
289 <tt>FCGI_Accept</tt> removes the bindings made on the previous call
290 before adding a new set for the request just accepted, again preserving
291 the initial environment.<p>
293 The FastCGI-integrated <tt>tclsh</tt> also includes
294 commands <tt>FCGI_Finish</tt>, <tt>FCGI_SetExitStatus</tt>,
295 and <tt>FCGI_StartFilterData</tt> that correspond to
296 C functions in <tt>fcgi_stdio.h</tt>; see the manpages for
299 Converting a Tcl CGI application to FastCGI is not fundamentally
300 different from converting a C CGI application. You separate
301 the portion of the application that performs one-time
302 initialization from the portion that performs per-request
303 processing. You put the per-request processing into a loop
304 controlled by <tt>FCGI_Accept</tt>.<p>
307 <ADDRESS><A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A></ADDRESS>