-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
-<HTML>\r
- <HEAD>\r
- <TITLE>\r
- Integrating FastCGI with Tcl\r
- </TITLE>\r
-<STYLE TYPE="text/css">\r
- body {\r
- background-color: #FFFFFF;\r
- color: #000000;\r
- }\r
- :link { color: #cc0000 }\r
- :visited { color: #555555 }\r
- :active { color: #000011 }\r
- h5.c3 {text-align: center}\r
- p.c2 {text-align: center}\r
- div.c1 {text-align: center}\r
-</STYLE>\r
- </HEAD>\r
- <BODY>\r
- <DIV CLASS="c1">\r
- <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>\r
- </DIV>\r
- <BR CLEAR="all">\r
- <DIV CLASS="c1">\r
- <H3>\r
- Integrating FastCGI with Tcl\r
- </H3>\r
- </DIV>\r
- <!--Copyright (c) 1996 Open Market, Inc. -->\r
- <!--See the file "LICENSE.TERMS" for information on usage and redistribution-->\r
- <!--of this file, and for a DISCLAIMER OF ALL WARRANTIES. -->\r
- <P CLASS="c2">\r
- Michael S. Shanzer<BR>\r
- Open Market, Inc.<BR>\r
- <EM>19 January 1995</EM>\r
- </P>\r
- <H5 CLASS="c3">\r
- Copyright © 1996 Open Market, Inc. 245 First Street, Cambridge, MA 02142 U.S.A.<BR>\r
- Tel: 617-621-9500 Fax: 617-621-1703 URL: <A HREF=\r
- "http://www.openmarket.com/">http://www.openmarket.com/</A><BR>\r
- $Id: fcgi-tcl.htm,v 1.3 2001/11/27 01:03:47 robs Exp $<BR>\r
- </H5>\r
- <HR>\r
- <H3>\r
- <A NAME="S1">1. Introduction</A>\r
- </H3>\r
- <P>\r
- Tcl (tool command language) is an embeddable scripting language that's often used for CGI programming. Tcl\r
- is freely available as a source kit.\r
- </P>\r
- <P>\r
- We've built a Tcl interpreter that runs as a FastCGI application. Our purpose in doing so was twofold:\r
- </P>\r
- <UL>\r
- <LI>\r
- <I>Create a useful artifact.</I> Open Market has written many CGI applications using Tcl. Now we'd like\r
- to turn them into FastCGI applications.\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- <I>Demonstrate how easy it is to integrate FastCGI with an existing program.</I> The Tcl interpreter is a\r
- substantial program, so integrating FastCGI with the Tcl interpreter is a good test of the\r
- <TT>fcgi_stdio</TT> compatability library.\r
- </LI>\r
- </UL>\r
- <P>\r
- We've succeeded on both counts. We now have a platform for migrating our Tcl-based CGI applications to\r
- FastCGI. And the integration required a very small effort. The only source code change to the Tcl interpreter\r
- was the routine addition of a handful of new commands: <TT>FCGI_Accept</TT>, <TT>FCGI_Finish</TT>,\r
- <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT>.\r
- </P>\r
- <P>\r
- The FastCGI-integrated Tcl interpreter works as usual when run from a shell or as a CGI program. You don't\r
- need two Tcls, one for FastCGI and one for other uses.\r
- </P>\r
- <P>\r
- The remainder of this document gives a recipe you can follow to build FastCGI into Tcl, explains what's\r
- happening in the recipe, and illustrates the use of FastCGI Tcl with an example program.\r
- </P>\r
- <P>\r
- </P>\r
- <H3>\r
- <A NAME="S2">2. Recipe</A>\r
- </H3>\r
- <P>\r
- Here are the assumptions embedded in the following recipe:\r
- </P>\r
- <UL>\r
- <LI>\r
- You are building Tcl 7.4p3, the current stable Tcl release as this is written. You unpack the Tcl kit into\r
- a directory <TT>tcl7.4</TT> that's a sibling of the FastCGI kit directory <TT>fcgi-devel-kit</TT>.\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- You have gcc version 2.7 installed on your system, and use it in the build. gcc is convenient because it\r
- supports the <TT>-include</TT> command-line option that instructs the C preprocessor to include a specific\r
- file before processing any other include files. This allows you to include <TT>fcgi_stdio.h</TT> without\r
- modifying Tcl source files. (The reason for specifying gcc version 2.7 is that I have experienced bad\r
- behavior with an earlier version and the <TT>-include</TT> flag -- the C preprocessor died with SIGABRT.)\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- You have GNU autoconf installed on your system. If you don't have GNU autoconf, you will have to make\r
- certain edits by hand and repeat these edits for each build platform.<BR>\r
- <BR>\r
- </LI>\r
- </UL>\r
- <P>\r
- If those are valid assumptions, follow these steps:\r
- </P>\r
- <OL>\r
- <LI>\r
- <I>Build the FastCGI Developer's Kit.</I> Tcl needs to link against <TT>libfcgi.a</TT>, so <A HREF=\r
- "fcgi-devel-kit.htm#S2">build the FastCGI Developer's Kit</A> in order to create this library for your\r
- platform.\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- <I>Pull the Tcl 7.4p3 kit.</I> You'll need the files <A HREF=\r
- "ftp://ftp.smli.com/pub/tcl/tcl7.4.tar.Z">tcl7.4.tar.Z</A>, <A HREF=\r
- "ftp://ftp.smli.com/pub/tcl/tcl7.4p1.patch.gz">tcl7.4p1.patch.gz</A>, <A HREF=\r
- "ftp://ftp.smli.com/pub/tcl/tcl7.4p2.patch.gz">tcl7.4p2.patch.gz</A>, and <A HREF=\r
- "ftp://ftp.smli.com/pub/tcl/tcl7.4p3.patch.gz">tcl7.4p3.patch.gz</A>. (Some older Netscape browsers\r
- can't perform these retrievals because of a protocol conflict between Netscape and Sun's firewall.)\r
- <P>\r
- Unpack the tar file in the parent directory of the FastCGI kit directory you used in the previous step,\r
- so that the directories <TT>tcl7.4</TT> and <TT>fcgi-devel-kit</TT> are siblings. After unpacking the\r
- tar file, follow the directions in the <TT>README</TT> to apply the patches.\r
- </P>\r
- <P>\r
- The <A HREF="http://www.sunlabs.com:80/research/tcl/">Sun Labs Tcl/Tk Project Page</A> contains a wealth\r
- of information on Tcl, including up to date information on the latest kits.\r
- </P>\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- <I>Copy the files <TT>tclFCGI.c</TT>, <TT>tclAppInit.c</TT>, <TT>Makefile.in</TT>, and\r
- <TT>configure.in</TT> from the FastCGI kit.</I> \r
-<PRE>\r
- > cd tcl7.4\r
- > mv tclAppInit.c tclAppInit.c.orig\r
- > mv Makefile.in.orig Makefile.in.orig.orig\r
- > mv Makefile.in Makefile.in.orig\r
- > mv configure.in configure.in.orig\r
- > cp ../fcgi-devel-kit/tcl/tcl7.4/* .\r
- > cp ../fcgi-devel-kit/tcl/common/* .\r
-</PRE>\r
- </LI>\r
- <LI>\r
- <I>Create a new <TT>configure</TT> script.</I> \r
-<PRE>\r
- > autoconf\r
-</PRE>\r
- </LI>\r
- <LI>\r
- <I>Configure and build.</I> \r
-<PRE>\r
- > ./configure\r
- > make\r
-</PRE>\r
- The <TT>make</TT> creates the Tcl interpreter <TT>tclsh</TT> and library archive <TT>libtcl.a</TT> (for\r
- embedding Tcl in your own C applications). The Tcl <TT>README</TT> file explains how you can experiment\r
- with <TT>tclsh</TT> without installing it in a standard place.<BR>\r
- <BR>\r
- </LI>\r
- </OL>\r
- <H3>\r
- <A NAME="S3">3. Recipe Explained</A>\r
- </H3>\r
- <P>\r
- The recipe alone is fine if you are using Tcl 7.4p3, you have gcc version 2.7, and you have GNU autoconf. In\r
- case one or more of these assumptions doesn't hold for you, and to illuminate how little work was involved\r
- in integrating FastCGI, here's an explanation of how and why you would modify the files\r
- <TT>tclAppInit.c</TT>, <TT>Makefile.in</TT>, and <TT>configure.in</TT> from the Tcl kit.\r
- </P>\r
- <UL>\r
- <LI>\r
- <TT>tclAppInit.c</TT>:\r
- <P>\r
- </P>\r
- <UL>\r
- <LI>\r
- Add the following three lines of code to the function <TT>Tcl_AppInit</TT> after the call to\r
- <TT>Tcl_Init</TT> and after the comment about calling init procedures: \r
-<PRE>\r
- if (FCGI_Init(interp) == TCL_ERROR) {\r
- return TCL_ERROR;\r
- }\r
-</PRE>\r
- This registers four Tcl commands (<TT>FCGI_Accept</TT>, <TT>FCGI_Finish</TT>,\r
- <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT>), implemented in <TT>tclFCGI.c</TT>,\r
- with the Tcl interpreter.\r
- <P>\r
- </P>\r
- </LI>\r
- </UL>\r
- </LI>\r
- <LI>\r
- <TT>Makefile.in</TT>:\r
- <P>\r
- </P>\r
- <UL>\r
- <LI>\r
- Add <TT>tclFCGI.o</TT> to the <TT>GENERIC_OBJS</TT> variable, and add <TT>tclFCGI.c</TT> to the\r
- <TT>SRCS</TT> variable.\r
- <P>\r
- This builds the FastCGI Tcl commands and links them into the Tcl interpreter.\r
- </P>\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- Add <TT>-I../fcgi-devel-kit/include -include ../fcgi-devel-kit/include/fcgi_stdio.h</TT> to the\r
- <TT>CFLAGS</TT> variable.\r
- <P>\r
- This includes <TT>fcgi_stdio.h</TT> when compiling C code for the Tcl interpreter, overriding the\r
- normal <TT>stdio</TT> types, variables, and functions.\r
- </P>\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- Add <TT>../fcgi-devel-kit/libfcgi/libfcgi.a</TT> before the <TT>@LIBS@</TT> part of the <TT>LIBS</TT>\r
- variable.\r
- <P>\r
- This links the implementation of <TT>fcgi_stdio.h</TT> into the Tcl interpreter, for use by the\r
- <TT>FCGI_accept</TT> command and any code that uses <TT>stdio</TT> variables or calls\r
- <TT>stdio</TT> functions.\r
- </P>\r
- <P>\r
- </P>\r
- </LI>\r
- </UL>\r
- <P>\r
- The last two edits will vary if you use a compiler other than gcc or install the <TT>tcl7.4</TT>\r
- directory somewhere else in relation to the <TT>fcgi-devel-kit</TT> directory.\r
- </P>\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- <TT>configure.in</TT>:\r
- <P>\r
- </P>\r
- <UL>\r
- <LI>\r
- Replace the lines \r
-<PRE>\r
-AC_C_CROSS\r
-CC=${CC-cc}\r
-</PRE>\r
- with the lines \r
-<PRE>\r
-AC_PROG_CC\r
-AC_C_CROSS\r
-</PRE>\r
- This selects gcc in preference to other C compilers.\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- Add the following lines just after the <TT>AC_SUBST(CC)</TT> line: \r
-<PRE>\r
-AC_CHECK_LIB(socket, main, [LIBS="$LIBS -lsocket"])\r
-AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"])\r
-AC_SUBST(LIBS)\r
-</PRE>\r
- This ensures that the socket libraries used by FastCGI are linked into the Tcl interpreter.\r
- <P>\r
- </P>\r
- </LI>\r
- </UL>\r
- If GNU autoconf is not available to you, you'll leave <TT>configure.in</TT> alone and perform the\r
- following steps:\r
- <P>\r
- </P>\r
- <UL>\r
- <LI>\r
- Execute \r
-<PRE>\r
- > SETENV CC gcc\r
-</PRE>\r
- before running <TT>configure</TT>.\r
- <P>\r
- </P>\r
- </LI>\r
- <LI>\r
- If you are running on a SVR4-derived Unix platform, edit <TT>Makefile</TT> to add <TT>-lsocket\r
- -lnsl</TT> to the <TT>LIBS</TT> value after running <TT>configure</TT>.\r
- <P>\r
- </P>\r
- </LI>\r
- </UL>\r
- If you ever re-run <TT>configure</TT>, you'll need to repeat these steps.\r
- <P>\r
- </P>\r
- </LI>\r
- </UL>\r
- <H3>\r
- <A NAME="S4">4. Writing FastCGI applications in Tcl</A>\r
- </H3>\r
- <P>\r
- The Tcl program <TT>tcl/tiny-tcl-fcgi</TT> performs the same function as the C program\r
- <TT>examples/tiny-fcgi.c</TT> that's used as an example in the <A HREF="fcgi-devel-kit.htm#S3.1.1">FastCGI\r
- Developer's Kit document</A>. Here's what the Tcl version looks like:\r
- </P>\r
- <P>\r
- </P>\r
-<PRE>\r
-#!./tclsh\r
-set count 0 \r
-while {[FCGI_Accept] >= 0 } {\r
- incr count\r
- puts -nonewline "Content-type: text/html\r\n\r\n"\r
- puts "<title>FastCGI Hello! (Tcl)</title>"\r
- puts "<h1>FastCGI Hello! (Tcl)</h1>"\r
- puts "Request number $count running on host <i>$env(SERVER_NAME)</i>"\r
-}\r
-</PRE>\r
- <P>\r
- If you've built Tcl according to the recipe and you have a Web server set up to run FastCGI applications,\r
- load the FastCGI Developer's Kit Index Page in that server and run this Tcl application now.\r
- </P>\r
- <P>\r
- The script invokes Tcl indirectly via the symbolic link <TT>examples/tclsh</TT>. It does this because HP-UX\r
- has a limit of 32 characters for the first line of a command-interpreter file such as\r
- <TT>examples/tiny-tcl-fcgi</TT>. If you run on HP-UX you won't want to sprinkle symbolic links to\r
- <TT>tclsh</TT> everywhere, so you should install <TT>tclsh</TT> with a shorter pathname than\r
- <TT>/usr/local/tcl7.4-fcgi/bin/tclsh7.4</TT>.\r
- </P>\r
- <P>\r
- The Tcl command <TT>FCGI_Accept</TT> treats the initial environment differently than the C function\r
- <TT>FCGI_Accept</TT>. The first call to the C function <TT>FCGI_Accept</TT> replaces the initial environment\r
- with the environment of the first request. The first call to the Tcl command <TT>FCGI_Accept</TT> adds the\r
- variable bindings of the first request to the bindings present in the initial environment. So when the first\r
- call to <TT>FCGI_Accept</TT> returns, bindings from the initial environment are still there (unless, due to\r
- naming conflicts, some of them have been overwritten by the first request). The next call to\r
- <TT>FCGI_Accept</TT> removes the bindings made on the previous call before adding a new set for the request\r
- just accepted, again preserving the initial environment.\r
- </P>\r
- <P>\r
- The FastCGI-integrated <TT>tclsh</TT> also includes commands <TT>FCGI_Finish</TT>,\r
- <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT> that correspond to C functions in\r
- <TT>fcgi_stdio.h</TT>; see the manpages for full information.\r
- </P>\r
- <P>\r
- Converting a Tcl CGI application to FastCGI is not fundamentally different from converting a C CGI\r
- application. You separate the portion of the application that performs one-time initialization from the\r
- portion that performs per-request processing. You put the per-request processing into a loop controlled by\r
- <TT>FCGI_Accept</TT>.\r
- </P>\r
- <P>\r
- </P>\r
- <HR>\r
- <ADDRESS>\r
- <A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A>\r
- </ADDRESS>\r
- </BODY>\r
-</HTML>\r
-\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<HTML>
+ <HEAD>
+ <TITLE>
+ Integrating FastCGI with Tcl
+ </TITLE>
+<STYLE TYPE="text/css">
+ body {
+ background-color: #FFFFFF;
+ color: #000000;
+ }
+ :link { color: #cc0000 }
+ :visited { color: #555555 }
+ :active { color: #000011 }
+ h5.c3 {text-align: center}
+ p.c2 {text-align: center}
+ div.c1 {text-align: center}
+</STYLE>
+ </HEAD>
+ <BODY>
+ <DIV CLASS="c1">
+ <A HREF="http://fastcgi.com"><IMG BORDER="0" SRC="../images/fcgi-hd.gif" ALT="[[FastCGI]]"></A>
+ </DIV>
+ <BR CLEAR="all">
+ <DIV CLASS="c1">
+ <H3>
+ Integrating FastCGI with Tcl
+ </H3>
+ </DIV>
+ <!--Copyright (c) 1996 Open Market, Inc. -->
+ <!--See the file "LICENSE.TERMS" for information on usage and redistribution-->
+ <!--of this file, and for a DISCLAIMER OF ALL WARRANTIES. -->
+ <P CLASS="c2">
+ Michael S. Shanzer<BR>
+ Open Market, Inc.<BR>
+ <EM>19 January 1995</EM>
+ </P>
+ <H5 CLASS="c3">
+ Copyright © 1996 Open Market, Inc. 245 First Street, Cambridge, MA 02142 U.S.A.<BR>
+ Tel: 617-621-9500 Fax: 617-621-1703 URL: <A HREF=
+ "http://www.openmarket.com/">http://www.openmarket.com/</A><BR>
+ $Id: fcgi-tcl.htm,v 1.4 2002/02/25 00:42:59 robs Exp $<BR>
+ </H5>
+ <HR>
+ <H3>
+ <A NAME="S1">1. Introduction</A>
+ </H3>
+ <P>
+ Tcl (tool command language) is an embeddable scripting language that's often used for CGI programming. Tcl
+ is freely available as a source kit.
+ </P>
+ <P>
+ We've built a Tcl interpreter that runs as a FastCGI application. Our purpose in doing so was twofold:
+ </P>
+ <UL>
+ <LI>
+ <I>Create a useful artifact.</I> Open Market has written many CGI applications using Tcl. Now we'd like
+ to turn them into FastCGI applications.
+ <P>
+ </P>
+ </LI>
+ <LI>
+ <I>Demonstrate how easy it is to integrate FastCGI with an existing program.</I> The Tcl interpreter is a
+ substantial program, so integrating FastCGI with the Tcl interpreter is a good test of the
+ <TT>fcgi_stdio</TT> compatability library.
+ </LI>
+ </UL>
+ <P>
+ We've succeeded on both counts. We now have a platform for migrating our Tcl-based CGI applications to
+ FastCGI. And the integration required a very small effort. The only source code change to the Tcl interpreter
+ was the routine addition of a handful of new commands: <TT>FCGI_Accept</TT>, <TT>FCGI_Finish</TT>,
+ <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT>.
+ </P>
+ <P>
+ The FastCGI-integrated Tcl interpreter works as usual when run from a shell or as a CGI program. You don't
+ need two Tcls, one for FastCGI and one for other uses.
+ </P>
+ <P>
+ The remainder of this document gives a recipe you can follow to build FastCGI into Tcl, explains what's
+ happening in the recipe, and illustrates the use of FastCGI Tcl with an example program.
+ </P>
+ <P>
+ </P>
+ <H3>
+ <A NAME="S2">2. Recipe</A>
+ </H3>
+ <P>
+ Here are the assumptions embedded in the following recipe:
+ </P>
+ <UL>
+ <LI>
+ You are building Tcl 7.4p3, the current stable Tcl release as this is written. You unpack the Tcl kit into
+ a directory <TT>tcl7.4</TT> that's a sibling of the FastCGI kit directory <TT>fcgi-devel-kit</TT>.
+ <P>
+ </P>
+ </LI>
+ <LI>
+ You have gcc version 2.7 installed on your system, and use it in the build. gcc is convenient because it
+ supports the <TT>-include</TT> command-line option that instructs the C preprocessor to include a specific
+ file before processing any other include files. This allows you to include <TT>fcgi_stdio.h</TT> without
+ modifying Tcl source files. (The reason for specifying gcc version 2.7 is that I have experienced bad
+ behavior with an earlier version and the <TT>-include</TT> flag -- the C preprocessor died with SIGABRT.)
+ <P>
+ </P>
+ </LI>
+ <LI>
+ You have GNU autoconf installed on your system. If you don't have GNU autoconf, you will have to make
+ certain edits by hand and repeat these edits for each build platform.<BR>
+ <BR>
+ </LI>
+ </UL>
+ <P>
+ If those are valid assumptions, follow these steps:
+ </P>
+ <OL>
+ <LI>
+ <I>Build the FastCGI Developer's Kit.</I> Tcl needs to link against <TT>libfcgi.a</TT>, so <A HREF=
+ "fcgi-devel-kit.htm#S2">build the FastCGI Developer's Kit</A> in order to create this library for your
+ platform.
+ <P>
+ </P>
+ </LI>
+ <LI>
+ <I>Pull the Tcl 7.4p3 kit.</I> You'll need the files <A HREF=
+ "ftp://ftp.smli.com/pub/tcl/tcl7.4.tar.Z">tcl7.4.tar.Z</A>, <A HREF=
+ "ftp://ftp.smli.com/pub/tcl/tcl7.4p1.patch.gz">tcl7.4p1.patch.gz</A>, <A HREF=
+ "ftp://ftp.smli.com/pub/tcl/tcl7.4p2.patch.gz">tcl7.4p2.patch.gz</A>, and <A HREF=
+ "ftp://ftp.smli.com/pub/tcl/tcl7.4p3.patch.gz">tcl7.4p3.patch.gz</A>. (Some older Netscape browsers
+ can't perform these retrievals because of a protocol conflict between Netscape and Sun's firewall.)
+ <P>
+ Unpack the tar file in the parent directory of the FastCGI kit directory you used in the previous step,
+ so that the directories <TT>tcl7.4</TT> and <TT>fcgi-devel-kit</TT> are siblings. After unpacking the
+ tar file, follow the directions in the <TT>README</TT> to apply the patches.
+ </P>
+ <P>
+ The <A HREF="http://www.sunlabs.com:80/research/tcl/">Sun Labs Tcl/Tk Project Page</A> contains a wealth
+ of information on Tcl, including up to date information on the latest kits.
+ </P>
+ <P>
+ </P>
+ </LI>
+ <LI>
+ <I>Copy the files <TT>tclFCGI.c</TT>, <TT>tclAppInit.c</TT>, <TT>Makefile.in</TT>, and
+ <TT>configure.in</TT> from the FastCGI kit.</I>
+<PRE>
+ > cd tcl7.4
+ > mv tclAppInit.c tclAppInit.c.orig
+ > mv Makefile.in.orig Makefile.in.orig.orig
+ > mv Makefile.in Makefile.in.orig
+ > mv configure.in configure.in.orig
+ > cp ../fcgi-devel-kit/tcl/tcl7.4/* .
+ > cp ../fcgi-devel-kit/tcl/common/* .
+</PRE>
+ </LI>
+ <LI>
+ <I>Create a new <TT>configure</TT> script.</I>
+<PRE>
+ > autoconf
+</PRE>
+ </LI>
+ <LI>
+ <I>Configure and build.</I>
+<PRE>
+ > ./configure
+ > make
+</PRE>
+ The <TT>make</TT> creates the Tcl interpreter <TT>tclsh</TT> and library archive <TT>libtcl.a</TT> (for
+ embedding Tcl in your own C applications). The Tcl <TT>README</TT> file explains how you can experiment
+ with <TT>tclsh</TT> without installing it in a standard place.<BR>
+ <BR>
+ </LI>
+ </OL>
+ <H3>
+ <A NAME="S3">3. Recipe Explained</A>
+ </H3>
+ <P>
+ The recipe alone is fine if you are using Tcl 7.4p3, you have gcc version 2.7, and you have GNU autoconf. In
+ case one or more of these assumptions doesn't hold for you, and to illuminate how little work was involved
+ in integrating FastCGI, here's an explanation of how and why you would modify the files
+ <TT>tclAppInit.c</TT>, <TT>Makefile.in</TT>, and <TT>configure.in</TT> from the Tcl kit.
+ </P>
+ <UL>
+ <LI>
+ <TT>tclAppInit.c</TT>:
+ <P>
+ </P>
+ <UL>
+ <LI>
+ Add the following three lines of code to the function <TT>Tcl_AppInit</TT> after the call to
+ <TT>Tcl_Init</TT> and after the comment about calling init procedures:
+<PRE>
+ if (FCGI_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+</PRE>
+ This registers four Tcl commands (<TT>FCGI_Accept</TT>, <TT>FCGI_Finish</TT>,
+ <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT>), implemented in <TT>tclFCGI.c</TT>,
+ with the Tcl interpreter.
+ <P>
+ </P>
+ </LI>
+ </UL>
+ </LI>
+ <LI>
+ <TT>Makefile.in</TT>:
+ <P>
+ </P>
+ <UL>
+ <LI>
+ Add <TT>tclFCGI.o</TT> to the <TT>GENERIC_OBJS</TT> variable, and add <TT>tclFCGI.c</TT> to the
+ <TT>SRCS</TT> variable.
+ <P>
+ This builds the FastCGI Tcl commands and links them into the Tcl interpreter.
+ </P>
+ <P>
+ </P>
+ </LI>
+ <LI>
+ Add <TT>-I../fcgi-devel-kit/include -include ../fcgi-devel-kit/include/fcgi_stdio.h</TT> to the
+ <TT>CFLAGS</TT> variable.
+ <P>
+ This includes <TT>fcgi_stdio.h</TT> when compiling C code for the Tcl interpreter, overriding the
+ normal <TT>stdio</TT> types, variables, and functions.
+ </P>
+ <P>
+ </P>
+ </LI>
+ <LI>
+ Add <TT>../fcgi-devel-kit/libfcgi/libfcgi.a</TT> before the <TT>@LIBS@</TT> part of the <TT>LIBS</TT>
+ variable.
+ <P>
+ This links the implementation of <TT>fcgi_stdio.h</TT> into the Tcl interpreter, for use by the
+ <TT>FCGI_accept</TT> command and any code that uses <TT>stdio</TT> variables or calls
+ <TT>stdio</TT> functions.
+ </P>
+ <P>
+ </P>
+ </LI>
+ </UL>
+ <P>
+ The last two edits will vary if you use a compiler other than gcc or install the <TT>tcl7.4</TT>
+ directory somewhere else in relation to the <TT>fcgi-devel-kit</TT> directory.
+ </P>
+ <P>
+ </P>
+ </LI>
+ <LI>
+ <TT>configure.in</TT>:
+ <P>
+ </P>
+ <UL>
+ <LI>
+ Replace the lines
+<PRE>
+AC_C_CROSS
+CC=${CC-cc}
+</PRE>
+ with the lines
+<PRE>
+AC_PROG_CC
+AC_C_CROSS
+</PRE>
+ This selects gcc in preference to other C compilers.
+ <P>
+ </P>
+ </LI>
+ <LI>
+ Add the following lines just after the <TT>AC_SUBST(CC)</TT> line:
+<PRE>
+AC_CHECK_LIB(socket, main, [LIBS="$LIBS -lsocket"])
+AC_CHECK_LIB(nsl, main, [LIBS="$LIBS -lnsl"])
+AC_SUBST(LIBS)
+</PRE>
+ This ensures that the socket libraries used by FastCGI are linked into the Tcl interpreter.
+ <P>
+ </P>
+ </LI>
+ </UL>
+ If GNU autoconf is not available to you, you'll leave <TT>configure.in</TT> alone and perform the
+ following steps:
+ <P>
+ </P>
+ <UL>
+ <LI>
+ Execute
+<PRE>
+ > SETENV CC gcc
+</PRE>
+ before running <TT>configure</TT>.
+ <P>
+ </P>
+ </LI>
+ <LI>
+ If you are running on a SVR4-derived Unix platform, edit <TT>Makefile</TT> to add <TT>-lsocket
+ -lnsl</TT> to the <TT>LIBS</TT> value after running <TT>configure</TT>.
+ <P>
+ </P>
+ </LI>
+ </UL>
+ If you ever re-run <TT>configure</TT>, you'll need to repeat these steps.
+ <P>
+ </P>
+ </LI>
+ </UL>
+ <H3>
+ <A NAME="S4">4. Writing FastCGI applications in Tcl</A>
+ </H3>
+ <P>
+ The Tcl program <TT>tcl/tiny-tcl-fcgi</TT> performs the same function as the C 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
+ Developer's Kit document</A>. Here's what the Tcl version looks like:
+ </P>
+ <P>
+ </P>
+<PRE>
+#!./tclsh
+set count 0
+while {[FCGI_Accept] >= 0 } {
+ incr count
+ puts -nonewline "Content-type: text/html\r\n\r\n"
+ puts "<title>FastCGI Hello! (Tcl)</title>"
+ puts "<h1>FastCGI Hello! (Tcl)</h1>"
+ puts "Request number $count running on host <i>$env(SERVER_NAME)</i>"
+}
+</PRE>
+ <P>
+ If you've built Tcl according to the recipe and you have a Web server set up to run FastCGI applications,
+ load the FastCGI Developer's Kit Index Page in that server and run this Tcl application now.
+ </P>
+ <P>
+ The script invokes Tcl indirectly via the symbolic link <TT>examples/tclsh</TT>. It does this because HP-UX
+ has a limit of 32 characters for the first line of a command-interpreter file such as
+ <TT>examples/tiny-tcl-fcgi</TT>. If you run on HP-UX you won't want to sprinkle symbolic links to
+ <TT>tclsh</TT> everywhere, so you should install <TT>tclsh</TT> with a shorter pathname than
+ <TT>/usr/local/tcl7.4-fcgi/bin/tclsh7.4</TT>.
+ </P>
+ <P>
+ The Tcl command <TT>FCGI_Accept</TT> treats the initial environment differently than the C function
+ <TT>FCGI_Accept</TT>. The first call to the C function <TT>FCGI_Accept</TT> replaces the initial environment
+ with the environment of the first request. The first call to the Tcl command <TT>FCGI_Accept</TT> adds the
+ variable bindings of the first request to the bindings present in the initial environment. So when the first
+ call to <TT>FCGI_Accept</TT> returns, bindings from the initial environment are still there (unless, due to
+ naming conflicts, some of them have been overwritten by the first request). The next call to
+ <TT>FCGI_Accept</TT> removes the bindings made on the previous call before adding a new set for the request
+ just accepted, again preserving the initial environment.
+ </P>
+ <P>
+ The FastCGI-integrated <TT>tclsh</TT> also includes commands <TT>FCGI_Finish</TT>,
+ <TT>FCGI_SetExitStatus</TT>, and <TT>FCGI_StartFilterData</TT> that correspond to C functions in
+ <TT>fcgi_stdio.h</TT>; see the manpages for full information.
+ </P>
+ <P>
+ Converting a Tcl CGI application to FastCGI is not fundamentally different from converting a C CGI
+ application. You separate the portion of the application that performs one-time initialization from the
+ portion that performs per-request processing. You put the per-request processing into a loop controlled by
+ <TT>FCGI_Accept</TT>.
+ </P>
+ <P>
+ </P>
+ <HR>
+ <ADDRESS>
+ <A HREF="mailto:shanzer@openmarket.com">Mike Shanzer // shanzer@openmarket.com</A>
+ </ADDRESS>
+ </BODY>
+</HTML>
+