2 <head><title>Integrating FastCGI with Tcl</title>
5 <body bgcolor="#FFFFFF" text="#000000" link="#cc0000" alink="#000011"
9 <a href="/fastcgi/words">
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.1 1997/09/16 15:36:26 stanleyg 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="http://www.fastcgi.com/kit/doc/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
258 function as the C program <tt>examples/tiny-fcgi.c</tt>
259 that's used as an example in the
260 <a href="fcgi-devel-kit.html#S3.1.1">FastCGI Developer's Kit
261 document</a>. Here's what the Tcl version looks like:<p>
266 while {[FCGI_Accept] >= 0 } {
268 puts -nonewline "Content-type: text/html\r\n\r\n"
269 puts "<title>FastCGI Hello! (Tcl)</title>"
270 puts "<h1>FastCGI Hello! (Tcl)</h1>"
271 puts "Request number $count running on host <i>$env(SERVER_NAME)</i>"
275 If you've built Tcl according to the recipe and you have a Web server
276 set up to run FastCGI applications, load the FastCGI Developer's Kit
277 Index Page in that server and run this Tcl application now.<p>
279 The script invokes Tcl indirectly via the symbolic link
280 <tt>examples/tclsh</tt>. It does this because HP-UX has a limit of 32
281 characters for the first line of a command-interpreter file such as
282 <tt>examples/tiny-tcl-fcgi</tt>. If you run on HP-UX you won't want
283 to sprinkle symbolic links to <tt>tclsh</tt> everywhere, so you should install
284 <tt>tclsh</tt> with a shorter pathname than
285 <tt>/usr/local/tcl7.4-fcgi/bin/tclsh7.4</tt>.<p>
287 The Tcl command <tt>FCGI_Accept</tt> treats the initial
288 environment differently than the C function <tt>FCGI_Accept</tt>. The
290 C function <tt>FCGI_Accept</tt> replaces the initial environment with
291 the environment of the first request. The first call to the Tcl command
292 <tt>FCGI_Accept</tt> adds the variable bindings of the first request
293 to the bindings present in the initial environment. So when the first
294 call to <tt>FCGI_Accept</tt> returns, bindings from the initial
295 environment are still there (unless, due to naming conflicts, some of
296 them have been overwritten by the first request). The next call to
297 <tt>FCGI_Accept</tt> removes the bindings made on the previous call
298 before adding a new set for the request just accepted, again preserving
299 the initial environment.<p>
301 The FastCGI-integrated <tt>tclsh</tt> also includes
302 commands <tt>FCGI_Finish</tt>, <tt>FCGI_SetExitStatus</tt>,
303 and <tt>FCGI_StartFilterData</tt> that correspond to
304 C functions in <tt>fcgi_stdio.h</tt>; see the manpages for
307 Converting a Tcl CGI application to FastCGI is not fundamentally
308 different from converting a C CGI application. You separate
309 the portion of the application that performs one-time
310 initialization from the portion that performs per-request
311 processing. You put the per-request processing into a loop
312 controlled by <tt>FCGI_Accept</tt>.<p>
315 <ADDRESS><A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A></ADDRESS>