1 |
.TH thttpd 8 "29 February 2000" |
2 |
.SH NAME |
3 |
thttpd - tiny/turbo/throttling HTTP server |
4 |
.SH SYNOPSIS |
5 |
.B thttpd |
6 |
.RB [ -C |
7 |
.IR configfile ] |
8 |
.RB [ -p |
9 |
.IR port ] |
10 |
.RB [ -d |
11 |
.IR dir ] |
12 |
.RB [ -r | -nor ] |
13 |
.RB [ -s | -nos ] |
14 |
.RB [ -v | -nov ] |
15 |
.RB [ -g | -nog ] |
16 |
.RB [ -u |
17 |
.IR user ] |
18 |
.RB [ -c |
19 |
.IR cgipat ] |
20 |
.RB [ -t |
21 |
.IR throttles ] |
22 |
.RB [ -h |
23 |
.IR host ] |
24 |
.RB [ -l |
25 |
.IR logfile ] |
26 |
.RB [ -i |
27 |
.IR pidfile ] |
28 |
.RB [ -T |
29 |
.IR charset ] |
30 |
.RB [ -V ] |
31 |
.RB [ -D ] |
32 |
.SH DESCRIPTION |
33 |
.PP |
34 |
.I thttpd |
35 |
is a simple, small, fast, and secure HTTP server. |
36 |
It doesn't have a lot of special features, but it suffices for most uses of |
37 |
the web, it's about as fast as the best full-featured servers (Apache, NCSA, |
38 |
Netscape), |
39 |
and it has one extremely useful feature (URL-traffic-based throttling) |
40 |
that no other server currently has. |
41 |
.SH OPTIONS |
42 |
.TP |
43 |
.B -C |
44 |
Specifies a config-file to read. |
45 |
All options can be set either by command-line flags or in the config file. |
46 |
See below for details. |
47 |
.TP |
48 |
.B -p |
49 |
Specifies an alternate port number to listen on. |
50 |
The default is 80. |
51 |
The config-file option name for this flag is "port", |
52 |
and the config.h option is DEFAULT_PORT. |
53 |
.TP |
54 |
.B -d |
55 |
Specifies a directory to chdir() to at startup. |
56 |
This is merely a convenience - you could just as easily |
57 |
do a cd in the shell script that invokes the program. |
58 |
The config-file option name for this flag is "dir", |
59 |
and the config.h options are WEBDIR, USE_USER_DIR. |
60 |
.TP |
61 |
.B -r |
62 |
Do a chroot() at initialization time, restricting file access |
63 |
to the program's current directory. |
64 |
If -r is the compiled-in default, then -nor disables it. |
65 |
See below for details. |
66 |
The config-file option names for this flag are "chroot" and "nochroot", |
67 |
and the config.h option is ALWAYS_CHROOT. |
68 |
.TP |
69 |
.B -nos |
70 |
Don't do explicit symbolic link checking. |
71 |
Normally, thttpd explicitly expands any symbolic links in filenames, |
72 |
to check that the resulting path stays within the original document tree. |
73 |
If you want to turn off this check and save some CPU time, you can use |
74 |
the -nos flag, however this is not recommended. |
75 |
Note, though, that if you are using the chroot option, the symlink |
76 |
checking is unnecessary and is turned off, so the safe way to save |
77 |
those CPU cycles is to use chroot. |
78 |
The config-file option names for this flag are "symlink" and "nosymlink". |
79 |
.TP |
80 |
.B -v |
81 |
Do el-cheapo virtual hosting. |
82 |
If -v is the compiled-in default, then -nov disables it. |
83 |
See below for details. |
84 |
The config-file option names for this flag are "vhost" and "novhost", |
85 |
and the config.h option is ALWAYS_VHOST. |
86 |
.TP |
87 |
.B -g |
88 |
Use a global passwd file. |
89 |
This means that every file in the entire document tree is protected by |
90 |
the single .htpasswd file at the top of the tree. |
91 |
Otherwise the semantics of the .htpasswd file are the same. |
92 |
If this option is set but there is no .htpasswd file in |
93 |
the top-level directory, then thttpd proceeds as if the option was |
94 |
not set - first looking for a local .htpasswd file, and if that doesn't |
95 |
exist either then serving the file without any password. |
96 |
If -g is the compiled-in default, then -nog disables it. |
97 |
The config-file option names for this flag are "globalpasswd" and |
98 |
"noglobalpasswd", |
99 |
and the config.h option is ALWAYS_GLOBAL_PASSWD. |
100 |
.TP |
101 |
.B -u |
102 |
Specifies what user to switch to after initialization when started as root. |
103 |
The default is "nobody". |
104 |
The config-file option name for this flag is "user", |
105 |
and the config.h option is DEFAULT_USER. |
106 |
.TP |
107 |
.B -c |
108 |
Specifies a wildcard pattern for CGI programs, for instance "**.cgi" |
109 |
or "/cgi-bin/*". |
110 |
See below for details. |
111 |
The config-file option name for this flag is "cgipat", |
112 |
and the config.h option is CGI_PATTERN. |
113 |
.TP |
114 |
.B -t |
115 |
Specifies a file of throttle settings. |
116 |
See below for details. |
117 |
The config-file option name for this flag is "throttles". |
118 |
.TP |
119 |
.B -h |
120 |
Specifies a hostname to bind to, for multihoming. |
121 |
The default is to bind to all hostnames supported on the local machine. |
122 |
See below for details. |
123 |
The config-file option name for this flag is "host", |
124 |
and the config.h option is SERVER_NAME. |
125 |
.TP |
126 |
.B -l |
127 |
Specifies a file for logging. |
128 |
If no -l argument is specified, thttpd logs via syslog(). |
129 |
If "-l /dev/null" is specified, thttpd doesn't log at all. |
130 |
The config-file option name for this flag is "logfile". |
131 |
.TP |
132 |
.B -i |
133 |
Specifies a file to write the process-id to. |
134 |
If no file is specified, no process-id is written. |
135 |
You can use this file to send signals to thttpd. |
136 |
See below for details. |
137 |
The config-file option name for this flag is "pidfile". |
138 |
.TP |
139 |
.B -T |
140 |
Specifies the character set to use with text MIME types. |
141 |
The default is iso-8859-1. |
142 |
The config-file option name for this flag is "charset", |
143 |
and the config.h option is DEFAULT_CHARSET. |
144 |
.TP |
145 |
.B -V |
146 |
Shows the current version info. |
147 |
.TP |
148 |
.B -D |
149 |
This was originally just a debugging flag, however it's worth mentioning |
150 |
because one of the things it does is prevent thttpd from making itself |
151 |
a background daemon. |
152 |
Instead it runs in the foreground like a regular program. |
153 |
This is necessary when you want to run thttpd wrapped in a little shell |
154 |
script that restarts it if it exits. |
155 |
.SH "CONFIG-FILE" |
156 |
.PP |
157 |
All the command-line options can also be set in a config file. |
158 |
One advantage of using a config file is that the file can be changed, |
159 |
and thttpd will pick up the changes with a restart. |
160 |
.PP |
161 |
The syntax of the config file is simple, a series of "option" or |
162 |
"option=value" separated by whitespace. |
163 |
The option names are listed above with their corresponding command-line flags. |
164 |
.SH "CHROOT" |
165 |
.PP |
166 |
chroot() is a system call that restricts the program's view |
167 |
of the filesystem to the current directory and directories |
168 |
below it. |
169 |
It becomes impossible for remote users to access any file |
170 |
outside of the initial directory. |
171 |
The restriction is inherited by child processes, so CGI programs get it too. |
172 |
This is a very strong security measure, and is recommended. |
173 |
The only downside is that only root can call chroot(), so this means |
174 |
the program must be started as root. |
175 |
However, the last thing it does during initialization is to |
176 |
give up root access by becoming another user, so this is safe. |
177 |
.PP |
178 |
The program can also be compile-time configured to always |
179 |
do a chroot(), without needing the -r flag. |
180 |
.PP |
181 |
Note that with some other web servers, such as NCSA httpd, setting |
182 |
up a directory tree for use with chroot() is complicated, involving |
183 |
creating a bunch of special directories and copying in various files. |
184 |
With thttpd it's a lot easier, all you have to do is make sure |
185 |
any shells, utilities, and config files used by your CGI programs and |
186 |
scripts are available. |
187 |
If you have CGI disabled, or if you make a policy that all CGI programs |
188 |
must be written in a compiled language such as C and statically linked, |
189 |
then you probably don't have to do any setup at all. |
190 |
.PP |
191 |
Relevant config.h option: ALWAYS_CHROOT. |
192 |
.SH "CGI" |
193 |
.PP |
194 |
thttpd supports the CGI 1.1 spec. |
195 |
.PP |
196 |
In order for a CGI program to be run, its name must match the pattern |
197 |
specified either at compile time or on the command line with the -c flag. |
198 |
This is a simple shell-style filename pattern. |
199 |
You can use * to match any string not including a slash, |
200 |
or ** to match any string including slashes, |
201 |
or ? to match any single character. |
202 |
You can also use multiple such patterns separated by |. |
203 |
The patterns get checked against the filename |
204 |
part of the incoming URL. |
205 |
Don't forget to quote any wildcard characters so that the shell doesn't |
206 |
mess with them. |
207 |
.PP |
208 |
Restricting CGI programs to a single directory lets the site administrator |
209 |
review them for security holes, and is strongly recommended. |
210 |
If there are individual users that you trust, you can enable their |
211 |
directories too. |
212 |
.PP |
213 |
If no CGI pattern is specified, neither here nor at compile time, |
214 |
then CGI programs cannot be run at all. |
215 |
If you want to disable CGI as a security measure, that's how you do it, just |
216 |
comment out the patterns in the config file and don't run with the -c flag. |
217 |
.PP |
218 |
Note: the current working directory when a CGI program gets run is |
219 |
the directory that the CGI program lives in. |
220 |
This isn't in the CGI 1.1 spec, but it's what most other HTTP servers do. |
221 |
.PP |
222 |
Relevant config.h options: CGI_PATTERN, CGI_TIMELIMIT, CGI_NICE, CGI_PATH, CGI_LD_LIBRARY_PATH, CGIBINDIR. |
223 |
.SH "BASIC AUTHENTICATION" |
224 |
.PP |
225 |
Basic Authentication is available as an option at compile time. |
226 |
If enabled, it uses a password file in the directory to be protected, |
227 |
called .htpasswd by default. |
228 |
This file is formatted as the familiar colon-separated |
229 |
username/encrypted-password pair, records delimited by newlines. |
230 |
The protection does not carry over to subdirectories. |
231 |
The utility program htpasswd(1) is included to help create and |
232 |
modify .htpasswd files. |
233 |
.PP |
234 |
Relevant config.h option: AUTH_FILE |
235 |
.SH "THROTTLING" |
236 |
.PP |
237 |
The throttle file lets you set maximum byte rates on URLs or URL groups. |
238 |
There is no provision for setting a maximum request rate throttle, |
239 |
because throttling a request uses as much cpu as handling it, so |
240 |
there would be no point. |
241 |
.PP |
242 |
The format of the throttle file is very simple. |
243 |
A # starts a comment, and the rest of the line is ignored. |
244 |
Blank lines are ignored. |
245 |
The rest of the lines should consist of a pattern, whitespace, and a number. |
246 |
The pattern is a simple shell-style filename pattern, using ?/**/*, or |
247 |
multiple such patterns separated by |. |
248 |
.PP |
249 |
The numbers in the file are byte rates, specified in units of bytes per second. |
250 |
For comparison, a v.32b/v.42b modem gives about 1500/2000 B/s |
251 |
depending on compression, a double-B-channel ISDN line about |
252 |
12800 B/s, and a T1 line is about 150000 B/s. |
253 |
.PP |
254 |
Example: |
255 |
.nf |
256 |
# throttle file for www.acme.com |
257 |
|
258 |
** 100000 # limit total web usage to 2/3 of our T1 |
259 |
**.jpg|**.gif 50000 # limit images to 1/3 of our T1 |
260 |
**.mpg 20000 # and movies to even less |
261 |
jef/** 20000 # jef's pages are too popular |
262 |
.fi |
263 |
.PP |
264 |
Throttling is implemented by checking each incoming URL filename against all |
265 |
of the patterns in the throttle file. |
266 |
The server accumulates statistics on how much bandwidth each pattern |
267 |
has accounted for recently (via a rolling average). |
268 |
If a URL matches a pattern that has been exceeding its specified limit, |
269 |
then the data returned is actually slowed down, with |
270 |
pauses between each block. |
271 |
If that's not possible (e.g. for CGI programs), then |
272 |
the server returns a special code saying 'try again later'. |
273 |
.SH "MULTIHOMING" |
274 |
.PP |
275 |
Multihoming means using one machine to serve multiple hostnames. |
276 |
For instance, if you're an internet provider and you want to let |
277 |
all of your customers have customized web addresses, you might |
278 |
have www.joe.acme.com, www.jane.acme.com, and your own www.acme.com, |
279 |
all running on the same physical hardware. |
280 |
This feature is also known as "virtual hosts". |
281 |
There are three steps to setting this up. |
282 |
.PP |
283 |
One, make DNS entries for all of the hostnames. |
284 |
The current way to do this, allowed by HTTP/1.1, is to use CNAME aliases, |
285 |
like so: |
286 |
.nf |
287 |
www.acme.com IN A 192.100.66.1 |
288 |
www.joe.acme.com IN CNAME www.acme.com |
289 |
www.jane.acme.com IN CNAME www.acme.com |
290 |
.fi |
291 |
However, this is incompatible with older HTTP/1.0 browsers. |
292 |
If you want to stay compatible, there's a different way - use A records |
293 |
instead, each with a different IP address, like so: |
294 |
.nf |
295 |
www.acme.com IN A 192.100.66.1 |
296 |
www.joe.acme.com IN A 192.100.66.200 |
297 |
www.jane.acme.com IN A 192.100.66.201 |
298 |
.fi |
299 |
This is bad because it uses extra IP addresses, a somewhat scarce resource. |
300 |
But if you want people with older browsers to be able to visit your |
301 |
sites, you still have to do it this way. |
302 |
.PP |
303 |
Step two. |
304 |
If you're using the modern CNAME method of multihoming, then you can |
305 |
skip this step. |
306 |
Otherwise, using the older multiple-IP-address method you |
307 |
must set up IP aliases or multiple interfaces for the extra addresses. |
308 |
You can use ifconfig(8)'s alias command to tell the machine to answer to |
309 |
all of the different IP addresses. |
310 |
Example: |
311 |
.nf |
312 |
ifconfig le0 www.acme.com |
313 |
ifconfig le0 www.joe.acme.com alias |
314 |
ifconfig le0 www.jane.acme.com alias |
315 |
.fi |
316 |
If your OS's version of ifconfig doesn't have an alias command, you're |
317 |
probably out of luck (but see http://www.acme.com/software/thttpd/notes.html). |
318 |
.PP |
319 |
Third and last, you must set up thttpd to handle the multiple hosts. |
320 |
The easiest way is with the -v flag, or the ALWAYS_VHOST config.h option. |
321 |
This works with either CNAME multihosting or multiple-IP multihosting. |
322 |
What it does is send each incoming request to a subdirectory based on the |
323 |
hostname it's intended for. |
324 |
All you have to do in order to set things up is to create those subdirectories |
325 |
in the directory where thttpd will run. |
326 |
With the example above, you'd do like so: |
327 |
.nf |
328 |
mkdir www.acme.com www.joe.acme.com www.jane.acme.com |
329 |
.fi |
330 |
If you're using old-style multiple-IP multihosting, you should also create |
331 |
symbolic links from the numeric addresses to the names, like so: |
332 |
.nf |
333 |
ln -s www.acme.com 192.100.66.1 |
334 |
ln -s www.joe.acme.com 192.100.66.200 |
335 |
ln -s www.jane.acme.com 192.100.66.201 |
336 |
.fi |
337 |
This lets the older HTTP/1.0 browsers find the right subdirectory. |
338 |
.PP |
339 |
There's an optional alternate step three if you're using multiple-IP |
340 |
multihosting: run a separate thttpd process for each hostname, using |
341 |
the -h flag to specify which one is which. |
342 |
This gives you more flexibility, since you can run each of these processes |
343 |
in separate directories, with different throttle files, etc. |
344 |
Example: |
345 |
.nf |
346 |
thttpd -r -d /usr/www -h www.acme.com |
347 |
thttpd -r -d /usr/www/joe -u joe -h www.joe.acme.com |
348 |
thttpd -r -d /usr/www/jane -u jane -h www.jane.acme.com |
349 |
.fi |
350 |
But remember, this multiple-process method does not work with CNAME |
351 |
multihosting - for that, you must use a single thttpd process with |
352 |
the -v flag. |
353 |
.SH "CUSTOM ERRORS" |
354 |
.PP |
355 |
thttpd lets you define your own custom error pages for the various |
356 |
HTTP errors. |
357 |
There's a separate file for each error number, all stored in one |
358 |
special directory. |
359 |
The directory name is "errors", at the top of the web directory tree. |
360 |
The error files should be named "errNNN.html", where NNN is the error number. |
361 |
So for example, to make a custom error page for the authentication failure |
362 |
error, which is number 401, you would put your HTML into the file |
363 |
"errors/err401.html". |
364 |
If no custom error file is found for a given error number, then the |
365 |
usual built-in error page is generated. |
366 |
.PP |
367 |
If you're using the virtual hosts option, you can also have different |
368 |
custom error pages for each different virtual host. |
369 |
In this case you put another "errors" directory in the top of that |
370 |
virtual host's web tree. |
371 |
thttpd will look first in the virtual host errors directory, and |
372 |
then in the server-wide errors directory, and if neither of those |
373 |
has an appropriate error file then it will generate the built-in error. |
374 |
.SH "NON-LOCAL REFERERS" |
375 |
.PP |
376 |
Sometimes another site on the net will embed your image files in their |
377 |
HTML files, which basically means they're stealing your bandwidth. |
378 |
You can prevent them from doing this by using non-local referer filtering. |
379 |
With this option, certain files can only be fetched via a local referer. |
380 |
The files have to be referenced by a local web page. |
381 |
If a web page on some other site references the files, that fetch will |
382 |
be blocked. |
383 |
There are three config-file variables for this feature: |
384 |
.TP |
385 |
.B urlpat |
386 |
A wildcard pattern for the URLs that should require a local referer. |
387 |
This is typically just image files, sound files, and so on. |
388 |
For example: |
389 |
.nf |
390 |
urlpat=**.jpg|**.gif|**.au|**.wav |
391 |
.fi |
392 |
For most sites, that one setting is all you need to enable referer filtering. |
393 |
.TP |
394 |
.B noemptyreferers |
395 |
By default, requests with no referer at all, or a null referer, or a |
396 |
referer with no apparent hostname, are allowed. |
397 |
With this variable set, such requests are disallowed. |
398 |
.TP |
399 |
.B localpat |
400 |
A wildcard pattern that specifies the local host or hosts. |
401 |
This is used to determine if the host in the referer is local or not. |
402 |
If not specified it defaults to the actual local hostname. |
403 |
.SH SYMLINKS |
404 |
.PP |
405 |
thttpd is very picky about symbolic links. |
406 |
Before delivering any file, it first checks each element in the path |
407 |
to see if it's a symbolic link, and expands them all out to get the final |
408 |
actual filename. |
409 |
Along the way it checks for things like links with ".." that go above |
410 |
the server's directory, and absolute symlinks (ones that start with a /). |
411 |
These are prohibited as security holes, so the server returns an |
412 |
error page for them. |
413 |
This means you can't set up your web directory with a bunch of symlinks |
414 |
pointing to individual users' home web directories. |
415 |
Instead you do it the other way around - the user web directories are |
416 |
real subdirs of the main web directory, and in each user's home |
417 |
dir there's a symlink pointing to their actual web dir. |
418 |
.PP |
419 |
The CGI pattern is also affected - it gets matched against the fully-expanded |
420 |
filename. So, if you have a single CGI directory but then put a symbolic |
421 |
link in it pointing somewhere else, that won't work. The CGI program will be |
422 |
treated as a regular file and returned to the client, instead of getting run. |
423 |
This could be confusing. |
424 |
.SH PERMISSIONS |
425 |
.PP |
426 |
thttpd is also picky about file permissions. |
427 |
It wants data files (HTML, images) to be world readable. |
428 |
Readable by the group that the thttpd process runs as is not enough - thttpd |
429 |
checks explicitly for the world-readable bit. |
430 |
This is so that no one ever gets surprised by a file that's not set |
431 |
world-readable and yet somehow is readable by the HTTP server and |
432 |
therefore the *whole* world. |
433 |
.PP |
434 |
The same logic applies to directories. |
435 |
As with the standard Unix "ls" program, thttpd will only let you |
436 |
look at the contents of a directory if its read bit is on; but |
437 |
as with data files, this must be the world-read bit, not just the |
438 |
group-read bit. |
439 |
.PP |
440 |
thttpd also wants the execute bit to be *off* for data files. |
441 |
A file that is marked executable but doesn't match the CGI pattern |
442 |
might be a script or program that got accidentally left in the |
443 |
wrong directory. |
444 |
Allowing people to fetch the contents of the file might be a security breach, |
445 |
so this is prohibited. |
446 |
Of course if an executable file *does* match the CGI pattern, then it |
447 |
just gets run as a CGI. |
448 |
.PP |
449 |
In summary, data files should be mode 644 (rw-r--r--), |
450 |
directories should be 755 (rwxr-xr-x) if you want to allow indexing and |
451 |
711 (rwx--x--x) to disallow it, and CGI programs should be mode |
452 |
755 (rwxr-xr-x) or 711 (rwx--x--x). |
453 |
.SH LOGS |
454 |
.PP |
455 |
thttpd does all of its logging via syslog(3). |
456 |
The facility it uses is configurable. |
457 |
Aside from error messages, there are only a few log entry types of interest, |
458 |
all fairly similar to CERN Common Log Format: |
459 |
.nf |
460 |
Aug 6 15:40:34 acme thttpd[583]: 165.113.207.103 - - "GET /file" 200 357 |
461 |
Aug 6 15:40:43 acme thttpd[583]: 165.113.207.103 - - "HEAD /file" 200 0 |
462 |
Aug 6 15:41:16 acme thttpd[583]: referer http://www.acme.com/ -> /dir |
463 |
Aug 6 15:41:16 acme thttpd[583]: user-agent Mozilla/1.1N |
464 |
.fi |
465 |
The package includes a script for translating these log entries info |
466 |
CERN-compatible files. |
467 |
Note that thttpd does not translate numeric IP addresses into domain names. |
468 |
This is both to save time and as a minor security measure (the numeric |
469 |
address is harder to spoof). |
470 |
.PP |
471 |
Relevant config.h option: LOG_FACILITY. |
472 |
.PP |
473 |
If you'd rather log directly to a file, you can use the -l command-line |
474 |
flag. But note that error messages still go to syslog. |
475 |
.SH SIGNALS |
476 |
.PP |
477 |
thttpd handles a couple of signals, which you can send via the |
478 |
standard Unix kill(1) command: |
479 |
.TP |
480 |
.B INT,TERM |
481 |
These signals tell thttpd to shut down immediately. |
482 |
Any requests in progress get aborted. |
483 |
.TP |
484 |
.B USR1 |
485 |
This signal tells thttpd to shut down as soon as it's done servicing |
486 |
all current requests. |
487 |
In addition, the network socket it uses to accept new connections gets |
488 |
closed immediately, which means a fresh thttpd can be started up |
489 |
immediately. |
490 |
.TP |
491 |
.B HUP |
492 |
This signal tells thttpd to close and re-open its (non-syslog) log file, |
493 |
for instance if you rotated the logs and want thttpd to start using the |
494 |
new one. |
495 |
However, this feature isn't actually that useful at the moment. |
496 |
The problem is that thttpd will generally be started as root, so that |
497 |
it can bind to port 80; then it gives up the root uid as soon as it can, |
498 |
for security reasons. |
499 |
But if you later send it a HUP, it will try to re-open the log file |
500 |
without root access and will generally fail. |
501 |
Also, if you're running inside a chroot tree, as you should be, |
502 |
the log file won't even be accessible. |
503 |
Currently the best alternative for log rotation is to send a USR1 signal, |
504 |
shutting down thttpd altogether, and then restart it. |
505 |
.SH "SEE ALSO" |
506 |
redirect(8), ssi(8), makeweb(1), htpasswd(1), syslogtocern(8), weblog_parse(1), http_get(1) |
507 |
.SH THANKS |
508 |
.PP |
509 |
Many thanks to contributors, reviewers, testers: |
510 |
John LoVerso, Jordan Hayes, Chris Torek, Jim Thompson, Barton Schaffer, |
511 |
Geoff Adams, Dan Kegel, John Hascall, Bennett Todd, KIKUCHI Takahiro, |
512 |
Catalin Ionescu. |
513 |
Special thanks to Craig Leres for substantial debugging and development, |
514 |
and for not complaining about my coding style very much. |
515 |
.SH AUTHOR |
516 |
Copyright © 1995,1998,1999,2000 by Jef Poskanzer <jef@acme.com>. |
517 |
All rights reserved. |
518 |
.\" Redistribution and use in source and binary forms, with or without |
519 |
.\" modification, are permitted provided that the following conditions |
520 |
.\" are met: |
521 |
.\" 1. Redistributions of source code must retain the above copyright |
522 |
.\" notice, this list of conditions and the following disclaimer. |
523 |
.\" 2. Redistributions in binary form must reproduce the above copyright |
524 |
.\" notice, this list of conditions and the following disclaimer in the |
525 |
.\" documentation and/or other materials provided with the distribution. |
526 |
.\" |
527 |
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
528 |
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
529 |
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
530 |
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
531 |
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
532 |
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
533 |
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
534 |
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
535 |
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
536 |
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
537 |
.\" SUCH DAMAGE. |