2 <head><title>Integrating FastCGI with Tcl</title>
5 <body bgcolor="#FFFFFF" text="#000000" link="#cc0000" alink="#000011"
9 <a href="http://fastcgi.com">
10 <img border=0 src="../images/fcgi-hd.gif" alt="[[FastCGI]]"></a>
13 <h3><center>Integrating FastCGI with Tcl</center></h3>
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. -->
24 <EM>19 January 1995</EM>
28 Copyright © 1996 Open Market, Inc. 245 First Street, Cambridge,
30 Tel: 617-621-9500 Fax: 617-621-1703 URL:
31 <a href="http://www.openmarket.com/">http://www.openmarket.com/</a><br>
32 $Id: fcgi-tcl.htm,v 1.2 2001/05/14 13:00:30 robs Exp $ <br>
37 <h3><a NAME = "S1">1. Introduction</a></h3>
40 Tcl (tool command language) is an embeddable scripting language
41 that's often used for CGI programming. Tcl is freely available
44 We've built a Tcl interpreter that runs as a FastCGI application. Our
45 purpose in doing so was twofold:
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
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.
58 We've succeeded on both counts. We now have a platform for
59 migrating our Tcl-based CGI applications to FastCGI. And
60 the integration required a very small effort. The only source
61 code change to the Tcl interpreter was the routine addition of a
62 handful of new commands: <tt>FCGI_Accept</tt>, <tt>FCGI_Finish</tt>,
63 <tt>FCGI_SetExitStatus</tt>, and <tt>FCGI_StartFilterData</tt>.<p>
65 The FastCGI-integrated Tcl interpreter works as usual when run
66 from a shell or as a CGI program. You don't need two Tcls,
67 one for FastCGI and one for other uses.<p>
69 The remainder of this document gives a recipe you can follow to
70 build FastCGI into Tcl, explains what's happening in the recipe,
71 and illustrates the use of FastCGI Tcl with
72 an example program.<p>
74 <h3><a NAME = "S2">2. Recipe</a></h3>
76 Here are the assumptions embedded in the following recipe:
78 <li>You are building Tcl 7.4p3, the current stable Tcl release
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>
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>
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>
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>
101 If those are valid assumptions, follow these steps:
103 <li><i>Build the FastCGI Developer's Kit.</i>
104 Tcl needs to link against <tt>libfcgi.a</tt>, so
105 <a href="fcgi-devel-kit.htm#S2">build
106 the FastCGI Developer's Kit</a>
107 in order to create this library for your platform.<p>
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>,
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>
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>
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>
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>
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>
141 <li><i>Create a new <tt>configure</tt> script.</i>
145 <li><i>Configure and build.</i>
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>
156 <h3><a NAME = "S3">3. Recipe Explained</a></h3>
158 The recipe alone is fine if you are using Tcl 7.4p3, you have gcc
159 version 2.7, and you have GNU autoconf. In case one or more of these
160 assumptions doesn't hold for you, and to illuminate how little work was
161 involved in integrating FastCGI, here's an explanation of how
162 and why you would modify the files <tt>tclAppInit.c</tt>,
163 <tt>Makefile.in</tt>, and <tt>configure.in</tt> from the Tcl kit.
166 <li><tt>tclAppInit.c</tt>:<p>
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
173 if (FCGI_Init(interp) == TCL_ERROR) {
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>
182 <li><tt>Makefile.in</tt>:<p>
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>
187 This builds the FastCGI Tcl commands and
188 links them into the Tcl interpreter.<p>
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>
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>
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>
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>
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>
211 <li><tt>configure.in</tt>:<p>
222 This selects gcc in preference to other C compilers.<p>
225 Add the following lines just after the
226 <tt>AC_SUBST(CC)</tt> line:
228 AC_CHECK_LIB(socket, main, [LIBS="$LIBS -lsocket"])
229 AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"])
231 This ensures that the socket libraries used by FastCGI
232 are linked into the Tcl interpreter.<p>
234 If GNU autoconf is not available to you, you'll leave
235 <tt>configure.in</tt> alone and perform the following steps:<p>
240 > SETENV CC gcc</pre>
241 before running <tt>configure</tt>.<p>
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>
249 If you ever re-run <tt>configure</tt>, you'll need to repeat
255 <h3><a NAME = "S4">4. Writing FastCGI applications in Tcl</a></h3>
257 The Tcl program <tt>tcl/tiny-tcl-fcgi</tt> performs the same function as the C
258 program <tt>examples/tiny-fcgi.c</tt> that's used as an example in the <a href="fcgi-devel-kit.htm#S3.1.1">FastCGI
259 Developer's Kit document</a>. Here's what the Tcl version looks like:
265 while {[FCGI_Accept] >= 0 } {
267 puts -nonewline "Content-type: text/html\r\n\r\n"
268 puts "<title>FastCGI Hello! (Tcl)</title>"
269 puts "<h1>FastCGI Hello! (Tcl)</h1>"
270 puts "Request number $count running on host <i>$env(SERVER_NAME)</i>"
274 If you've built Tcl according to the recipe and you have a Web server
275 set up to run FastCGI applications, load the FastCGI Developer's Kit
276 Index Page in that server and run this Tcl application now.<p>
278 The script invokes Tcl indirectly via the symbolic link
279 <tt>examples/tclsh</tt>. It does this because HP-UX has a limit of 32
280 characters 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
282 to 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>
286 The Tcl command <tt>FCGI_Accept</tt> treats the initial
287 environment differently than the C function <tt>FCGI_Accept</tt>. The
289 C function <tt>FCGI_Accept</tt> replaces the initial environment with
290 the 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
292 to the bindings present in the initial environment. So when the first
293 call to <tt>FCGI_Accept</tt> returns, bindings from the initial
294 environment are still there (unless, due to naming conflicts, some of
295 them have been overwritten by the first request). The next call to
296 <tt>FCGI_Accept</tt> removes the bindings made on the previous call
297 before adding a new set for the request just accepted, again preserving
298 the initial environment.<p>
300 The FastCGI-integrated <tt>tclsh</tt> also includes
301 commands <tt>FCGI_Finish</tt>, <tt>FCGI_SetExitStatus</tt>,
302 and <tt>FCGI_StartFilterData</tt> that correspond to
303 C functions in <tt>fcgi_stdio.h</tt>; see the manpages for
306 Converting a Tcl CGI application to FastCGI is not fundamentally
307 different from converting a C CGI application. You separate
308 the portion of the application that performs one-time
309 initialization from the portion that performs per-request
310 processing. You put the per-request processing into a loop
311 controlled by <tt>FCGI_Accept</tt>.<p>
314 <ADDRESS><A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A></ADDRESS>