home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

Book HomeApache: The Definitive GuideSearch this book

4.2. Writing and Executing Scripts

Bear in mind that the CGI script must be executable in the opinion of your operating system. In order to test it, you can run it from the console with the same login that Apache uses. If you cannot, you have a problem that's signaled by disagreeable messages at the client end, plus equivalent stories in the log files on the server, such as:

You don't have permission to access /cgi-bin/mycgi on this server

You need to do either of the following:

If you have not used ScriptAlias, then Options ExecCGI must be on. It will normally be on by default. See the section Section 4.5, "Debugging Scripts", later in this chapter, for more information on fixing scripts.

To experiment, we have a simple test script, mycgi.cgi, in two locations: .../cgi-bin to test the first method above, and .../site.cgi/htdocs to test the second. When it works, we would write the script properly in C or Perl or whatever.

Figure 4.2 The script mycgi.cgi looks like this:

echo "content-type: text/plain"
echo "Have a nice day"

Figure 4.2 Under Win32, providing you want to run your script under COMMAND.COM and call it mycgi.bat, the script can be a little simpler than the Unix version -- it doesn't need the line that specifies the shell:

@echo off
echo "content-type: text/plain"
echo "Have a nice day"

Figure 4.2 The @echo off command turns off command-line echoing, which would otherwise completely destroy the output of the batch file. The slightly weird-looking "echo." gives a blank line (a plain echo without a dot prints "ECHO is off").

Figure 4.2 If you are running a more exotic shell, like bash or perl, you need the `shebang' line at the top of the script to invoke it:

#!shell path

A CGI script consists of headers and a body. Everything up to the first blank line (strictly speaking, CRLF CRLF, but Apache will tolerate LF LF) is header, and everything else is body. The lines of the header are separated by LF or CRLF. A list of possible headers is to be found in the draft CGI 1.1 specification, from which this is a quotation:

The CGI 
header fields have the generic syntax:
    generic-header = field-name ":" [ field-value ] NL
    field-name     = 1*<any CHAR, excluding CTLs, SP and ":">
    field-value    = *( field-content | LWSP )
    field-content  = *( token | tspecial | quoted-string )
   The field-name is not case sensitive; a NULL field value is equivalent to
   the header field not being sent.
          The Internet Media Type [9] of the entity body, which is to
          be sent unmodified to the client.
    Content-Type = "Content-Type" ":" media-type NL
          This is actually an HTTP-Header rather than a CGI-header
          field, but it is listed here because of its importance in the
          CGI dialogue as a member of the "one of these is required"
          set of header fields.
          This is used to specify to the server that the script is
          returning a reference to a document rather than an actual
    Location         = "Location" ":"
                       ( fragment-URI | rel-URL-abs-path ) NL
    fragment-URI     = URI [ # fragmentid ]
    URI              = scheme ":" *qchar
    fragmentid       = *qchar
    rel-URL-abs-path = "/" [ hpath ] [ "?" query-string ]
    hpath            = fpsegment *( "/" psegment )
    fpsegment        = 1*hchar
    psegment         = *hchar
    hchar            = alpha | digit | safe | extra
                     | ":" | "@" | "& | "="

Our little script first tells Apache to use the sh shell and then specifies what type of data the content is, using the Content-Type header. This must be specified because:

  • Apache can't tell from the filename (remember that for ordinary files, there's a host of ways of determining the content type, for example, the mime.types file or the AddType directive).

  • The CGI script may want to decide on content type dynamically.

So, the script must send at least one header line: Content-Type. We set it to text/plain to get a nicely formatted output screen. Failure to include it results in an error message on the client, plus equivalent entries in the server log files:

The server encountered an internal error or misconfiguration and was unable to complete your request

Headers must be terminated by a blank line, hence the second echo.

We are going to call our script from one of the Butterthlies forms: form_summer.html. Depending on which location and calling method we use for the script, we need slightly different invocations in the form.

Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.