2. Edit the file "config.h" in the top level directory. You should enter the host name of the computer on which you plan to run gn and the complete path name of your gopher data directory. If you want to run at a port other than 70 also edit the DEFAULTPORT entry. You should also specify the complete path of the file mkcache/gn_mime.types on your system. You can put this file anywhere convenient (and give it any name). This file is used by the mkcache program; see the section below on Content-type for an explanation of the function of this file. Other customizations are possible but should not be needed.
3. Edit the file "Makefile" in the top level directory. This allows you to specify the C compiler used if you wish to use something other than cc, e.g. gcc. You can also specify two directories in which things are placed when you do a "make install". The first of these SERVBINDIR is the path of the directory in which you want the executable file for the gn server installed. The second BINDIR is the location for the mkcache and uncache programs. If you are using a SysV version of UNIX you will need to uncomment the "-DSYSV" compiler directive also.
4. In the directory gn-2.0X do a "make" to produce the server "gn" and the two utilities "mkcache" and "uncache". The utility mkcache produces "cache files" for use by the server (it is described below) and uncache is used to convert from the Minnesota server gopherd to gn. If you want a C compiler other than cc you will need to edit the Makefile in each directory. The binary gn is the server and can be installed anywhere you choose. The binaries mkcache and uncache are utility programs for maintainers and should be installed somewhere in your path, e.g. /usr/local/bin.
5. You can now either run the server as a standalone daemon, the sgn executable, or run under inetd, the gn executable. We first describe the standalone version. Run this with the command
sgn -p port [other options] /path/to/gnroot &
where "port" is the number of the port on which you wish the server to run. If this is a non-privileged port (i.e. > 1024) then sgn can be run as an ordinary user. However, for privileged ports like 70 or 80 you must run the command above as root. When sgn starts up it will change its user id to the one set in the config.h file line where USERID is #defined.
The other way to run the server is to use gn under inetd. There are surely variations on how this works from system to system so you may need to look at the man page for inetd.conf(5). Here's how it works under many systems, e.g. Suns: Edit the file /etc/services and create the line
gn 70/tcp
(or replace 70 by the port you wish to use). Then edit the file /etc/inetd.conf and insert the line
gn stream tcp nowait nobody /full/path/for/gn gn
After the last gn you can have optional arguments to turn on logging or use a different data directory (see the man page gn.8).
It is important to run gn as "nobody" (the fifth field in the inetd.conf line above) or some other user with no access privileges. If you are using an inetd with without the capability to set UID on startup (e.g., Ultrix), you should define the group ID and user ID in config.h so that the program is not running as root (look for the #defines USERID and GROUPID and set the values appropriately). It should never be necessary to run gn as root and to do so would be a serious mistake for maintaining security. Every attempt has been made to make gn as secure as possible, even if it is run as root, however, no program accessible to remote users on the internet can be assumed perfectly secure.
After editing the inetd.conf and services files you should find the process id number of the inetd process and do the command "kill -HUP pocess_id#". This must be done as root. If you have never done this before, get someone who has to help you.
# This is a comment Maintainer=mailto:gnperson@host.edu Name=This description of the file will display on the client Path=0/path/to/dir/file Type=0 Host=YourHost.YourU.edu Port=70 Name=This is a subdirectory Path=1/path/to/dir/subdir Type=1 Host=YourHost.YourU.edu Port=70 Name=This is a remote link Path=0/myfile/path Type=0 Host=MyHost.MyUniv.edu Port=70
The line starting with Maintainer= is optional (and provides information only to HTTP clients). It should contain a reference to the maintainer of this directory like the one above (technically any URL is permissible). The Maintainer line must be the first non-blank and non-comment line in the menu file.
There are several things to note about item entries in this file. The Name field must be first, the Path field starts with a gn type (e.g. '0' for a file or '1' for a directory, see the Appendix to this document for more details). It is followed by the path name of the file or directory relative to the top level data directory.
The Type, Host, and Port fields are optional for local items, but required for remote links. If they are not present, the Type will be taken from the first character of the Path field and the Host and Path fields will be those specified in config.h (or on the command line of mkcache). In general it is a good idea not include the Host and Port fields for local items. This makes it much easier if at some future time you should wish to move your server to a new host or new port. For more details on the format of menu files see the man page mkcache.1 and the sample menu files in each directory of the source hierarchy.
After the menu files have been created you must run the mkcache program to produce a .cache file. This can be done once for each directory or once in the top data directory with the "-r" option to make all the .cache files for the hierarchy. You might want to look a .cache file to see what it is like.
Next place a copy of the file /docs/sample.root.menu in your root data directory and name it "menu" (be sure to save the previous menu file if you have created one). Now in your root directory run the program mkcache with the command "mkcache -r". This will produce some messages including a warning about the file docs/Install, which you can ignore. (To understand the meaning of this warning read the section on structured files below.) Running mkcache with the "-r" option should produce two ".cache" files, one in your root directory and one in the docs subdirectory. Now change to the directory docs/images and run mkcache again to produce a .cache file here. Using the "-r" directory didn't take care of this directory because we don't want it to show on our menus and hence it isn't in any menu file. The image in this directory will appear "inline" in the menu for the root directory (if it is viewed with an HTTP client like Mosaic -- gopher clients lack the capability to display it and will ignore it.
Now you are ready to test your server installation on this directory. Try it with your favorite gopher or http client.
First if the compilation of gn failed and produced an error message like
ld: Undefined symbol _putenvit means that the C programming libraries on your system do not contain the function putenv(). For three functions which seem to be less common than they should versions have been supplied. They are putenv(), strncasecmp() and strftime(). To use them you will need to edit config.h and uncomment the line #define NEED_PUTENV, for example. If the compilation was successful you can check the server itself by executing it from the command line. If you use the command "gn /full/path/of/root/dir", it should run and pause for input. Type a return in response and gn should print the "gopher protocol lines" of your top level .cache file and exit. If instead of a return you type the "selector" for a file (i.e. the contents of the Path= line in the menu, like "0/dir/filename") then gn should display the contents of that file and exit.
If this doesn't happen there should be an error message which may be helpful. Better error messages are placed in the log file so you may want run gn again with the additional arguments "-L logfile" and then examine the contents of the logfile. Or if you run "gn -L /dev/tty" the log entries will be printed to your screen instead of being put in a file. If it can't open a file, for example, the name of that file will be recorded in the logfile. Check its permissions. Remember that all files that gn servers must be world readable.
A second useful test is to telnet to your server at port 70. You should get a connection message and a pause for input. If you get a "Connection refused" message it is likely there is a problem with your inetd setup or for some reason your system can't find or can't execute the gn binary.
You may also list the domain names of the machines using wildcards provided the machines all have proper PTR domain name records. To allow access to all machines under nwu.edu, use the line *.nwu.edu. Note that this will not allow access to a machine called nwu.edu if it exists. One would need to add in the record nwu.edu to allow access.
You can also exclude IP addresses or domain names by prefixing them with an '!', so if .access contained only the lines
!speedy.acns.nwu.edu *
Access would be permitted to every machine except speedy. Likewise
!129.111 *
would allow access to everyone except those on subnet 129.111. It is important to note that in determining access gn reads the .access file only until it finds a match (with or without '!') and then quits. So if .access consisted of the two lines
* !129.111
then access would be granted to everyone since the * comes first and it matches everyone.
The "-A" option is similar to the -a option except access is allowed on a per directory basis. Each client request is processed by first looking for a .access file in the directory containing the requested item and comparing the IP address of the client with the addresses in this file. If no .access file exists in this directory, one is sought in the parent directory and then if necessary the parent of the parent, etc. up to the root data directory. If no .access file is found by this process access is allowed to all clients provided the item requested exists in a .cache file.
It is possible with gn to attain even finer access discrimination than on a per directory basis, though it is somewhat cumbersome to do so. Nevertheless if you have a need to make certain menu items visible (and accessible) to a select group of hosts, this is possible. Details on how to do it are in the last section of the document /docs/technical.notes.
In the remainder of this section we will describe the grep-like builtin search capabilities of gn. The example gn server on hopf.math.nwu.edu there has a top level menu item which is called "Full text search of gn documentation." When a user selects this item the client will prompt for a search term and then return a menu of all the available files in the documentation directory which contain the search term. The searches are case insensitive. In fact they use grep like regular expressions (see the UNIX man page for grep(1)). The searching is not done by actually invoking the UNIX grep program, however. Gn has its own builtin regular expression code.
This feature is enabled by putting two entries in appropriate menu files. The first looks like this:
Name=Documentation for the GN server Path=1s/docs
This is just a minor modification of the normal entry for the directory "docs" which contains the documentation files we want to make available by gn. The only difference is that the path is "1s/docs" instead of "1/docs". The "s" that we are making the directory searchable, i.e. giving permission to run grep like searches of all the files which are listed in the menu file for the docs directory. Of course, docs must be a directory in the gn hierarchy and it must contain a .cache file allowing files to be served by gn in the usual way.
As yet, however, we have no menu item for the search. This is achieved with the second menu item:
Name=Full text search of GN documentation Path=7g/docs
The "7" indicates that this is a search type and the "g" indicates that this is a "grep" type search. In this example docs is a directory in the gn root directory, but it could be lower in which case we would have the line Path=7g/foo/bar/docs. Both of these menu items might, as in this example, go in the same menu, but this is not necessary. You might, for example, want to have the "Full text search of gn documentation" item occur in the menu which lists the documentation files, rather than menu which lists the documentation directory. Or you might want to have it occur in both menus, which is fine. This menu item can occur in any menu of your gn hierarchy. But, of course, the "Documentation for the gn server" menu item is corresponds to the physical directory "docs", so it must be in the menu corresponding to the directory containing "docs". In this example that is the gn root directory.
You can also do full text grep-like searches through any collection of directories (instead of a single directory) but it requires a little trick. Here's how you do it.
In the directory whose menu you want to contain the search item (let's call it dir1) create a new directory (call it newdir). Take the menu files from all the directories you want to search, concatenate them into a single file and make it the menu file in newdir. Run mkcache on this concatenated menu file to produce a .cache file in newdir. Now in the menu file in dir1 put the follow entry:
Name=Search a bunch of files from mulitple directories Path=7g/dir1/newdir
then make a new .cache from this menu file. That's all there is to it. If you want also to have a menu visible to users showing all the files in the multiple directories you can add an item
Name=List of a bunch of files from mulitple directories Path=1s/dir1/newdir
to the dir1/menu file. But this isn't necessary.
These searches are fairly efficient because gn contains its own regular expression matching routines rather than externally calling the grep function. Regular expressions which the user can enter as search terms are essentially the same as those allowed by grep (see the man page grep(1)) with the addition of the special character ~ which matches word boundaries.
Separator=^FromSection=^Subject:
The first line, which should have a literal space at the end not the
word
Here's another example. This document consists of sections with
section headings lines written all in caps. Since I want to make a
menu with each section a separate item I use the following entry in my
menu file
The Separator is ^[A-Z][A-Z "]*$. This matches any line starting with
a letter from A to Z (i.e. caps) followed by any number of characters
which are between A and Z or equal to space or the quotation mark, and
then the end of the line. This describes the section headings of this
document. I need the initial [A-Z] so blank lines won't be matched.
When the separator field is matched a new section is started which
will have its own menu item. The title of the menu item is determined
by the Section regular expression. In fact the section is searched,
starting with the separator line, for a match for this second regular
expression. When a match is found, everything on the line
after the matching pattern is taken as the title. Thus for
mail everything after the word "Subject:" becomes the title. In the
example of this document, the expression ^ matches the beginning of
the separator line so that whole line becomes the menu title. To see
this in use gopher to hopf.math.nwu.edu and look in the documentation
directory for this document.
Another example of how this might be used is for a directory. If a
file consists of entries like
then Separator=^Name: and Section=^Name: would give a menu with
an item
which when selected would would give the multiline record with my
name, address, etc. In this example it would be even better to use
the search feature for structured files.
In the example above the "1m" at the beginning of the Path field
indicates that this is a structured file. It is Type 1 because to
clients it will look like a directory. If we add an additional menu
entry like
which is Type 7 and has a path beginning with "7m" the client will
prompt the user for a search term which can be a regular expression.
The gn server will return a menu with only those sections containing a
match for the regular expression. Thus for the directory example if
the user searched for Northwestern she would get only those directory
entries containing that word.
Here's how this works. When mkcache is run with a menu file
containing the "1m" entry above it produces the regular .cache file
but also produces another file (in this case called Install..cache)
which is a cache file for the sections of the file Install specified
in this menu item. The lines in this cache file contain the menu
titles obtained from the file by matching regular expressions and
contain a selector which designates a range of bytes corresponding to
a section of the document. Gn knows how to serve a single section of
document when given one of these byte range selectors.
Since the file Install..cache was made when the item with path
1m/docs/Install was encountered we it is not necessary to remake when
the item with path 7m/docs/Install is reached. We signal this by
omitting the Separator and Section fields from this menu item. If
these fields were in both items the cache file Install..cache would be
made twice and the one done last would take effect if there was a
difference in the regular expressions given. Of course if the regular
expressions are omitted from both then the cache file will not be made
and attempts to access either item will result in an error
(cryptically reported as "Access denied"). For this reason Whenever, an
item of type 1m or 7m with no regular expressions is encountered by
mkcache, a warning message is printed.
It is easy to effectively use two different separator regular
expressions or two different section expressions for the same file.
You might for example want to have a mail file with menu by subject
and another menu by author. To do this you must make a UNIX link (see
the man page ln(1)) to give the mail file an additional name and use
the two different names in the menu file Path entries. This is
necessary so the cache files created will have different names.
The two regular expressions for the separator and the menu titles are
not put in to the selector string. Thus they are not available to the
client to change. This has a slightly unfortunate side effect when
uncache is used to produce a menu file. Since there is no information
about these regular expressions in the .cache file there is no way for
the uncache program to put it in the menu file it makes and they must
be added by hand. This is the only way that uncache fails to be a
complete inverse for mkcache.
Note: All regular expressions given as search terms and all lines in
which a match is sought are converted to lower case before the
matching is attempted. This has the (desirable) effect of making all
searches case insensitive. By contrast the regular expressions used
to define separators and menu lines are case sensitive. Regular
expressions which can be used for the separator and section strings
are essentially the same as those allowed by grep with the addition of
the special character ~ which matches word boundaries. To give
special characters (including ^ ~ [ ] ( ) * . \ and $) their regular
meaning they must be escaped with a \.
HTTP stands for Hyper Text Transfer Protocol and it is the underlying
protocol used by WWW (World Wide Web) browsers such as the Mosaic
family. Gopher and HTTP each have some advantages not shared by the
other. Making gn a multi-protocol server is an attempt to let
us have our cake and eat it too.
While it is correct that as soon as you start up gn you are serving
documents via HTTP, in order to take advantage of some of the
really nice features, like images in menus, you do have to put
some information in your menu file.
HTTP is a protocol designed for use with HTML (Hyper Text Markup
Language) and the usual HTTP server consists of a collection documents
written in this markup language with internal hypertext links between
them rather than any menus, as such. The gn server works with HTTP
clients by translating menus into HTML and serving them in accordance
with protocol that HTTP browsers understand.
In addition you can, of course, create your own HTML documents and
make them available on your server. You can learn about the format of
an HTML document from an online beginners guide by Marc Andreessen at
http://www.ncsa.uiuc.edu/General/Internet/WWW/HTMLPrimer.html (This is
a URL or Universal Resource Locator which says the document is
available via HTTP at www.ncsa.uiuc.edu in the file with the path
given). This document is an excellent introduction to HTML documents
and gives references for further reading.
Once you have created a document you can serve it with gn by giving
it a file name ending in .html and making it available in the usual
way as a text document. For example,
If this document is viewed with an HTTP browser it will be displayed
with the capabilities of that browser (i.e. nicely formatted in the
ways prescribed by your HTML document). If it is viewed by a gopher
client the HTML source, i.e. the unformatted document with markup
tags, will be displayed. If you want to create two versions of a
document -- one in plain text and the other in HTML, this is easily
handled by gn. Simply give the plain text file a name, say "sample,"
and use the name "sample.html" for the HTML version. Then use the
plain text name, but with a Path starting with "0h" (that's zero h).
For example a menu entry like
will provide the file "sample" to gopher clients and "sample.html" to
HTTP clients. You can also name the plaintext file sample.txt
and gn will automatically change the name to sample.html when
putting it on a menu for an HTTP browser. This is only true for the
suffix ".txt" though. If you name the plain version foo.tex then the
html version must be named foo.tex.html. There is also a "1h" which
works similarly. If a directory has path field 1h/dir/foo then gopher
clients will see it in the usual way but for HTTP clients an html file
/dir/foo.html will be served instead. However, the method described
in the following paragraph is a better way to deal with putting
HTML text into menus for most situations.
Adding HTML text to menus works slightly differently. You simply include
the source in the menu file beginning with the keyword "httpText="
on a line by itself and ending with the keyword "endText=" on a line
by itself. Here is an example from the main menu of the gn server
at hopf.math.nwu.edu. It illustrates how to put graphic images into
a menu.
This is the home of the gn Gopher/HTTP server. It contains
documentation on gn, the source, and several examples of how gn
can be used. To get the source distribution select the compressed
tar file listed below.
endText=
Name=Announcement of GN version 1.0
Path=0/announce-1.0
etc.
After the keyword httpText=, the first line creates a title for the
document. All HTML "tags" which do the markup are contained in angle
brackets <>. The line starting <img src=... says to insert the
graphic image on hopf at port 70 with Path=I/image/fract2.gif at this
point in the document. The tag <P> indicates a paragraph break. See
the document mentioned above for more details on HTML. Any HTML text
can be inserted in this way in a menu. There can be multiple
insertions and they can be anywhere in the text.
If you use the keyword Text= in place of httpText= then gn will serve
the text to HTTP clients exactly as with httpText=, but will also put
the text (with all HTML tags deleted) in the gopher menus using the
'i' or comment type supported by many clients. For the gopher clients
no text formatting is done. The lines will have the same length they
do in your menu file.
Sometimes it is desirable to actually put HTML constructs into a menu
line itself. This can be accomplished by using Hname= instead of Name=.
For example the menu entry
will produce a menu item for gopher clients linked to /dir/sample, but
for HTTP clients there will be two links the first with anchor "Sample"
to /dir/sample.html, and the second with anchor "Hypertext" to
/hyper.html. In an Hname line there must always be at least one
closing anchor to close the anchor automatically opened at the
start of the line which provides a link to the item in the Path field.
HTML documents normally have a title given at the beginning of the
document and set off by the tags <TITLE> and </TITLE>.
This is displayed by most browsers. When gn menus are
converted to HTML documents the Name= entry from the parent menu is
used as the title except for the root menu (which has no parent). The
default root menu title is set in the config.h #define ROOT_MENU_NAME,
but this can be changed executing gn or sgn with the -t
option followed by a quoted title. For example the command
Finally, it is possible to use gn as server to serve only HTTP clients
and have no menus. Well, there would have to be one menu, the root
menu, but it could contain nothing but HTML surrounded by the keywords
httpText= and endText=. This document could have hypertext links to
other HTML documents which in turn have hypertext links, etc. It
will still be necessary to create "dummy" menu files in each directory
with the Path of each of the HTML files and to run mkcache to create
.cache files. This is for security reasons.
will be displayed only to gopher clients.
Similarly there is a way to have a menu item displayed only for
HTTP clients. The menu item would be
Of course, it is also possible to handle links intended only for HTTP
clients in another way. This is done by placing them in the menu as
HTML documents, bracketed by the httpText= and endText= keywords. This
is often the more natural way to treat such items.
Finally you may wish for certain items never to be displayed on
a menu, but to be accessible to requests, for example an inline
graphic file for an html document. To be accessible such a file
must be referenced in a menu file (and the .cache file produced
from it) so that the server has permission to serve it. In versions
of gn earlier than version 2.0 the only way to achieve this
was to put such items in a subdirectory (containing a menu file) but
not refer to the directory in any other menu, so a client would not
find it. Newer versions have an explicit mechanism for this. Simply
add the line "Attribute=invisible" to the menu item and it will not
be displayed. For example the entry
will allow file.gif to be served but will never show in any client's
menu. Hence what you put in the Name field is only a note to yourself
since the server should never allow it to be viewed.
Remote links are slightly problematical for gn. If a link to a remote
server is made in the usual way by specifying Name, Path, Type, Host
and Port then the gn server assumes by default that this is a link to
a server capable of dealing only with the gopher protocol and will
present it as such. The determination of whether or not a link is
remote is done at the time that mkcache is run and a link is
considered remote unless the the Host and Port fields in the menu are
omitted or agree exactly with the default values as specified on the
mkcache command line or at compile time in the file config.h. For
this reason it is important that whenever you run mkcache you specify
the host on the command line, unless you have placed that name in the
config.h file as HOSTNAME.
Of course, you may know that a remote link is running the gn server
and therefore capable of handling HTTP requests as well as gopher
requests. In this case, to allow HTTP clients to get the best link,
simply use "gnlink" attribute in your menu file entry. For
example, a link to the Northwestern University Math server would look
like:
A final attribute value is nosearch. If a menu item contains the
line "Attribute=nosearch" then that item will be displayed for clients
but its title will not be used when searches of menu items (as described
in the next section) are done.
The only currently allowable values for the Attribute= field in a menu
are, invisible, gopheronly, httponly, nosearch, and gnlink. When entered
in a menu attribute line their case is not significant. It is not
possible for a single menu item to have two attributes.
Here's how to set it up. Create an entry like this in the menu file
where you want the search item to occur.
(If you want the search to cover only those items in directory
/foo/bar, then the path line should be Path=7c/foo/bar/.cache) now run
"mkcache" to translate the new menu file to a .cache file and you are
done. The Type, Host and Port lines are optional -- if they are
omitted mkcache will use the default value or the value supplied on
the command line. When you change any of the menus in your server and
remake the .cache files gn will automatically reflect this in menu
searches. There is a maximum depth which gn will search into the gn
hierarchy. It's value can be changed by editing the config.h file and
re-compiling.
When configuring "gn" for compilation, be sure to set the
#define DECOMPRESS in the file config.h to the path name of
the program which will decompress the files you have compressed.
The default value for this is "/usr/local/bin/zcat". Another
possibility would be "/usr/ucb/uncompress -c".
If the file you want to make available is "rootdir/dir1/bigfile,"
first you must compress it with the compress command which will
replace it with the file bigfile.gz or bigfile.Z. You then make
a menu entry like the following (assuming bigfile was a text file
and you have produced bigfile.gz).
The key here is the 'Z' which is the second character of the Path
field. It indicates that the file is compressed. The Path would
start with "0Z" (that's zero Z) for any compressed text file.
It doesn't matter how the file was compressed or whether its name
is bigfile.Z or bigfile.gz or something else. You have already
told gn how to decompress the file by specifying the DECOMPRESS
program in config.h.
Of course, if bigfile is a binary the Path field would be
9Z/dir/bigfile.gz and the Type would be 9. For a sound file
Path=sZ/dir/bigfile.gz, Type=s, etc. Files of types 0, 4, 5, 9, s,
and I can be compressed. Structured files (type 1m) cannot be
compressed.
You might want to let users download the file in compressed format.
You could give them the option by having the menu item as above
with Path=0Z/dir/bigfile.gz and also having a menu item
Note that the Type=9 since compressed files are binaries (even though
bigfile is text) and there is no 'Z' as the second character of the
Path, because now we do not want to decompress. Also note that two
versions of bigfile show up on your menu (text and compressed binary)
but there is only one file bigfile.gz on your disk.
The phrase "exec" says to run the program "prog" which must be
executable by the gn userid (probably "nobody"). The "0" after
the exec says this is a text file. exec can return most types,
including 0 (text), 1 (menus), 9 (binaries), s (sound), I (image).
Scripts or programs returning type 1 documents must produce a document
in the format of a .cache file. This format is described in the file
/docs/technical.notes. To specify a type the single character type is
appended to the word exec in the path and the Type=0 line above is not
really necessary. Thus if you wanted to return the output of a
program which is in the format of an image file you might have an
entry like
The pair of colons in the path can contain arguments to the program.
For security reasons none of the characters
are allowed in the arguments to programs. Thus, if you want to run a
command like "prog -u
and make this script be what gn executes.
It would be nice to have the client query the user for a word or
phrase and have this passed to the program as an argument. Unfortunately
the basic gopher protocol protocol does not allow this.
In the meantime here is an example of how to work around the
difficulty. This is a simple example of how to make a search item
which will print all the lines of a file containing a match for a
given word. It requires two very small shell scripts. The first,
let's call it "script1" would have a menu file entry like
in gn_root/dir/menu and the script itself, gn_root/dir/script1, would
contain only the lines
with <tab> replaced by the tab character. When a client selects this
item and returns a search term the script creates a new menu with one
item "on the fly". The one menu item is "Matches for X" where X is
the search term entered by the user.
When this "Matches" item is selected and sent to the server the second
script "script2" is invoked with argument set to the search term
already entered. Script2 should contain the lines
which will then output the matching lines. Recall that for security
reasons every file, including scripts, which will be served, must be
in a .cache file. To achieve this there must be a menu item for
script2 in gn_root/dir2/menu like
One normally puts this in a different directory (gn_root/dir2 in this
example) which is not in your gn hierarchy and hence this item won't
show on any menu. It is only there so that when gn is asked to
provide the output of script2 in response to the "on the fly menu", it
can find script2 in a .cache file and hence serve its output.
One final remark about this example. It will work fine it the search
term is a normal word or part of a word. However, regular expressions
used by grep often contain special characters which by default are not
allowed in arguments to scripts as mentioned above. This applies only
to arguments to scripts, as in this example, and regular expressions
work fine with the built searches in gn described above.
There is also support in gn for scripts which comply with the
CGI (Common
Gateway Interface) standard. This allows the use of a growing
collection of scripts which are written for HTTP servers supporting
the standard. There is an
archive of such
scripts.
The use of these scripts is similar to the exec0 types described
above but with a somewhat different syntax. Your menu file entry might
look like
The initial CGI in the Path field indicates that this is
a CGI item. In some respects the syntax is rather awkward, but
it is made necessary by complying with the standard which was
really intended for servers with a quite different design.
In particular the name of the script must end with the suffix
".cgi" (or a replacement set at compile time in the file config.h) and
no directory above the script in the data hierarchy may end in this
suffix. The reason for this is the unusual way in which arguments to
CGI scripts must be transmitted to the script. Instead of enclosing
them in colons as with the exec0 examples above, the arguments
are appended to the end of the path as if they were a file name.
Thus to execute the script above with argument "foo" you would use
the URL http://host/CGI/dir/script.cgi/foo.
This URL is frequently generated by the script itself with the
extra so called "path information" (the "foo" in this example) used
as a way of saving state. It is also possible to put this in the
menu file so the script will be executed with that argument.
in gn_mime.types means that menu items with Type=I and a file name like
picture.gif should be given the "image/gif" type. This assignment
can be overridden on a per file basis by adding a line to the menu
file. For example, a menu item like
will be given the Content-type "text/html" even though the file name
does not end with the suffix ".html" (had the file name been
filename.html it would not have been necessary to add the ContentType=
line. There is a similar "ContentEncoding" field to indicate that a
file is compressed. For example, the entry
would be appropriate for a compressed Postscript file. A content
encoding should not be used with files of type 0Z or 9Z (see the
section on compressed files) because these
are decompressed on the server so the client should not be told they
are compressed.
If standard suffixes (as described in the gn_mime.types file) are used
gn can infer the correct values of ContentType and
ContentEncoding, so these need not be in the menu file. These
attributes are only used with clients supporting the HTTP/1.0
protocol. Gopher0 clients and HTTP/0.9 protocol clients are not
capable of using this information.
If the file gn_mime.types is not present mkcache will issue a warning
but use internal default values. The file exists so that you can add
to it if you wish to add new kinds of documents to your server. The
format of the file is explained in the file. The default version of
the file is in mkcache/gn_mime.types. The internal defaults are the
same as what is currently in this file.
To subscribe send a message to listserv@netcom.com containing the
line
Name=Installation/Maintenance Guide Sections
Path=1m/docs/Install
Separator=^[A-Z][A-Z" ]*$
Section=^
Type=1
Name: Franks, John
Address: Department of Mathematics, Northwestern University
Phone: 708-491-5548
etc., etc.
1. Franks, John
Name=Search Installation Guide
Path=7m/docs/Install
Type=7
Using HTML -- GN as a WWW Server
Starting with release 1.0, the gn sever became a multi-protocol
server. It will accept either gopher requests or HTTP requests and
respond appropriately. To the maintainer this takes place
automatically with no action necessary or his or her part.
Name=A Sample of Hypertext Markup
Path=0/dir/dir2/sample.html
Name=A Sample of Plain/Hyper text
Path=0h/dir/dir2/sample
httpText=
Hname=Sample</A> of <A HREF="http://host/hyper.html">Hyper text</A>
Path=0h/dir/sample
sgn -t "My Server"
will set the title to My Server. The Attribute Field in Menus
The HttpText and Hname mechanisms described above give a way to
display more information to HTTP clients than to gopher clients.
Sometimes it is desirable to do the reverse, i.e. show a link to
gopher clients but hide it from WWW clients. This can be done by
using the Attribute= field for the menu item. Thus the entry
Name=A file for gopher clients only
Path=0/dir/file
Attribute=gopheronly
Name=A file for HTTP clients only
Path=0/dir/file
Attribute=httponly
Name=My gif file for an inline image
Path=I/dir/file.gif
Attribute=invisible
Name=Northwestern University Mathematics Department
Path=1/
Attribute=gnlink
Type=1
Host=gopher.math.nwu.edu
Port=70
Setting up a "Search All Menus" Item
A builtin feature of gn is the ability to have a menu item which
when selected prompts the user for a search term and returns a
"virtual menu" of all menu items which contain that term. In fact
such an item can occur at any level and return either all matches
from all menus on that server or all matches at or below some
chosen level.
Name=Search all menus on this server
Type=7
Path=7c/.cache
Compressed Files
If you wish you can keep files on your server in a compressed format
and uncompress them on the fly as a client requests them. You need
a program to compress the files and a companion program to decompress
them. I recommend "gzip" and "zcat" from the GNU project. They are
considerably more efficient than the UNIX standard "compress."
Name=All the text in Bigfile
Path=0Z/dir/bigfile.gz
Type=0
Name=Bigfile in compressed format
Path=9/dir/bigfile.gz
Type=9
Serving the Output of a Program or Script
Sometimes it is convenient to have the server return the output
of a program or script. This capability is built into gn. Assuming
you have a program in a file "prog" which returns some text you
can make its output be an item on your server's menu with a menu
entry like
Name=Program output
Type=0
Path=exec0::/dir/prog
Name=Image program output
Path=execI::/dir/prog
ContentType=image/gif
; ` ' | \ * ? - ~ < > ^ ( ) [ ] { } & $ / or \
Name=Search for a word in Myfile
Path=7/dir/script1
#!/bin/sh
echo "0Matches for $1: <tab>exec0:$1:/dir2/script2<tab>myhost.edu<tab>70"
#!/bin/sh
grep "$1" /complete/path/of/Myfile
Name=Anything
Path=exec0::/dir2/script2
Name=A CGI script
Path=CGI/dir/script.cgi
Name=A CGI script
Path=CGI/dir/script.cgi/foo
MIME Content-Type
HTTP/1.0 uses an IANA standard "Mime Content-type" classification for
the files served. Examples of such types are "text/plain",
"image/gif", etc. Starting with version 1.0 the gn server needs to
know this type to transmit to the client. This is normally
accomplished automatically using the file gn_mime.types which can be
edited by server maintainer. Information in this file enables mkcache
program to translate the gopher Type= field and the suffix from the
file name into a standard type. For example, the line
I<tab>gif<tab>image/gif
Name=An html file
Path=0/dir/filename
ContentType=text/html
Type=0
Name=A compressed Postscript file
Path=9/dir/filename.ps.gz
ContentType=application/postscript
ContentEncoding=x-gzip
Type=9
Support
Unfortunately, I do not have time to answer all the questions sent to
me by GN users. I recommend that you subscribe to the mailing list of
gn maintainers and ask your questions there. It is read by many
knowledgable GN users (including me). The people reading this list
seem to be very helpful.
subscribe gn-maint
Thanks
I would like to thank the many people who have aided in the creation
of the gn package, either through writing code or finding and
fixing bugs. They include Earle Ake, Henry Cejtin, Mike Crowley, Paul
DuBois, Stephen Hebditch, Albert Lunde, Jishnu Mukerji, Marko
Nordberg, Jim Rees, Craig Milo Rogers, Stephen Trier, Ed Vielmetti,
and Rico Tudor. Appendix: GN Internal Types
Each "Path" field in a gn menu file contains an entry known as a
selector. The format of this selector is a gn internal type
field followed by the path relative to the gn root directory of the
file referenced. The gn internal type indicates to the server what
kind of document or file is referenced. It can be a single character
like "0" to indicate a text file, or a more complicated string.
Here is a list of the types and what they mean.
John Franks -- Dept of Math. Northwestern University
<john@math.nwu.edu>