diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-09-13 09:43:21 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-09-13 09:43:21 -0700 |
commit | 5280f9a0cd1f9ba200422ebba65d1e0133410995 (patch) | |
tree | bf85ce4e320a769d7e0903ff52ccfde13a422666 /man2html | |
download | man-5280f9a0cd1f9ba200422ebba65d1e0133410995.tar.gz man-5280f9a0cd1f9ba200422ebba65d1e0133410995.tar.bz2 man-5280f9a0cd1f9ba200422ebba65d1e0133410995.zip |
Initial.man-1.6g
Diffstat (limited to 'man2html')
27 files changed, 6100 insertions, 0 deletions
diff --git a/man2html/Makefile b/man2html/Makefile new file mode 100644 index 0000000..ed1b981 --- /dev/null +++ b/man2html/Makefile @@ -0,0 +1,70 @@ +# +# Generated automatically from Makefile.in by the +# configure script. +# +CC = gcc -O +CFLAGS += -Wall -Wstrict-prototypes -Wmissing-prototypes +OBJECTS = man2html.o cgibase.o abbrev.o strdefs.o +EXEEXT = +bindir = $(DESTDIR)$(PREFIX)/usr/bin +mandir = $(DESTDIR)$(PREFIX)/usr/share/man +vardir = $(DESTDIR)$(PREFIX)/var +httpdir = $(DESTDIR)$(PREFIX)/home/httpd +cgiowner = nobody +cgigroup = nobody + +all: man2html$(EXEEXT) hman + +man2html$(EXEEXT): $(OBJECTS) + $(CC) $(LDFLAGS) -o man2html$(EXEEXT) $(OBJECTS) + +# man2html: ../src/version.h + +# This installs the man2html utility +install: man2html$(EXEEXT) + mkdir -p $(bindir) + install -m 755 man2html$(EXEEXT) $(bindir) + mkdir -p $(mandir)/man1 + install -m 644 man2html.1 $(mandir)/man1/man2html.1 + +install-scripts: install-man-scripts install-glimpse-stuff install-hman + +# These are the scripts that allow pointing a browser at +# http://localhost/cgi-bin/man/man2html +# to work. +install-man-scripts: + mkdir -p $(httpdir)/cgi-bin/man + mkdir -p $(httpdir)/cgi-aux/man + install -m 755 scripts/cgi-bin/man/* $(httpdir)/cgi-bin/man + install -m 644 scripts/cgi-aux/man/* $(httpdir)/cgi-aux/man + install -d -o $(cgiowner) -g $(cgigroup) -m 775 $(vardir)/man2html +# (aux was renamed to cgi-aux since aux causes problems under DOS) + +# If you have installed glimpse, and have compressed man pages, +# then perhaps you also want these filters. +install-glimpse-stuff: + install -m 644 glimpse_filters $(vardir)/man2html/.glimpse_filters + +# In order not to have to type a long command like +# netscape http://localhost/cgi-bin/man/man2html?section+topic +# or +# lynx lynxcgi:/home/httpd/cgi-bin/man/man2html?section+topic +# it is convenient to have some shell script as a wrapper. +# The script hman can be aliased to man. It uses an environment +# variable MANHTMLPAGER to find out which browser you use, and +# you can set MANHTMLHOST if the pages are not on localhost. +hman: hman.sh + rm -f hman + sed -e 's,%version%,man-1.6g,' hman.sh > hman + +install-hman: hman + install -m 555 hman $(bindir)/hman + install -m 644 hman.1 $(mandir)/man1/hman.1 + +clean: + rm -f core hman man2html$(EXEEXT) $(OBJECTS) *~ + +spotless: clean + rm -f Makefile + +$(OBJECTS): defs.h diff --git a/man2html/Makefile.in b/man2html/Makefile.in new file mode 100644 index 0000000..b41eaba --- /dev/null +++ b/man2html/Makefile.in @@ -0,0 +1,66 @@ +CC = @CC@ +CFLAGS += -Wall -Wstrict-prototypes -Wmissing-prototypes +OBJECTS = man2html.o cgibase.o abbrev.o strdefs.o +EXEEXT = @EXEEXT@ +bindir = $(DESTDIR)$(PREFIX)/usr/bin +mandir = $(DESTDIR)$(PREFIX)@mandir@ +vardir = $(DESTDIR)$(PREFIX)/var +httpdir = $(DESTDIR)$(PREFIX)/home/httpd +cgiowner = nobody +cgigroup = nobody + +all: man2html$(EXEEXT) hman + +man2html$(EXEEXT): $(OBJECTS) + $(CC) $(LDFLAGS) -o man2html$(EXEEXT) $(OBJECTS) + +# man2html: ../src/version.h + +# This installs the man2html utility +install: man2html$(EXEEXT) + mkdir -p $(bindir) + install -m 755 man2html$(EXEEXT) $(bindir) + mkdir -p $(mandir)/man1 + install -m 644 man2html.1 $(mandir)/man1/man2html.@man1ext@ + +install-scripts: install-man-scripts install-glimpse-stuff install-hman + +# These are the scripts that allow pointing a browser at +# http://localhost/cgi-bin/man/man2html +# to work. +install-man-scripts: + mkdir -p $(httpdir)/cgi-bin/man + mkdir -p $(httpdir)/cgi-aux/man + install -m 755 scripts/cgi-bin/man/* $(httpdir)/cgi-bin/man + install -m 644 scripts/cgi-aux/man/* $(httpdir)/cgi-aux/man + install -d -o $(cgiowner) -g $(cgigroup) -m 775 $(vardir)/man2html +# (aux was renamed to cgi-aux since aux causes problems under DOS) + +# If you have installed glimpse, and have compressed man pages, +# then perhaps you also want these filters. +install-glimpse-stuff: + install -m 644 glimpse_filters $(vardir)/man2html/.glimpse_filters + +# In order not to have to type a long command like +# netscape http://localhost/cgi-bin/man/man2html?section+topic +# or +# lynx lynxcgi:/home/httpd/cgi-bin/man/man2html?section+topic +# it is convenient to have some shell script as a wrapper. +# The script hman can be aliased to man. It uses an environment +# variable MANHTMLPAGER to find out which browser you use, and +# you can set MANHTMLHOST if the pages are not on localhost. +hman: hman.sh + rm -f hman + sed -e 's,%version%,@version@,' hman.sh > hman + +install-hman: hman + install -m 555 hman $(bindir)/hman + install -m 644 hman.1 $(mandir)/man1/hman.@man1ext@ + +clean: + rm -f core hman man2html$(EXEEXT) $(OBJECTS) *~ + +spotless: clean + rm -f Makefile + +$(OBJECTS): defs.h diff --git a/man2html/README b/man2html/README new file mode 100644 index 0000000..6dabd52 --- /dev/null +++ b/man2html/README @@ -0,0 +1,91 @@ +This directory contains the following. + +1. man2html + +This is a pure manroff -> html converter. +No manpath search etc. + +Call: man2html [-l | -H host.domain:port] [filename] + +The contents of FILENAME (or STDIN, in case FILENAME is "-" or absent) +are converted from man-style nroff to html, and printed on STDOUT. + +With "-l" URLs of the form "lynxcgi:/home/httpd/cgi-bin/..." are generated. +With "-H host" we make URLs of the form "http://host/cgi-bin/...". +The default is "http://localhost/cgi-bin/...". + +2. A collection of scripts + +This part is not installed by "make install" of the global Makefile. +There are security considerations: it is very unlikely that these +scripts (still in alpha) are secure, so for the time being they +should only be used where security is not a major concern. + +If you are not afraid, or are not running a httpd, do +"make install-scripts" in this directory. +This does three things: install man stuff, install glimpse stuff, +and install user interface stuff. + +2A. man stuff + +This first part (that can be done separately with "make install-man-scripts") +puts various scripts under /home/httpd/cgi-bin and /home/httpd/cgi-aux +in a subdirectory man. +It will create a directory /var/man2html to hold the indices. +(This directory should be writable by the cgi scripts; +probably that means that the owner should be nobody. +Choose a group and add all non-httpd users that should be +able to write this directory to that group.) + +Structure of the collection of scripts: + man2html is the main script. + It uses man.aux when called without arguments. + It uses manwhatis when asked for an index of manpages+descriptions. + It uses mansec when asked for a compact index of manpages. + It uses mansearch when asked for a glimpse search. + In its turn mansearch uses mansearch.aux when called + without arguments. It uses mansearchhelp (which uses + mansearchhelp.aux) when asked for help. + +2B. glimpse stuff +The second part (that can be done separately with +"make install-glimpse-stuff") installs .glimpse_filters +in /var/man2html, in order to tell glimpse what decompressors to use. + +2C. user interface stuff +The third part (that can be done separately with "make install-hman") +installs a user interface to these scripts in /usr/bin/hman. +Now people can say + alias man=/usr/bin/hman +and have a man that uses a html browser. +The browser is chosen via environment variables - look at the script. + +3. Glimpse. + +For the glimpse part, I quote Michael Hamilton: +---------------------------------------------------------------------- +To use the Glimpse full text searching, you will need to install +glimpse in /usr/bin. Redhat rpm users can get glimpse from + + ftp://ftp.redhat.com/pub/contrib/i386/glimpse-4.0-6.i386.rpm + +The glimpse home ftp site is cs.arizona.edu. N.B. glimpse is not +freely redistributable for commercial use, I'd be very interested in a +more liberal alternative. Having installed glimpse, you will need to +build a glimpse index in /var/man2html. This doesn't take too long - +about 3 minutes on my 486DX2/66 16MB machine. As root do: + + /usr/bin/glimpseindex -z -H /var/man2html /usr/man/man* /usr/X11R6/man/man* \ + /usr/local/man/man* /opt/man/man* + chmod ugo+r /var/man2html/.glimpse* + +The -z option causes glimpse to apply any filters (for decompression etc) +specified in /var/man2html/.glimpse_filters. + +This could be set up as a cron job in /etc/crontab, e.g. (the following +must be all on one line): + + 21 04 * * 1 root /usr/bin/glimpseindex -z -H /var/man2html /usr/man/man* + /usr/X11R6/man/man* /usr/local/man/man* /opt/man/man* ; + chmod +r /var/man2html/.glimpse* +-------------------------------------------------------------------------- diff --git a/man2html/TODO b/man2html/TODO new file mode 100644 index 0000000..b0101ad --- /dev/null +++ b/man2html/TODO @@ -0,0 +1,43 @@ +There are still many problems with man2html. +Partly these are caused by the imprecise definition +of the man file format. (And the many buggy man pages.) +Partly by the incomplete implementation of the man/doc macro packages. +Partly by the imperfect emulation of troff. +Partly by the variation between various browsers in the +accepted html. +Partly just because man2html is buggy. + +Of course in reality a man2html converter must contain +large parts of the troff source, so that it can be fed +with the defining macro packages and always do the right thing. + +On a RedHat 5.0 system: +- /usr/man/mann/DirDlg.n is not formatted correctly. + (It does not start with .TH) +- <i>bug_readline</i>@<i>prep.ai.mit.edu</i> does not generate + a mailto: link. It should generate + <a href="mailto:bug_readline@prep.ai.mit.edu> + <i>bug_readline</i>@<i>prep.ai.mit.edu</i> + </a> + but this requires parsing of the surrounding html markup. + Easy, but not done yet. +- Some manpages generate bad whatis information + [where the name in the whatis line is not the filename of the man page]. + (E.g., tc589_cs.4, auto.master.5, pcmcia.5, proc.5 and autofs.8 + generate whatis lines + 3c589_cs (4) - 3Com 3c589 Etherlink III device driver + /etc/auto.master (5) - Master Map for automounter + /etc/init.d/rc.d/autofs (8) - Control Script for automounter + /etc/pcmcia/config (5) - PCMCIA card configuration database + /proc (5) - process information pseudo-filesystem + ) + As a consequence, the corresponding manwhatis links are bad. +- Some manpages have bad .so information. + (E.g., TIFFScanlineSize.3t contains .so TIFFsize.3t + instead of .so man3/TIFFsize.3t .) + This also confuses whatis, and generates bad links. + (But right now these happen to work.) + +Of course, patches are welcome! + + diff --git a/man2html/abbrev.c b/man2html/abbrev.c new file mode 100644 index 0000000..fa7df06 --- /dev/null +++ b/man2html/abbrev.c @@ -0,0 +1,62 @@ +#include <string.h> +#include "defs.h" +/* + * lookup_abbrev() is used for TX macros - is that + * something SUN-specific? + */ + +char *abbrev_list[] = { + "GSBG", "Getting Started ", + "SUBG", "Customizing SunOS", + "SHBG", "Basic Troubleshooting", + "SVBG", "SunView User's Guide", + "MMBG", "Mail and Messages", + "DMBG", "Doing More with SunOS", + "UNBG", "Using the Network", + "GDBG", "Games, Demos & Other Pursuits", + "CHANGE", "SunOS 4.1 Release Manual", + "INSTALL", "Installing SunOS 4.1", + "ADMIN", "System and Network Administration", + "SECUR", "Security Features Guide", + "PROM", "PROM User's Manual", + "DIAG", "Sun System Diagnostics", + "SUNDIAG", "Sundiag User's Guide", + "MANPAGES", "SunOS Reference Manual", + "REFMAN", "SunOS Reference Manual", + "SSI", "Sun System Introduction", + "SSO", "System Services Overview", + "TEXT", "Editing Text Files", + "DOCS", "Formatting Documents", + "TROFF", "Using <B>nroff</B> and <B>troff</B>", + "INDEX", "Global Index", + "CPG", "C Programmer's Guide", + "CREF", "C Reference Manual", + "ASSY", "Assembly Language Reference", + "PUL", "Programming Utilities and Libraries", + "DEBUG", "Debugging Tools", + "NETP", "Network Programming", + "DRIVER", "Writing Device Drivers", + "STREAMS", "STREAMS Programming", + "SBDK", "SBus Developer's Kit", + "WDDS", "Writing Device Drivers for the SBus", + "FPOINT", "Floating-Point Programmer's Guide", + "SVPG", "SunView 1 Programmer's Guide", + "SVSPG", "SunView 1 System Programmer's Guide", + "PIXRCT", "Pixrect Reference Manual", + "CGI", "SunCGI Reference Manual", + "CORE", "SunCore Reference Manual", + "4ASSY", "Sun-4 Assembly Language Reference", + "SARCH", "<FONT SIZE=\"-1\">SPARC</FONT> Architecture Manual", + "KR", "The C Programming Language", + 0, 0 }; + +char *lookup_abbrev (char *s) +{ + int i=0; + + if (!s) + return ""; + while (abbrev_list[i] && strcmp(s, abbrev_list[i])) + i = i+2; + return abbrev_list[i] ? abbrev_list[i+1] : s; +} diff --git a/man2html/cgibase.c b/man2html/cgibase.c new file mode 100644 index 0000000..de31cdf --- /dev/null +++ b/man2html/cgibase.c @@ -0,0 +1,143 @@ +/* + * Here are the routines of man2html that output a HREF string. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <ctype.h> /* tolower() */ +#include <string.h> /* strlen() */ +#include "defs.h" + +/* + * The default is to use cgibase. With relative html style + * we generate URLs of the form "../manX/page.html". + */ +static int relat_html_style = 0; + +/* + * Either the user is non-local (or local, but using httpd), + * in which case we use http:/cgi-bin, or the user is local + * and uses lynx, and we use lynxcgi:/home/httpd/cgi-bin. + */ + +static char *man2htmlpath = "/cgi-bin/man/man2html"; /* default */ +static char *cgibase_format = "http://%s"; /* host.domain:port */ +static char *cgibase_ll_format = "lynxcgi:%s"; /* directory */ +static char *cgibase = "http://localhost"; /* default */ + +/* + * Separator between URL and argument string. + * + * With http:<path to script>/a/b?c+d+e the script is called + * with PATH_INFO=/a/b and QUERY_STRING=c+d+e and args $1=c, $2=d, $3=e. + * With lynxcgi:<full path to script>?c+d+e no PATH_INFO is possible. + */ +static char sep = '?'; /* or '/' */ + +void +set_separator(char s) { + sep = s; +} + +void +set_lynxcgibase(char *s) { + int n = strlen(cgibase_ll_format) + strlen(s); + char *t = (char *) xmalloc(n); + + sprintf(t, cgibase_ll_format, s); + cgibase = t; +} + +void +set_cgibase(char *s) { + int n = strlen(cgibase_format) + strlen(s); + char *t = (char *) xmalloc(n); + + sprintf(t, cgibase_format, s); + cgibase = t; +} + +void +set_man2htmlpath(char *s) { + man2htmlpath = xstrdup(s); +} + +void +set_relative_html_links(void) { + relat_html_style = 1; +} + +/* What shall we say in case of relat_html_style? */ +static char *signature = "<HR>\n" +"This document was created by\n" +"<A HREF=\"%s%s\">man2html</A>,\n" +"using the manual pages.<BR>\n" +"%s\n"; + +#define TIMEFORMAT "%T GMT, %B %d, %Y" +#define TIMEBUFSZ 500 + +void print_sig() +{ + char timebuf[TIMEBUFSZ]; + struct tm *timetm; + time_t clock; + + timebuf[0] = 0; +#ifdef TIMEFORMAT + sprintf(timebuf, "Time: "); + clock=time(NULL); + timetm=gmtime(&clock); + strftime(timebuf+6, TIMEBUFSZ-6, TIMEFORMAT, timetm); + timebuf[TIMEBUFSZ-1] = 0; +#endif + printf(signature, cgibase, man2htmlpath, timebuf); +} + +void +include_file_html(char *g) { + printf("<A HREF=\"file:/usr/include/%s\">%s</A>>", g,g); +} + +void +man_page_html(char *sec, char *h) { + if (relat_html_style) { + if (!h) + printf("<A HREF=\"../index.html\">" + "Return to Main Contents</A>"); + else + printf("<A HREF=\"../man%s/%s.%s.html\">%s</A>", + sec, h, sec, h); + } else { + if (!h) + printf("<A HREF=\"%s%s\">Return to Main Contents</A>", + cgibase, man2htmlpath); + else if (!sec) + printf("<A HREF=\"%s%s%c%s\">%s</A>", + cgibase, man2htmlpath, sep, h, h); + else + printf("<A HREF=\"%s%s%c%s+%s\">%s</A>", + cgibase, man2htmlpath, sep, sec, h, h); + } +} + +void +ftp_html(char *f) { + printf("<A HREF=\"ftp://%s\">%s</A>", f, f); +} + +void +www_html(char *f) { + printf("<A HREF=\"http://%s\">%s</A>", f, f); +} + +void +mailto_html(char *g) { + printf("<A HREF=\"mailto:%s\">%s</A>", g, g); +} + +void +url_html(char *g) { + printf("<A HREF=\"%s\">%s</A>", g, g); +} diff --git a/man2html/defs.h b/man2html/defs.h new file mode 100644 index 0000000..f3e75ef --- /dev/null +++ b/man2html/defs.h @@ -0,0 +1,41 @@ +extern int nroff; +extern int local_lynx; + +typedef struct STRDEF STRDEF; +struct STRDEF { + int nr,slen; + char *st; + STRDEF *next; +}; + +typedef struct INTDEF INTDEF; +struct INTDEF { + int nr; + int val; + int incr; + INTDEF *next; +}; + +extern STRDEF *chardef, *strdef, *defdef; +extern INTDEF *intdef; + +#define V(A,B) ((A)*256+(B)) + +#include <sys/types.h> +extern void stdinit(void); +extern void print_sig(void); +extern char *lookup_abbrev(char *); +extern void include_file_html(char *); +extern void man_page_html(char*, char *); +extern void ftp_html(char *); +extern void www_html(char *); +extern void mailto_html(char *); +extern void url_html(char *); +extern void set_separator(char); +extern void set_lynxcgibase(char *); +extern void set_cgibase(char *); +extern void set_man2htmlpath(char *); +extern void set_relative_html_links(void); +extern void *xmalloc(size_t size); +extern void *xrealloc(void *ptr, size_t size); +extern char *xstrdup(const char *s); diff --git a/man2html/glimpse_filters b/man2html/glimpse_filters new file mode 100644 index 0000000..1814e5d --- /dev/null +++ b/man2html/glimpse_filters @@ -0,0 +1,3 @@ +*.gz gzip -d -c +*.Z gzip -d -c + diff --git a/man2html/hman b/man2html/hman new file mode 100644 index 0000000..9426c0d --- /dev/null +++ b/man2html/hman @@ -0,0 +1,96 @@ +#!/bin/sh +# +# hman - interface to the man2html scripts +# +# Michael Hamilton <michael@actrix.gen.nz>, Apr 1996 +# Andries Brouwer <aeb@cwi.nl>, Jan 1998. +# +# Usage examples: +# hman - get start page +# hman man2html - get man page for man2html +# hman 7 locale - get section 7 man page for locale +# hman 1 - section 1 index of names only +# hman 3 index - section 3 index names+descriptions +# hman -k editor - search all man pages for some string +# hman -P arena ./twm.man - specify browser; specify man page +# +# hman from man-1.6g +# + +if [ x"$1" = x"-v" -o x"$1" = x"-V" ]; then + echo "`basename $0` from man-1.6g" + exit 0 +fi + +# The user has to set MANHTMLPAGER (or he will get httpd-free lynx). +# Pick your favorite browser: lynx, xmosaic, netscape, arena, amaya, grail, ... +BROWSER=${MANHTMLPAGER-lynxcgi} +# +# If the man pages are on a remote host, specify it in MANHTMLHOST. +HOST=${MANHTMLHOST-localhost} + +# Perhaps the browser was specified on the command line? +if [ $# -gt 1 -a "$1" = "-P" ]; then + BROWSER="$2" + shift; shift +fi + +# Perhaps the host was specified on the command line? +if [ $# -gt 1 -a "$1" = "-H" ]; then + HOST="$2" + shift; shift +fi + +# Interface to a live (already running) netscape browser. +function nsfunc () { + if ( /bin/ps xc | grep -q 'netscape$' ) ; then + if [ -x netscape-remote ] ; then + exec netscape-remote -remote "openURL($1,new_window)" + else + exec netscape -remote "openURL($1,new_window)" + fi + else + netscape $1 & + fi +} + +case $BROWSER in + lynxcgi) + BROWSER=lynx + CG="lynxcgi:/home/httpd/cgi-bin/man" + ;; + netscape) + BROWSER=nsfunc + CG="http://$HOST/cgi-bin/man" + ;; + *) + CG="http://$HOST/cgi-bin/man" + ;; +esac + + case $# in + 0) $BROWSER $CG/man2html ;; + 1) case "$1" in + 1|2|3|4|5|6|7|8|l|n) + $BROWSER "$CG/mansec?$CG+$1" ;; + /*) + $BROWSER "$CG/man2html?$1" ;; + */*) + $BROWSER "$CG/man2html?$PWD/$1" ;; + *) + $BROWSER "$CG/man2html?$1" ;; + esac ;; + 2) case "$1" in + -k) + $BROWSER "$CG/mansearch?$2" ;; + *) + if [ "$2" = index ]; then + $BROWSER "$CG/manwhatis?$CG+$1" + else + $BROWSER "$CG/man2html?$1+$2" + fi ;; + esac ;; + *) echo "bad number of args" ;; + esac + +exit 0 diff --git a/man2html/hman.1 b/man2html/hman.1 new file mode 100644 index 0000000..4676f55 --- /dev/null +++ b/man2html/hman.1 @@ -0,0 +1,69 @@ +.\" Copyright (c) 1998 Andries Brouwer +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.TH hman 1 "19 January 1998" +.LO 1 +.SH NAME +hman \- browse the on-line manual pages +.SH SYNOPSIS +.B hman +[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] \fIname\fP +.br +.B hman +[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] [ index ] +.SH DESCRIPTION +The +.B hman +script is an interface to man2html(1) that allows you to enter man page +requests at the command line and view the output in your favourite +browser. +The behaviour reminds of that of +.BR man (1) +so that many people will be able to alias +.B hman +to +.BR man . +If the browser used is netscape, and an incarnation of netscape +is running already, +.B hman +will pass the request to the existing browser. + +.SH OPTIONS +.TP +.B \-\^P " browser" +Specify which browser (like lynx, xmosaic, arena, chimera, +netscape, amaya, ...) to use. +This option overrides the +.B MANHTMLPAGER +environment variable. +The default is the non-httpd version of +.BR lynx . +.TP +.B \-\^H " host" +Specify from what host to get the man pages. +This option overrides the +.B MANHTMLHOST +environment variable. +The default is +.BR localhost . + +.SH ENVIRONMENT +.TP +MANHTMLPAGER +The default browser to use is selected using this environment variable. +.TP +MANHTMLHOST +The default host to use is selected using this environment variable. + +.SH "SEE ALSO" +.BR man (1), +.BR man2html (1), +.BR arena (1), +.BR lynx (1), +.BR netscape (1), +.BR xmosaic (1), +.BR glimpse (1) + +http://www.mcom.com/newsref/std/x-remote.html diff --git a/man2html/hman.sh b/man2html/hman.sh new file mode 100755 index 0000000..c484acc --- /dev/null +++ b/man2html/hman.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# +# hman - interface to the man2html scripts +# +# Michael Hamilton <michael@actrix.gen.nz>, Apr 1996 +# Andries Brouwer <aeb@cwi.nl>, Jan 1998. +# +# Usage examples: +# hman - get start page +# hman man2html - get man page for man2html +# hman 7 locale - get section 7 man page for locale +# hman 1 - section 1 index of names only +# hman 3 index - section 3 index names+descriptions +# hman -k editor - search all man pages for some string +# hman -P arena ./twm.man - specify browser; specify man page +# +# hman from %version% +# + +if [ x"$1" = x"-v" -o x"$1" = x"-V" ]; then + echo "`basename $0` from %version%" + exit 0 +fi + +# The user has to set MANHTMLPAGER (or he will get httpd-free lynx). +# Pick your favorite browser: lynx, xmosaic, netscape, arena, amaya, grail, ... +BROWSER=${MANHTMLPAGER-lynxcgi} +# +# If the man pages are on a remote host, specify it in MANHTMLHOST. +HOST=${MANHTMLHOST-localhost} + +# Perhaps the browser was specified on the command line? +if [ $# -gt 1 -a "$1" = "-P" ]; then + BROWSER="$2" + shift; shift +fi + +# Perhaps the host was specified on the command line? +if [ $# -gt 1 -a "$1" = "-H" ]; then + HOST="$2" + shift; shift +fi + +# Interface to a live (already running) netscape browser. +function nsfunc () { + if ( /bin/ps xc | grep -q 'netscape$' ) ; then + if [ -x netscape-remote ] ; then + exec netscape-remote -remote "openURL($1,new_window)" + else + exec netscape -remote "openURL($1,new_window)" + fi + else + netscape $1 & + fi +} + +case $BROWSER in + lynxcgi) + BROWSER=lynx + CG="lynxcgi:/home/httpd/cgi-bin/man" + ;; + netscape) + BROWSER=nsfunc + CG="http://$HOST/cgi-bin/man" + ;; + *) + CG="http://$HOST/cgi-bin/man" + ;; +esac + + case $# in + 0) $BROWSER $CG/man2html ;; + 1) case "$1" in + 1|2|3|4|5|6|7|8|l|n) + $BROWSER "$CG/mansec?$CG+$1" ;; + /*) + $BROWSER "$CG/man2html?$1" ;; + */*) + $BROWSER "$CG/man2html?$PWD/$1" ;; + *) + $BROWSER "$CG/man2html?$1" ;; + esac ;; + 2) case "$1" in + -k) + $BROWSER "$CG/mansearch?$2" ;; + *) + if [ "$2" = index ]; then + $BROWSER "$CG/manwhatis?$CG+$1" + else + $BROWSER "$CG/man2html?$1+$2" + fi ;; + esac ;; + *) echo "bad number of args" ;; + esac + +exit 0 diff --git a/man2html/locales/en/hman.1 b/man2html/locales/en/hman.1 new file mode 100644 index 0000000..4676f55 --- /dev/null +++ b/man2html/locales/en/hman.1 @@ -0,0 +1,69 @@ +.\" Copyright (c) 1998 Andries Brouwer +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the README file that comes with the man 1.0 +.\" distribution. +.TH hman 1 "19 January 1998" +.LO 1 +.SH NAME +hman \- browse the on-line manual pages +.SH SYNOPSIS +.B hman +[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] \fIname\fP +.br +.B hman +[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] [ index ] +.SH DESCRIPTION +The +.B hman +script is an interface to man2html(1) that allows you to enter man page +requests at the command line and view the output in your favourite +browser. +The behaviour reminds of that of +.BR man (1) +so that many people will be able to alias +.B hman +to +.BR man . +If the browser used is netscape, and an incarnation of netscape +is running already, +.B hman +will pass the request to the existing browser. + +.SH OPTIONS +.TP +.B \-\^P " browser" +Specify which browser (like lynx, xmosaic, arena, chimera, +netscape, amaya, ...) to use. +This option overrides the +.B MANHTMLPAGER +environment variable. +The default is the non-httpd version of +.BR lynx . +.TP +.B \-\^H " host" +Specify from what host to get the man pages. +This option overrides the +.B MANHTMLHOST +environment variable. +The default is +.BR localhost . + +.SH ENVIRONMENT +.TP +MANHTMLPAGER +The default browser to use is selected using this environment variable. +.TP +MANHTMLHOST +The default host to use is selected using this environment variable. + +.SH "SEE ALSO" +.BR man (1), +.BR man2html (1), +.BR arena (1), +.BR lynx (1), +.BR netscape (1), +.BR xmosaic (1), +.BR glimpse (1) + +http://www.mcom.com/newsref/std/x-remote.html diff --git a/man2html/locales/en/man2html.1 b/man2html/locales/en/man2html.1 new file mode 100644 index 0000000..c1c25b3 --- /dev/null +++ b/man2html/locales/en/man2html.1 @@ -0,0 +1,151 @@ +'\" t +.\" Man page for man2html +.\" aeb, 980101 +.\" +.TH man2html 1 "1 January 1998" +.LO 1 +.SH NAME +man2html \- format a manual page in html +.SH SYNOPSIS +man2html [options] [file] +.SH DESCRIPTION +.B man2html +converts a manual page as found in +.I file +(or stdin, in case no file argument, or the argument "-", is given) +from man-style nroff into html, and prints the result on stdout. +It does support tbl but does not know about eqn. +The exit status is 0. If something goes wrong, +an error page is printed on stdout. + +This can be used as a stand-alone utility, but is mainly intended +as an auxiliary, to enable users to browse their man pages using +a html browser like +.BR lynx (1), +.BR xmosaic (1) +or +.BR netscape (1). +./" (See +./" .BR man (1) +./" for info on how to browse man pages via +./" .BR man2html . +./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx" +./" in the environment.) + +The main part of +.B man2html +is the troff-to-html engine written by Richard Verhoeven (rcb5@win.tue.nl). +It adds hyperlinks for the following constructs: +.LP +.TS +l l. +foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo" +method://string "method://string" +www.host.name "http://www.host.name" +ftp.host.name "ftp://ftp.host.name" +name@host "mailto:name@host" +<string.h> "file:/usr/include/string.h" +.TE +.LP +(The first of these can be tuned by options - see below.) +No lookup is done - the links generated need not exist. +Also an index with internal hyperlinks to the various sections +is generated, so that it is easier to find one's way +in large man pages like +.BR bash (1). + +.SH OPTIONS +When reading from stdin, it is not always clear how to +do .so expansion. The \-D option allows a script to define +the working directory. +.LP +.TP +.B \-\^D pathname +Strip the last two parts from the pathname, and do a +\fIchdir\fP(\fIdir\fP) before starting the conversion. +.LP +The \-E option allows the easy generation of error messages +from a cgi script. +.LP +.TP +.B \-\^E string +Output an error page containing the given error message. +.LP +The general form of a hyperlink generated for a man page reference is +.IP +<method:cgipath><man2htmlpath><separator><manpage> +.LP +with a default as shown above. The parts of this hyperlink +are set using the various options. +.TP +.B \-\^h +Set method:cgipath to http://localhost. This is the default. +.TP +.BI \-\^H " host[.domain][:port]" +Set method:cgipath to +.RI http:// host.domain:port . +.TP +.B \-\^l +Set method:cgipath to +.RI lynxcgi: /home/httpd . +.TP +.BI \-\^L " dir" +Set method:cgipath to +.RI lynxcgi: dir . +.TP +.BI \-\^M " man2htmlpath" +Set the man2htmlpath to use. The default is +.IR /cgi-bin/man/man2html . +.TP +.B \-\^p +Set separator to '/'. +.TP +.B \-\^q +Set separator to '?'. This is the default. +.TP +.B \-\^r +Use relative html paths, instead of cgi-bin paths. +.LP +On a machine without running +.BR httpd , +one can use +.B lynx +to browse the man pages, using the lynxcgi method. +When some http daemon is running, lynx, or any other browser, +can be used to browse the man pages, using the http method. +The option \-l (for `lynxcgi') selects the former behaviour. +With it, the default cgipath is \fI/home/httpd\fP. + +In general, a cgi script can be called by +.IP +<path_to_script>/<more_path>?<query> +.LP +and the environment variables PATH_INFO and QUERY_STRING +will be set to <more_path> and <query>, respectively. +Since lynxcgi does not handle the PATH_INFO part, we generate +hyperlinks with `?' as a separator by default. +The option \-p (for `path') selects '/' as a separator, while +the option \-q (for `query') selects '?' as a separator. + +The option \-H \fIhost\fP will specify the host to use +(instead of \fIlocalhost\fP). A cgi script could use +.IP +man2html -H $SERVER_NAME +.LP +if the variable SERVER_NAME is set. This would allow your machine +to act as a server and export man pages. + +.SH BUGS +There are many heuristics. The output will not always be perfect. +The lynxcgi method will not work if lynx was compiled without +selecting support for it. There may be problems with security. + +.SH AUTHOR +Richard Verhoeven was the original author of +.BR "man2html" . +Michael Hamilton and Andries Brouwer subsequently improved on it. +Federico Lucifredi <flucifredi@acm.org> is the current maintainer. + +.SH "SEE ALSO" +.BR lynx (1), +.BR man (1) diff --git a/man2html/locales/fr/man2html.1 b/man2html/locales/fr/man2html.1 new file mode 100644 index 0000000..1e99cd8 --- /dev/null +++ b/man2html/locales/fr/man2html.1 @@ -0,0 +1,165 @@ +'\" t +.\" Man page for man2html +.\" aeb, 980101 +.\" +.TH man2html 1 "1er janvier 1998" "Manuel Linux" "Commandes utilisateur" +.LO 1 +.SH NOM +man2html \- formate une page de manuel en html +.SH SYNOPSIS +man2html [options] [fichier] +.SH DESCRIPTION +.B man2html +convertit une page de manuel telle que trouvée dans +.I fichier +(ou l'entrée standard stdin si aucun argument fichier n'est donné +ou si l'argument «\ -\ » est donné) à partir du format nroff +(celui des pages de manuels) vers un format html et affiche le résultat +sur la sortie standard (stdout). +.B man2html +supporte +.BR tbl (1) +mais ne connaît rien à propos de +.BR eqn (1). +Le code de sortie est 0. Si quelque chose va mal, une page d'erreur +est affichée sur la sortie standard stdout. + +Cette commande peut être utilisée seule mais a été principalement conçue pour +être un auxiliaire afin que les utilisateurs puissent naviguer dans les pages +de manuel avec un navigateur html comme +.BR lynx (1), +.BR xmosaic (1) +ou +.BR netscape (1). +./" (See +./" .BR man (1) +./" for info on how to browse man pages via +./" .BR man2html . +./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx" +./" in the environment.) + +La plus grande partie de +.B man2html +est l'engin «\ troff-vers-html\ » écrit par Richard Verhoeven (rcb5@win.tue.nl). +Il ajoute des hyperliens aux constructions suivantes\ : +.LP +.TS +l l. +foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo" +method://string "method://string" +www.host.name "http://www.host.name" +ftp.host.name "ftp://ftp.host.name" +name@host "mailto:name@host" +<string.h> "file:/usr/include/string.h" +.TE +.LP +(La première de celles\-ci peut être ajustée par des options - voir plus loin.) +Aucune consultation n'est effectuée - les liens générés n'ont pas besoin +d'exister. Un index avec des hyperliens internes vers les diverses +sections est également créé rendant plus facile la navigation dans les grandes +pages comme +.BR bash (1). + +.SH OPTIONS +Lorsqu'on lit à partir de stdin, il n'est pas toujours évident de savoir +comment se fait l'expansion .so. L'option \-D permet à un script de définir +le répertoire de travail. +.LP +.TP +.B \-\^D chemin +Retire les deux derniers éléments du chemin et effectue un changement +de répertoire courant \fIchdir\fP(\fIdir\fP) avant de débuter la conversion. +.LP +L'option \-E option facilite la production de messages d'erreurs à partir +de scripts cgi. +.LP +.TP +.B \-\^E chaîne +Produire en sortie une page d'erreur contenant le message d'erreur donné. +.LP +La forme générale d'un hyperlien généré pour référencer une page de manuel est +.IP +<method:cgipath><man2htmlpath><separator><manpage> +.LP +qui est d'ailleurs la forme par défaut. Les éléments de cet hyperlien sont +positionnés en utilisant diverses options. +.TP +.B \-\^h +Positionner method:cgipath à http://localhost. +C'est le comportement par défaut. +.TP +.BI \-\^H " hôte[.domaine][:port]" +Positionner method:cgipath à +.RI http:// hôte.domaine:port . +.TP +.B \-\^l +Positionner method:cgipath à +.RI lynxcgi: /home/httpd . +.TP +.BI \-\^L " dir" +Positionner method:cgipath à +.RI lynxcgi: dir . +.TP +.BI \-\^M " man2htmlpath" +Positionner le chemin vers man2html à utiliser. La valeur par défaut est +.IR /cgi-bin/man/man2html . +.TP +.B \-\^p +Positionner le séparateur à «\ /\ ». +.TP +.B \-\^q +Positionner le séparateur à «\ ?\ ». C'est la valeur par défaut. +.TP +.B \-\^r +Utiliser des chemins html relatifs plutôt que les chemins cgi-bin. +.LP +Sur une machine sur laquelle +.BR httpd +ne tourne pas, vous pouvez utiliser +.B lynx +pour naviguer dans les pages de manuel en utilisant la méthode lynxcgi. +Lorsqu'un démon http est en service, vous pouvez utiliser lynx ou n'importe +quel autre navigateur pour parcourir les pages de manuel en utilisant +la méthode http. +L'option \-l (pour «\ lynxcgi\ ») sélectionne ce fonctionnement. +Avec elle, le chemin cgi par défaut est \fI/home/httpd\fP. + +En général, un script cgi peut être appelé de la façon suivante +.IP +<path_to_script>/<more_path>?<query> +.LP +et les variables d'environnement PATH_INFO et QUERY_STRING seront positionnées +respectivement à <more_path> et <query>. +Puisque lynxcgi ne gère pas l'élément PATH_INFO, nous allons générer des +hyperliens avec «\ ?\ » comme séparateur par défaut. +L'option \-p (pour «\ path\ ») sélectionne «\ /\ » comme séparateur, alors que +l'option \-q (for «\ query\ ») sélectionne «\ ?\ ». + +L'option \-H \fIhost\fP spécifiera l'hôte à utiliser +(à la place \fIlocalhost\fP). Un script cgi pourra utiliser +.IP +man2html -H $SERVER_NAME +.LP +si la variable SERVER_NAME est positionnée. Cela permettra à votre machine +de fonctionner en tant que serveur et d'exporter les pages manuel. + +.SH BOGUES +Il y a beaucoup d'heuristiques. La sortie produite ne sera pas toujours +parfaite. La méthode lynxcgi ne fonctionnera pas si lynx a été compilé sans +le support de celle-ci. Il peut y avoir des problèmes de sécurité. + +.SH "VOIR AUSSI" +.BR lynx (1), +.BR man (1) + +.SH TRADUCTION +.PP +Ce document est une traduction réalisée par Alain Portal +<aportal AT univ-montp2 DOT fr> le 1er juin 2005 et mise à jour +le 7 novembre 2005. +.PP +L'équipe de traduction a fait le maximum pour réaliser une adaptation +française de qualité. La version anglaise la plus à jour de ce document est +toujours consultable via la commande\ : «\ \fBLANG=en\ man\ 1\ man2html\fR\ ». +N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute +erreur dans cette page de manuel. diff --git a/man2html/locales/it/hman.1 b/man2html/locales/it/hman.1 new file mode 100644 index 0000000..730de9c --- /dev/null +++ b/man2html/locales/it/hman.1 @@ -0,0 +1,71 @@ +.\" Copyright (c) 1998 Andries Brouwer
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the README file that comes with the man 1.0
+.\" distribution.
+.\" Traduzione da man-1.6d di Giulio Daprelà <giulio@pluto.it>
+.\" Revisione a cura di Vieri Giugni <v.giugni@gmail.com>
+.\" agosto 2006
+.\"
+.TH hman 1 "19 Gennaio 1998"
+.LO 1
+.SH NOME
+hman \- naviga le pagine di manuale on-line
+.SH SINTASSI
+.B hman
+[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] \fIname\fP
+.br
+.B hman
+[ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] [ index ]
+.SH DESCRIZIONE
+Lo script
+.B hman
+è un'interfaccia per man2html(1), che permette di inserire richieste di man
+page dalla linea di comando e vedere l'output nel browser
+preferito.
+Il comportamento ricorda quello di
+.BR man (1)
+perciò molte persone potranno utilizzare un alias da
+.B hman
+a
+.BR man .
+Se il browser usato è netscape, e una copia di netscape
+è già in esecuzione,
+.B hman
+passerà la richiesta a quest'ultima
+
+.SH OPZIONI
+.TP
+.B \-\^P " browser"
+Specifica quale browser (lynx, xmosaic, arena, chimera,
+netscape, amaya, ...) usare.
+Questa opzione sovrascrive la variabile d'ambiente
+.B MANHTMLPAGER .
+Il valore predefinito è la versione non-httpd di
+.BR lynx .
+.TP
+.B \-\^H " host"
+Specifica da quale host prendere le man page.
+Questa opzione sovrascrive la variabile d'ambiente
+.B MANHTMLHOST .
+Il valore predefinito è
+.BR localhost .
+
+.SH AMBIENTE
+.TP
+MANHTMLPAGER
+Il browser predefinito in uso è selezionato da questa variabile d'ambiente.
+.TP
+MANHTMLHOST
+L'host predefinito in uso è selezionato da questa variabile d'ambiente.
+
+.SH "VEDERE ANCHE"
+.BR man (1),
+.BR man2html (1),
+.BR arena (1),
+.BR lynx (1),
+.BR netscape (1),
+.BR xmosaic (1),
+.BR glimpse (1)
+
+http://www.mcom.com/newsref/std/x-remote.html
diff --git a/man2html/locales/it/man2html.1 b/man2html/locales/it/man2html.1 new file mode 100644 index 0000000..45feef0 --- /dev/null +++ b/man2html/locales/it/man2html.1 @@ -0,0 +1,153 @@ +'\" t
+.\" Man page for man2html
+.\" aeb, 980101
+.\"
+.\" Traduzione da man-1.6d di Giulio Daprelà <giulio@pluto.it>
+.\" Revisione a cura di Vieri Giugni <v.giugni@gmail.com>
+.\" giugno 2006
+.\"
+.TH man2html 1 "1 gennaio 1998"
+.LO 1
+.SH NOME
+man2html \- formatta una pagina di manuale in html
+.SH SINTASSI
+man2html [options] [file]
+.SH DESCRIZIONE
+.B man2html
+converte una pagina di manuale che si trova in
+.I file
+(o standard input (stdin); nel caso non venga fornito alcun file come
+argomento, o sia indicato "-", come argomento)
+dallo stile man nroff in html, e stampa il risultato in standard output (stdout).
+Supporta tbl, ma non conosce eqn.
+Lo stato di uscita è 0. Se qualcosa va male
+viene stampata su stdout una pagina di errore.
+
+Può essere usato come utilità stand-alone, ma è pensato principalmente
+come ausilio per permettere agli utenti di navigare le proprie man page
+usando un browser html come
+.BR lynx (1),
+.BR xmosaic (1)
+o
+.BR netscape (1).
+./" (See
+./" .BR man (1)
+./" for info on how to browse man pages via
+./" .BR man2html .
+./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx"
+./" in the environment.)
+
+La parte principale di
+.B man2html
+è il motore da troff a html scritto da Richard Verhoeven (rcb5@win.tue.nl).
+Esso aggiunge dei collegamenti ipertestuali per i seguenti costrutti:
+.LP
+.TS
+l l.
+foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo"
+method://string "method://string"
+www.host.name "http://www.host.name"
+ftp.host.name "ftp://ftp.host.name"
+name@host "mailto:name@host"
+<string.h> "file:/usr/include/string.h"
+.TE
+.LP
+(Il primo di questi può essere controllato dalle opzioni - vedere sotto).
+Non viene fatto nessun controllo - i collegamenti generati non sono
+necessari o indispensabili.
+Inoltre viene generato un indice con collegamenti interni alle varie sezioni,
+in modo che sia più facile effettuare ricerche personalizzate in pagine di
+manuale grandi come
+.BR bash (1).
+
+.SH OPZIONI
+Quando si legge da stdin non è sempre chiaro come effettuare l'espansione
+.so . L'opzione \-D permette a uno script di definire la
+directory di lavoro.
+.LP
+.TP
+.B \-\^D pathname
+Estrae le ultime due parti dal percorso, ed esegue
+\fIchdir\fP(\fIdir\fP) prima di iniziare la conversione.
+.LP
+L'opzione \-E permette una facile generazione di messaggi di errore
+da uno script cgi.
+.LP
+.TP
+.B \-\^E string
+Genera una pagina di errore contenente il messaggio di errore che si è verificato.
+.LP
+La forma generale di un collegamento ipertestuale creato per una
+man page di riferimento è
+.IP
+<method:cgipath><man2htmlpath><separator><manpage>
+.LP
+con un valore predefinito come mostrato sopra. Le parti di questo collegamento
+ipertestuale sono impostate usando le varie opzioni.
+.TP
+.B \-\^h
+Set method:cgipath to http://localhost. Questo è il valore predefinito.
+.TP
+.BI \-\^H " host[.domain][:port]"
+Set method:cgipath to
+.RI http:// host.domain:port .
+.TP
+.B \-\^l
+Set method:cgipath to
+.RI lynxcgi: /home/httpd .
+.TP
+.BI \-\^L " dir"
+Set method:cgipath to
+.RI lynxcgi: dir .
+.TP
+.BI \-\^M " man2htmlpath"
+Imposta il man2htmlpath da usare. Il valore predefinito è
+.IR /cgi-bin/man/man2html .
+.TP
+.B \-\^p
+Imposta '/' come separatore.
+.TP
+.B \-\^q
+Imposta '?' come separatore. Questo è il valore predefinito.
+.TP
+.B \-\^r
+Usa percorsi html relativi, invece dei percorsi cgi-bin.
+.LP
+Su una macchina, senza eseguire
+.BR httpd ,
+si può usare
+.B lynx
+per navigare le man page, usando il metodo lynxcgi.
+Quando è attivo qualche demone http, lynx, o qualunque altro browser,
+può essere usato per navigare le man page, usando il metodo http.
+L'opzione \-l (per `lynxcgi') seleziona il comportamento precedente.
+Con esso, il valore predefinito di cgipath è \fI/home/httpd\fP.
+
+In generale, uno script cgi può essere chiamato da
+.IP
+<path_to_script>/<more_path>?<query>
+.LP
+e le variabili d'ambiente PATH_INFO e QUERY_STRING
+verranno impostate rispettivamente in <more_path> e <query>.
+Poiché lynxcgi non gestisce la parte PATH_INFO, vengono generati
+collegamenti ipertestualil con `?' come separatore predefinito.
+L'opzione \-p (per `path') seleziona '/' come separatore, mentre
+l'opzione \-q (per `query') seleziona '?' come separatore.
+
+L'opzione \-H \fIhost\fP specificherà l'host da usare
+(invece di \fIlocalhost\fP). Uno script cgi può usare
+.IP
+man2html -H $SERVER_NAME
+.LP
+se è impostata la variabile SERVER_NAME . Questo permetterà alla propria
+macchina di comportarsi come un server ed esportare man page.
+
+.SH BUG
+Ci sono molti fattori difficilmente prevedibili. L'output potrebbe non
+essere sempre perfetto. Il metodo lynxcgi non funzionerà se lynx è stato
+compilato senza selezionare il supporto per quest'ultimo. Ci potrebbero
+essere problemi di sicurezza.
+
+.SH "VEDERE ANCHE"
+.BR lynx (1),
+.BR man (1)
diff --git a/man2html/man2html.1 b/man2html/man2html.1 new file mode 100644 index 0000000..c1c25b3 --- /dev/null +++ b/man2html/man2html.1 @@ -0,0 +1,151 @@ +'\" t +.\" Man page for man2html +.\" aeb, 980101 +.\" +.TH man2html 1 "1 January 1998" +.LO 1 +.SH NAME +man2html \- format a manual page in html +.SH SYNOPSIS +man2html [options] [file] +.SH DESCRIPTION +.B man2html +converts a manual page as found in +.I file +(or stdin, in case no file argument, or the argument "-", is given) +from man-style nroff into html, and prints the result on stdout. +It does support tbl but does not know about eqn. +The exit status is 0. If something goes wrong, +an error page is printed on stdout. + +This can be used as a stand-alone utility, but is mainly intended +as an auxiliary, to enable users to browse their man pages using +a html browser like +.BR lynx (1), +.BR xmosaic (1) +or +.BR netscape (1). +./" (See +./" .BR man (1) +./" for info on how to browse man pages via +./" .BR man2html . +./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx" +./" in the environment.) + +The main part of +.B man2html +is the troff-to-html engine written by Richard Verhoeven (rcb5@win.tue.nl). +It adds hyperlinks for the following constructs: +.LP +.TS +l l. +foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo" +method://string "method://string" +www.host.name "http://www.host.name" +ftp.host.name "ftp://ftp.host.name" +name@host "mailto:name@host" +<string.h> "file:/usr/include/string.h" +.TE +.LP +(The first of these can be tuned by options - see below.) +No lookup is done - the links generated need not exist. +Also an index with internal hyperlinks to the various sections +is generated, so that it is easier to find one's way +in large man pages like +.BR bash (1). + +.SH OPTIONS +When reading from stdin, it is not always clear how to +do .so expansion. The \-D option allows a script to define +the working directory. +.LP +.TP +.B \-\^D pathname +Strip the last two parts from the pathname, and do a +\fIchdir\fP(\fIdir\fP) before starting the conversion. +.LP +The \-E option allows the easy generation of error messages +from a cgi script. +.LP +.TP +.B \-\^E string +Output an error page containing the given error message. +.LP +The general form of a hyperlink generated for a man page reference is +.IP +<method:cgipath><man2htmlpath><separator><manpage> +.LP +with a default as shown above. The parts of this hyperlink +are set using the various options. +.TP +.B \-\^h +Set method:cgipath to http://localhost. This is the default. +.TP +.BI \-\^H " host[.domain][:port]" +Set method:cgipath to +.RI http:// host.domain:port . +.TP +.B \-\^l +Set method:cgipath to +.RI lynxcgi: /home/httpd . +.TP +.BI \-\^L " dir" +Set method:cgipath to +.RI lynxcgi: dir . +.TP +.BI \-\^M " man2htmlpath" +Set the man2htmlpath to use. The default is +.IR /cgi-bin/man/man2html . +.TP +.B \-\^p +Set separator to '/'. +.TP +.B \-\^q +Set separator to '?'. This is the default. +.TP +.B \-\^r +Use relative html paths, instead of cgi-bin paths. +.LP +On a machine without running +.BR httpd , +one can use +.B lynx +to browse the man pages, using the lynxcgi method. +When some http daemon is running, lynx, or any other browser, +can be used to browse the man pages, using the http method. +The option \-l (for `lynxcgi') selects the former behaviour. +With it, the default cgipath is \fI/home/httpd\fP. + +In general, a cgi script can be called by +.IP +<path_to_script>/<more_path>?<query> +.LP +and the environment variables PATH_INFO and QUERY_STRING +will be set to <more_path> and <query>, respectively. +Since lynxcgi does not handle the PATH_INFO part, we generate +hyperlinks with `?' as a separator by default. +The option \-p (for `path') selects '/' as a separator, while +the option \-q (for `query') selects '?' as a separator. + +The option \-H \fIhost\fP will specify the host to use +(instead of \fIlocalhost\fP). A cgi script could use +.IP +man2html -H $SERVER_NAME +.LP +if the variable SERVER_NAME is set. This would allow your machine +to act as a server and export man pages. + +.SH BUGS +There are many heuristics. The output will not always be perfect. +The lynxcgi method will not work if lynx was compiled without +selecting support for it. There may be problems with security. + +.SH AUTHOR +Richard Verhoeven was the original author of +.BR "man2html" . +Michael Hamilton and Andries Brouwer subsequently improved on it. +Federico Lucifredi <flucifredi@acm.org> is the current maintainer. + +.SH "SEE ALSO" +.BR lynx (1), +.BR man (1) diff --git a/man2html/man2html.c b/man2html/man2html.c new file mode 100644 index 0000000..b37eef6 --- /dev/null +++ b/man2html/man2html.c @@ -0,0 +1,3241 @@ +/* +** This program was written by Richard Verhoeven (NL:5482ZX35) +** at the Eindhoven University of Technology. Email: rcb5@win.tue.nl +** +** Permission is granted to distribute, modify and use this program +** as long as this comment is not removed or changed. +*/ + +/* BSD mandoc stuff added by Michael Hamilton. */ + +/* This program is rather buggy, but in spite of that it often works. + Improved things a little - April 1997 & January 1998 & Dec 2001 - + aeb@cwi.nl. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> +#include "defs.h" +#include "../src/version.h" + +/* BSD mandoc Bd/Ed example(?) blocks */ +#define BD_LITERAL 1 +#define BD_INDENT 2 + +#define SIZE(a) (sizeof(a)/sizeof(*a)) + +static char NEWLINE[2]="\n"; +static char idxlabel[6] = "ixAAA"; + +#define INDEXFILE "/tmp/manindex.list" + +char *fname; +char *directory; +FILE *idxfile; + +char eqndelimopen=0, eqndelimclose=0; +char escapesym='\\', nobreaksym='\'', controlsym='.', fieldsym=0, padsym=0; + +char *buffer=NULL; +int buffpos=0, buffmax=0; +int scaninbuff=0; +int still_dd=0; +int tabstops[20] = { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 }; +int maxtstop=12; +int curpos=0; + +static char *scan_troff(char *c, int san, char **result); +static char *scan_troff_mandoc(char *c, int san, char **result); + +static char **argument=NULL; + +static char charb[3]; + +static char * +expand_char(int nr) +{ + STRDEF *h; + + if (!nr) + return NULL; + + h = chardef; + if (h->nr != V('*','*')) { + printf("chardef corrupted\n"); + exit(1); + } + + for (h = chardef; h; h = h->next) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } + charb[0] = nr/256; + charb[1] = nr%256; + charb[2] = 0; + curpos += 2; + return charb; +} + +static char * +expand_string(int nr) +{ + STRDEF *h; + + if (!nr) + return NULL; + for (h = strdef; h; h = h->next) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } + return NULL; +} + + +static char outbuffer[1024]; +static int obp=0; +static int no_newline_output=0; /* boolean, set by \c */ +static int newline_for_fun=0; +static int output_possible=0; +static int out_length=0; + +static void +add_links(char *c) +{ + /* + ** Add the links to the output. + ** At the moment the following are recognized: + ** + ** name(*) -> ../man?/name.* + ** method://string -> method://string + ** www.host.name -> http://www.host.name + ** ftp.host.name -> ftp://ftp.host.name + ** name@host -> mailto:name@host + ** <name.h> -> file:/usr/include/name.h (guess) + ** + ** Other possible links to add in the future: + ** + ** /dir/dir/file -> file:/dir/dir/file + */ + int i,j,nr; + char *f, *g, *h; + char *idtest[6]; /* url, mailto, www, ftp, manpage, include file */ + + out_length+=strlen(c); + + nr=0; + idtest[0]=strstr(c+1,"://"); + idtest[1]=strchr(c+1,'@'); + idtest[2]=strstr(c,"www."); + idtest[3]=strstr(c,"ftp."); + idtest[4]=strchr(c+1,'('); + idtest[5]=strstr(c+1,".h>"); + for (i=0; i<6; i++) nr += (idtest[i]!=NULL); + while (nr) { + j=-1; + for (i=0; i<6; i++) + if (idtest[i] && (j<0 || idtest[i]<idtest[j])) j=i; + switch (j) { + case 5: /* <name.h> */ + f=idtest[5]; + h=f+2; + g=f; + while (g>c && g[-1]!=';') g--; + if (g!=c) { + char t; + t=*g; + *g=0; + printf("%s",c); + *g=t;*h=0; + include_file_html(g); + c=f+6; + } else { + f[5]=0; + printf("%s",c); + f[5]=';'; + c=f+5; + } + break; + case 4: /* manpage? */ + f=idtest[j]; + /* find section - accept (1), (3F), (3Xt), (n), (l) */ + g=strchr(f,')'); + if (g && g-f<7 /* section has length at most 5, like 3Xlib */ + /* preceded by name or html markup */ + && (isalnum(f[-1]) || f[-1]=='>') + /* section is n or l or starts with a digit */ + && strchr("123456789nl", f[1]) + && (g-f == 2 || (g-f == 3 && isdigit(f[1]) && isalpha(f[2])) + || (f[2] == 'X' && isdigit(f[1]))) + ) { + /* this might be a link */ + h=f-1; + /* skip html markup */ + while (h>c && *h=='>') { + while (h!=c && *h!='<') h--; + if (h!=c) h--; + } + if (isalnum(*h)) { + char t,te,tg,*e; + e=h+1; + while (h>c && (isalnum(h[-1]) || h[-1]=='_' || + h[-1]=='-' || h[-1]=='.' || h[-1]==':')) + h--; + t=*h; *h=0; + printf("%s", c); + *h=t; + tg=*g; *g=0; + te=*e; *e=0; + man_page_html(f+1, h); /* section, page */ + *e=te; + *g=tg; + c=e; + } + } + *f=0; + printf("%s", c); + *f='('; + idtest[4]=f-1; + c=f; + break; /* manpage */ + case 3: /* ftp */ + case 2: /* www */ + g=f=idtest[j]; + while (*g && (isalnum(*g) || *g=='_' || *g=='-' || *g=='+' || + *g=='.')) g++; + if (g[-1]=='.') g--; + if (g-f>4) { + char t; + t=*f; *f=0; + printf("%s",c); + *f=t; t=*g;*g=0; + if (j==3) + ftp_html(f); + else + www_html(f); + *g=t; + c=g; + } else { + f[3]=0; + printf("%s",c); + c=f+3; + f[3]='.'; + } + break; + case 1: /* mailto */ + g=f=idtest[1]; + while (g>c && (isalnum(g[-1]) || g[-1]=='_' || g[-1]=='-' || + g[-1]=='+' || g[-1]=='.' || g[-1]=='%')) g--; + h=f+1; + while (*h && (isalnum(*h) || *h=='_' || *h=='-' || *h=='+' || + *h=='.')) h++; + if (h[-1]=='.') h--; + if (h-f>4 && f-g>1) { + char t; + t=*g; + *g=0; + printf("%s",c); + *g=t;t=*h;*h=0; + mailto_html(g); + *h=t; + c=h; + } else { + *f=0; + printf("%s",c); + *f='@'; + idtest[1]=c; + c=f; + } + break; + case 0: /* url */ + g=f=idtest[0]; + while (g>c && isalpha(g[-1]) && islower(g[-1])) g--; + h=f+3; + while (*h && !isspace(*h) && *h!='<' && *h!='>' && *h!='"' && + *h!='&') h++; + if (f-g>2 && f-g<7 && h-f>3) { + char t; + t=*g; + *g=0; + printf("%s", c); + *g=t; t=*h; *h=0; + url_html(g); + *h=t; + c=h; + } else { + f[1]=0; + printf("%s", c); + f[1]='/'; + c=f+1; + } + break; + default: + break; + } + nr=0; + if (idtest[0] && idtest[0]<c) idtest[0]=strstr(c+1,"://"); + if (idtest[1] && idtest[1]<c) idtest[1]=strchr(c+1,'@'); + if (idtest[2] && idtest[2]<c) idtest[2]=strstr(c,"www."); + if (idtest[3] && idtest[3]<c) idtest[3]=strstr(c,"ftp."); + if (idtest[4] && idtest[4]<c) idtest[4]=strchr(c+1,'('); + if (idtest[5] && idtest[5]<c) idtest[5]=strstr(c+1,".h>"); + for (i=0; i<6; i++) nr += (idtest[i]!=NULL); + } + printf("%s", c); +} + +int current_font=0; +int current_size=0; +int fillout = 1; + +/* + * Kludge: remove \a - in the context + * .TH NAME 2 date "Version" "Title" + * we got output \aTitle\a. + */ +static void +out_html(char *c) { + if (!c) + return; + if (no_newline_output) { /* remove \n if present */ + int i=0; + while (c[i]) { + if (!no_newline_output) + c[i-1]=c[i]; + if (c[i]=='\n') + no_newline_output=0; + i++; + } + if (!no_newline_output) + c[i-1]=0; + } + if (scaninbuff) { + while (*c) { + if (buffpos >= buffmax) { + buffer = xrealloc(buffer, buffmax*2); + buffmax = buffmax*2; + } + if (*c != '\a') + buffer[buffpos++] = *c; + c++; + } + } else if (output_possible) { + while (*c) { + if (*c != '\a') + outbuffer[obp++] = *c; + if (*c == '\n' || obp > 1000) { + outbuffer[obp] = 0; + add_links(outbuffer); + obp = 0; + } + c++; + } + } +} + +/* --------------------------------------------------------------- */ +/* All references to dl_set and itemdepth are here. */ +/* --------------------------------------------------------------- */ +static int itemdepth=0; +static int dl_set[30]= { 0 }; +#define noDL 0 +#define DL 1 +#define UL 2 +#define OL 3 +static char *dl_open[4] = { "", "<DL COMPACT>\n", "<UL>", "<OL>" }; +static char *dl_close[4] = { "", "</DL>\n", "</UL>", "</OL>" }; + +static inline void +dl_begin(void) { + if (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == noDL) { + out_html(dl_open[DL]); + dl_set[itemdepth]=DL; + } + out_html("<DT>"); +} + +static inline void +dl_end(void) { + if (itemdepth < SIZE(dl_set)) { + int type = dl_set[itemdepth]; + if (type == DL) { + out_html(dl_close[type]); + dl_set[itemdepth]=noDL; + } + } +} + +static inline void +dl_newlevel(void) { + itemdepth++; + if (itemdepth < SIZE(dl_set)) + dl_set[itemdepth]=noDL; + out_html("<DL COMPACT><DT><DD>"); +} + +static inline void +dl_endlevel(void) { + if (itemdepth) { + dl_end(); + out_html("</DL>\n"); + itemdepth--; + } +} + +static inline void +dl_down(void) { + while (itemdepth) + dl_endlevel(); + dl_end(); +} + +static inline int +dl_type(int type) { + return (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == type); +} + +static inline void +dl_newlevel_type(int type) { + itemdepth++; + if (itemdepth < SIZE(dl_set)) { + dl_set[itemdepth]=type; + out_html(dl_open[type]); + } +} + +static inline void +dl_endlevel_type(void) { + if (itemdepth) { + if (itemdepth < SIZE(dl_set)) + out_html(dl_close[dl_set[itemdepth]]); + itemdepth--; + } +} +/* --------------------------------------------------------------- */ +/* This stuff is broken. +It generates + <DT><B>TIOCLINUX, subcode=0<DD> + Dump the screen. + </B><I>argp</I> points to a +from + .IP "\fBTIOCLINUX, subcode=0" + Dump the screen. + \fIargp\fP points to a +Bug 1: incorrect nesting: </B> is needed before <DD>. +Bug 2: incorrect font: after the .IP things are roman again. +*/ + +#define FO0 "" +#define FC0 "" +#define FO1 "<I>" +#define FC1 "</I>" +#define FO2 "<B>" +#define FC2 "</B>" +#define FO3 "<TT>" +#define FC3 "</TT>" + +char *switchfont[16] = { "" , FC0 FO1, FC0 FO2, FC0 FO3, + FC1 FO0, "" , FC1 FO2, FC1 FO3, + FC2 FO0, FC2 FO1, "" , FC2 FO3, + FC3 FO0, FC3 FO1, FC3 FO2, "" }; + +static char * +change_to_font(int nr) +{ + int i; + switch (nr) { + case '0': nr++; + case '1': case '2': case '3': case '4': + nr = nr-'1'; break; + case V('C','W'): break; + case 'L': nr=3; break; + case 'B': nr=2; break; + case 'I': nr=1; break; + case 0: case 1: case 2: case 3: + break; + case 'P': case 'R': + default: nr=0; break; + } + i= current_font*4+nr%4; + current_font=nr%4; + return switchfont[i]; +} + +static char sizebuf[200]; + +static char * +change_to_size(int nr) +{ + int i; + switch (nr) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': nr=nr-'0'; break; + case '\0': break; + default: nr=current_size+nr; if (nr>9) nr=9; if (nr< -9) nr=-9; break; + } + if (nr==current_size) return ""; + i=current_font; + sizebuf[0]=0; + strcat(sizebuf, change_to_font(0)); + if (current_size) strcat(sizebuf, "</FONT>"); + current_size=nr; + if (nr) { + int l; + strcat(sizebuf, "<FONT SIZE=\""); + l=strlen(sizebuf); + if (nr>0) sizebuf[l++]='+'; else sizebuf[l++]='-',nr=-nr; + sizebuf[l++]=nr+'0'; + sizebuf[l++]='"'; + sizebuf[l++]='>'; + sizebuf[l]=0; + } + strcat(sizebuf, change_to_font(i)); + return sizebuf; +} + +int asint=0; +int intresult=0; + +#define SKIPEOL while (*c && *c++!='\n') + +static int skip_escape=0; +static int single_escape=0; + +static char * +scan_escape(char *c) { + char *h=NULL; + char b[5]; + INTDEF *intd; + int exoutputp,exskipescape; + int i,j; + + intresult=0; + switch (*c) { + case 'e': h="\\"; curpos++;break; + case '0': + case ' ': h=" ";curpos++; break; + case '|': h=""; break; + case '"': SKIPEOL; c--; h=""; break; + case '$': + if (argument) { + c++; + i=(*c -'1'); + if (!(h=argument[i])) h=""; + } + break; + case 'z': + c++; + if (*c=='\\') { c=scan_escape(c+1); c--;h=""; } + else { + b[0]=*c; + b[1]=0; + h=""; + } + break; + case 'k': c++; if (*c=='(') c+=2; + case '^': + case '!': + case '%': + case 'a': + case 'd': + case 'r': + case 'u': + case '\n': + case '&': h=""; break; + case '(': + c++; + i= c[0]*256+c[1]; + c++; + h = expand_char(i); + break; + case '*': + c++; + if (*c=='(') { + c++; + i= c[0]*256+c[1]; + c++; + } else + i= *c *256+' '; + h = expand_string(i); + break; + case 'f': + c++; + if (*c=='\\') { + c++; + c=scan_escape(c); + c--; + i=intresult; + } else if (*c != '(') + i=*c; + else { + c++; + i=c[0]*256+c[1]; + c++; + } + if (!skip_escape) h=change_to_font(i); else h=""; + break; + case 's': + c++; + j=0;i=0; + if (*c=='-') {j= -1; c++;} else if (*c=='+') {j=1; c++;} + if (*c=='0') c++; else if (*c=='\\') { + c++; + c=scan_escape(c); + i=intresult; if (!j) j=1; + } else + while (isdigit(*c) && (!i || (!j && i<4))) i=i*10+(*c++)-'0'; + if (!j) { j=1; if (i) i=i-10; } + if (!skip_escape) h=change_to_size(i*j); else h=""; + c--; + break; + case 'n': + c++; + j=0; + switch (*c) { + case '+': j=1; c++; break; + case '-': j=-1; c++; break; + default: break; + } + if (*c=='(') { + c++; + i=V(c[0],c[1]); + c=c+1; + } else { + i=V(c[0],' '); + } + intd=intdef; + while (intd && intd->nr!=i) intd=intd->next; + if (intd) { + intd->val=intd->val+j*intd->incr; + intresult=intd->val; + } else { + switch (i) { + case V('.','s'): intresult=current_size; break; + case V('.','f'): intresult=current_font; break; + default: intresult=0; break; + } + } + h=""; + break; + case 'w': + c++; + i=*c; + c++; + exoutputp=output_possible; + exskipescape=skip_escape; + output_possible=0; + skip_escape=1; + j=0; + while (*c!=i) { + j++; + if (*c==escapesym) c=scan_escape(c+1); else c++; + } + output_possible=exoutputp; + skip_escape=exskipescape; + intresult=j; + break; + case 'l': h="<HR>"; curpos=0; + case 'b': + case 'v': + case 'x': + case 'o': + case 'L': + case 'h': + c++; + i=*c; + c++; + exoutputp=output_possible; + exskipescape=skip_escape; + output_possible=0; + skip_escape=1; + while (*c != i) + if (*c==escapesym) c=scan_escape(c+1); + else c++; + output_possible=exoutputp; + skip_escape=exskipescape; + break; + case 'c': no_newline_output=1; break; + case '{': newline_for_fun++; h="";break; + case '}': if (newline_for_fun) newline_for_fun--; h="";break; + case 'p': h="<BR>\n";curpos=0; break; + case 't': h="\t";curpos=(curpos+8)&0xfff8; break; + case '<': h="<";curpos++; break; + case '>': h=">";curpos++; break; + case '\\': if (single_escape) { c--; break;} + default: b[0]=*c; b[1]=0; h=b; curpos++; break; + } + c++; + if (!skip_escape) out_html(h); + return c; +} + +typedef struct TABLEITEM TABLEITEM; + +struct TABLEITEM { + char *contents; + int size,align,valign,colspan,rowspan,font,vleft,vright,space,width; + TABLEITEM *next; +}; + +static TABLEITEM emptyfield = {NULL,0,0,0,1,1,0,0,0,0,0,NULL}; +typedef struct TABLEROW TABLEROW; + +struct TABLEROW { + TABLEITEM *first; + TABLEROW *prev, *next; +}; + +static char *tableopt[]= { "center", "expand", "box", "allbox", "doublebox", + "tab", "linesize", "delim", NULL }; +static int tableoptl[] = { 6,6,3,6,9,3,8,5,0}; + + +static void clear_table(TABLEROW *table) +{ + TABLEROW *tr1,*tr2; + TABLEITEM *ti1,*ti2; + + tr1=table; + while (tr1->prev) tr1=tr1->prev; + while (tr1) { + ti1=tr1->first; + while (ti1) { + ti2=ti1->next; + if (ti1->contents) free(ti1->contents); + free(ti1); + ti1=ti2; + } + tr2=tr1; + tr1=tr1->next; + free(tr2); + } +} + +char *scan_expression(char *c, int *result); + +static char *scan_format(char *c, TABLEROW **result, int *maxcol) +{ + TABLEROW *layout, *currow; + TABLEITEM *curfield; + int i,j; + if (*result) { + clear_table(*result); + } + layout= currow=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->next=currow->prev=NULL; + currow->first=curfield=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + while (*c && *c!='.') { + switch (*c) { + case 'C': case 'c': case 'N': case 'n': + case 'R': case 'r': case 'A': case 'a': + case 'L': case 'l': case 'S': case 's': + case '^': case '_': + if (curfield->align) { + curfield->next=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); + curfield=curfield->next; + *curfield=emptyfield; + } + curfield->align=toupper(*c); + c++; + break; + case 'i': case 'I': case 'B': case 'b': + curfield->font = toupper(*c); + c++; + break; + case 'f': case 'F': + c++; + curfield->font = toupper(*c); + c++; + if (!isspace(*c)) c++; + break; + case 't': case 'T': curfield->valign='t'; c++; break; + case 'p': case 'P': + c++; + i=j=0; + if (*c=='+') { j=1; c++; } + if (*c=='-') { j=-1; c++; } + while (isdigit(*c)) i=i*10+(*c++)-'0'; + if (j) curfield->size= i*j; else curfield->size=j-10; + break; + case 'v': case 'V': + case 'w': case 'W': +// c=scan_expression(c+2,&curfield->width); + c++; + if (*c == '(') { + c=scan_expression(c+1,&curfield->width); + } else { + i=0; + while (isdigit(*c)) i=i*10+(*c++)-'0'; + curfield->width=i; + } + break; + case '|': + if (curfield->align) curfield->vleft++; + else curfield->vright++; + c++; + break; + case 'e': case 'E': + c++; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + i=0; + while (isdigit(*c)) i=i*10+(*c++)-'0'; + curfield->space=i; + break; + case ',': case '\n': + currow->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); + currow->next->prev=currow; + currow=currow->next; + currow->next=NULL; + curfield=currow->first=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + c++; + break; + default: + c++; + break; + } + } + if (*c=='.') while (*c++!='\n'); + *maxcol=0; + currow=layout; + while (currow) { + curfield=layout->first; + i=0; + while (curfield) { + i++; + curfield=curfield->next; + } + if (i>*maxcol) *maxcol=i; + currow=currow->next; + } + *result=layout; + return c; +} + +static TABLEROW * +next_row(TABLEROW *tr) +{ + if (tr->next) { + tr=tr->next; + if (!tr->next) next_row(tr); + return tr; + } else { + TABLEITEM *ti, *ti2; + tr->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); + tr->next->prev=tr; + ti=tr->first; + tr=tr->next; + tr->next=NULL; + if (ti) tr->first=ti2=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + else tr->first=ti2=NULL; + while (ti!=ti2) { + *ti2=*ti; + ti2->contents=NULL; + if ((ti=ti->next)) { + ti2->next=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + } + ti2=ti2->next; + } + return tr; + } +} + +char itemreset[20]="\\fR\\s0"; + +static char * +scan_table(char *c) { + char *h; + char *g; + int center=0, expand=0, box=0, border=0, linesize=1; + int i,j,maxcol=0, finished=0; + int oldfont, oldsize,oldfillout; + char itemsep='\t'; + TABLEROW *layout=NULL, *currow; + TABLEITEM *curfield; + while (*c++!='\n'); /* skip TS */ + h=c; + if (*h=='.') return c-1; + oldfont=current_font; + oldsize=current_size; + oldfillout=fillout; + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + while (*h && *h!='\n') h++; + if (h[-1]==';') { + /* scan table options */ + while (c<h) { + while (isspace(*c)) c++; + for (i=0; tableopt[i] && strncmp(tableopt[i],c,tableoptl[i]);i++); + c=c+tableoptl[i]; + switch (i) { + case 0: center=1; break; + case 1: expand=1; break; + case 2: box=1; break; + case 3: border=1; break; + case 4: box=2; break; + case 5: while (*c++!='('); itemsep=*c++; break; + case 6: while (*c++!='('); linesize=0; + while (isdigit(*c)) linesize=linesize*10+(*c++)-'0'; + break; + case 7: while (*c!=')') c++; + default: break; + } + c++; + } + c=h+1; + } + /* scan layout */ + c=scan_format(c,&layout, &maxcol); + currow=layout; + next_row(currow); + curfield=layout->first; + i=0; + while (!finished && *c) { + /* search item */ + h=c; + if ((*c=='_' || *c=='=') && (c[1]==itemsep || c[1]=='\n')) { + if (c[-1]=='\n' && c[1]=='\n') { + if (currow->prev) { + currow->prev->next=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->prev->next->next=currow; + currow->prev->next->prev=currow->prev; + currow->prev=currow->prev->next; + } else { + currow->prev=layout=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->prev->prev=NULL; + currow->prev->next=currow; + } + curfield=currow->prev->first= + (TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + curfield->align=*c; + curfield->colspan=maxcol; + curfield=currow->first; + c=c+2; + } else { + if (curfield) { + curfield->align=*c; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } + if (c[1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + c=c+2; + } + } else if (*c=='T' && c[1]=='{') { + h=c+2; + c=strstr(h,"\nT}"); + c++; + *c=0; + g=NULL; + scan_troff(h, 0, &g); + scan_troff(itemreset, 0, &g); + *c='T'; + c+=3; + if (curfield) { + curfield->contents=g; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } else + if (g) free(g); + if (c[-1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + } else if (*c=='.' && c[1]=='T' && c[2]=='&' && c[-1]=='\n') { + TABLEROW *hr; + while (*c++!='\n'); + hr=currow; + currow=currow->prev; + hr->prev=NULL; + c=scan_format(c,&hr, &i); + hr->prev=currow; + currow->next=hr; + currow=hr; + next_row(currow); + curfield=currow->first; + } else if (*c=='.' && c[1]=='T' && c[2]=='E' && c[-1]=='\n') { + finished=1; + while (*c++!='\n'); + if (currow->prev) + currow->prev->next=NULL; + currow->prev=NULL; + clear_table(currow); + } else if (*c=='.' && c[-1]=='\n' && !isdigit(c[1])) { + /* skip troff request inside table (usually only .sp ) */ + while (*c++!='\n'); + } else { + h=c; + while (*c && (*c!=itemsep || c[-1]=='\\') && + (*c!='\n' || c[-1]=='\\')) c++; + i=0; + if (*c==itemsep) {i=1; *c='\n'; } + if (h[0]=='\\' && h[2]=='\n' && + (h[1]=='_' || h[1]=='^')) { + if (curfield) { + curfield->align=h[1]; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } + h=h+3; + } else { + g=NULL; + h=scan_troff(h,1,&g); + scan_troff(itemreset,0,&g); + if (curfield) { + curfield->contents=g; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } else if (g) free(g); + } + if (i) *c=itemsep; + c=h; + if (c[-1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + } + } + /* calculate colspan and rowspan */ + currow=layout; + while (currow->next) currow=currow->next; + while (currow) { + TABLEITEM *ti, *ti1=NULL, *ti2=NULL; + ti=currow->first; + if (currow->prev) ti1=currow->prev->first; + while (ti) { + switch (ti->align) { + case 'S': + if (ti2) { + ti2->colspan++; + if (ti2->rowspan<ti->rowspan) ti2->rowspan=ti->rowspan; + } + break; + case '^': + if (ti1) ti1->rowspan++; + default: + if (!ti2) ti2=ti; + else { + do { + ti2=ti2->next; + } while (ti2 && curfield->align=='S'); + } + break; + } + ti=ti->next; + if (ti1) ti1=ti1->next; + } + currow=currow->prev; + } + /* produce html output */ + if (center) out_html("<CENTER>"); + if (box==2) out_html("<TABLE BORDER><TR><TD>"); + out_html("<TABLE"); + if (box || border) { + out_html(" BORDER"); + if (!border) out_html("><TR><TD><TABLE"); + if (expand) out_html(" WIDTH=100%"); + } + out_html(">\n"); + currow=layout; + while (currow) { + j=0; + out_html("<TR VALIGN=top>"); + curfield=currow->first; + while (curfield) { + if (curfield->align!='S' && curfield->align!='^') { + out_html("<TD"); + switch (curfield->align) { + case 'N': + curfield->space+=4; + case 'R': + out_html(" ALIGN=right"); + break; + case 'C': + out_html(" ALIGN=center"); + default: + break; + } + if (!curfield->valign && curfield->rowspan>1) + out_html(" VALIGN=center"); + if (curfield->colspan>1) { + char buf[5]; + out_html(" COLSPAN="); + sprintf(buf, "%i", curfield->colspan); + out_html(buf); + } + if (curfield->rowspan>1) { + char buf[5]; + out_html(" ROWSPAN="); + sprintf(buf, "%i", curfield->rowspan); + out_html(buf); + } + j=j+curfield->colspan; + out_html(">"); + if (curfield->size) out_html(change_to_size(curfield->size)); + if (curfield->font) out_html(change_to_font(curfield->font)); + switch (curfield->align) { + case '=': out_html("<HR><HR>"); break; + case '_': out_html("<HR>"); break; + default: + if (curfield->contents) out_html(curfield->contents); + break; + } + if (curfield->space) + for (i=0; i<curfield->space;i++) out_html(" "); + if (curfield->font) out_html(change_to_font(0)); + if (curfield->size) out_html(change_to_size(0)); + if (j>=maxcol && curfield->align>'@' && curfield->align!='_') + out_html("<BR>"); + out_html("</TD>"); + } + curfield=curfield->next; + } + out_html("</TR>\n"); + currow=currow->next; + } + if (box && !border) out_html("</TABLE>"); + out_html("</TABLE>"); + if (box==2) out_html("</TABLE>"); + if (center) out_html("</CENTER>\n"); + else out_html("\n"); + if (!oldfillout) out_html("<PRE>"); + fillout=oldfillout; + out_html(change_to_size(oldsize)); + out_html(change_to_font(oldfont)); + return c; +} + +char *scan_expression(char *c, int *result) { + int value=0,value2,sign=1,opex=0; + char oper='c'; + + if (*c=='!') { + c=scan_expression(c+1, &value); + value= (!value); + } else if (*c=='n') { + c++; + value=nroff; + } else if (*c=='t') { + c++; + value=1-nroff; + } else if (*c=='\'' || *c=='"' || *c<' ' || (*c=='\\' && c[1]=='(')) { + /* ?string1?string2? + ** test if string1 equals string2. + */ + char *st1=NULL, *st2=NULL, *h; + char *tcmp=NULL; + char sep; + sep=*c; + if (sep=='\\') { + tcmp=c; + c=c+3; + } + c++; + h=c; + while (*c!= sep && (!tcmp || strncmp(c,tcmp,4))) c++; + *c='\n'; + scan_troff(h, 1, &st1); + *c=sep; + if (tcmp) c=c+3; + c++; + h=c; + while (*c!=sep && (!tcmp || strncmp(c,tcmp,4))) c++; + *c='\n'; + scan_troff(h,1,&st2); + *c=sep; + if (!st1 && !st2) value=1; + else if (!st1 || !st2) value=0; + else value=(!strcmp(st1, st2)); + if (st1) free(st1); + if (st2) free(st2); + if (tcmp) c=c+3; + c++; + } else { + while (*c && !isspace(*c) && *c!=')') { + opex=0; + switch (*c) { + case '(': + c=scan_expression(c+1, &value2); + value2=sign*value2; + opex=1; + break; + case '.': + case '0': case '1': + case '2': case '3': + case '4': case '5': + case '6': case '7': + case '8': case '9': { + int num=0,denum=1; + value2=0; + while (isdigit(*c)) value2=value2*10+((*c++)-'0'); + if (*c=='.') { + c++; + while (isdigit(*c)) { + num=num*10+((*c++)-'0'); + denum=denum*10; + } + } + if (isalpha(*c)) { + /* scale indicator */ + switch (*c) { + case 'i': /* inch -> 10pt */ + value2=value2*10+(num*10+denum/2)/denum; + num=0; + break; + default: + break; + } + c++; + } + value2=value2+(num+denum/2)/denum; + value2=sign*value2; + opex=1; + break; + } + case '\\': + c=scan_escape(c+1); + value2=intresult*sign; + if (isalpha(*c)) c++; /* scale indicator */ + opex=1; + break; + case '-': + if (oper) { sign=-1; c++; break; } + case '>': + case '<': + case '+': + case '/': + case '*': + case '%': + case '&': + case '=': + case ':': + if (c[1]=='=') oper=(*c++) +16; else oper=*c; + c++; + break; + default: c++; break; + } + if (opex) { + sign=1; + switch (oper) { + case 'c': value=value2; break; + case '-': value=value-value2; break; + case '+': value=value+value2; break; + case '*': value=value*value2; break; + case '/': if (value2) value=value/value2; break; + case '%': if (value2) value=value%value2; break; + case '<': value=(value<value2); break; + case '>': value=(value>value2); break; + case '>'+16: value=(value>=value2); break; + case '<'+16: value=(value<=value2); break; + case '=': case '='+16: value=(value==value2); break; + case '&': value = (value && value2); break; + case ':': value = (value || value2); break; + default: fprintf(stderr, + "man2html: Unknown operator %c.\n", oper); + } + oper=0; + } + } + if (*c==')') c++; + } + *result=value; + return c; +} + +static void +trans_char(char *c, char s, char t) { + char *sl = c; + int slash = 0; + + while (*sl && (*sl != '\n' || slash)) { + if (!slash) { + if (*sl == escapesym) + slash = 1; + else if (*sl == s) + *sl = t; + } else + slash = 0; + sl++; + } +} + +/* + * Read STR until end-of-line (not preceded by \). + * Find whitespace separated words, and store starts in WORDS of lth MAXN. + * Return number of words in N. + * Replace each end-of-word by the character EOW (usually \n or 0). + * Return pointer to last char seen (either \n or 0). + * + * A part \"... is skipped. + * Quotes not preceded by \ are replaced by \a. + */ +static char * +fill_words(char *str, char *words[], int maxn, int *n, char eow) { + char *s = str; + int backslash = 0; + int skipspace = 0; /* 1 if space is not end-of-word */ + + *n = 0; + words[*n] = s; + while (*s && (*s != '\n' || backslash)) { + if (!backslash) { + if (*s == '"') { + *s = '\a'; + skipspace = !skipspace; + } else if (*s == escapesym) { + backslash = 1; + } else if ((*s == ' ' || *s == '\t') && !skipspace) { + *s = eow; + if (words[*n] != s && *n < maxn-1) + (*n)++; + words[*n] = s+1; + } + } else { + if (*s == '"') { + s--; + *s = eow; + if (words[*n] != s && *n < maxn-1) + (*n)++; + s++; + while (*s && *s != '\n') s++; + words[*n] = s; + s--; + } + backslash = 0; + } + s++; + } + if (s != words[*n]) + (*n)++; + return s; +} + + +char *section_list[] = { + "1", "User Commands ", + "1C", "User Commands", + "1G", "User Commands", + "1S", "User Commands", + "1V", "User Commands ", + "2", "System Calls", + "2V", "System Calls", + "3", "C Library Functions", + "3C", "Compatibility Functions", + "3F", "Fortran Library Routines", + "3K", "Kernel VM Library Functions", + "3L", "Lightweight Processes Library", + "3M", "Mathematical Library", + "3N", "Network Functions", + "3R", "RPC Services Library", + "3S", "Standard I/O Functions", + "3V", "C Library Functions", + "3X", "Miscellaneous Library Functions", + "4", "Devices and Network Interfaces", + "4F", "Protocol Families", + "4I", "Devices and Network Interfaces", + "4M", "Devices and Network Interfaces", + "4N", "Devices and Network Interfaces", + "4P", "Protocols", + "4S", "Devices and Network Interfaces", + "4V", "Devices and Network Interfaces", + "5", "File Formats", + "5V", "File Formats", + "6", "Games and Demos", + "7", "Environments, Tables, and Troff Macros", + "7V", "Environments, Tables, and Troff Macros", + "8", "Maintenance Commands", + "8C", "Maintenance Commands", + "8S", "Maintenance Commands", + "8V", "Maintenance Commands", + "L", "Local Commands", +/* for Solaris: + "1", "User Commands", + "1B", "SunOS/BSD Compatibility Package Commands", + "1b", "SunOS/BSD Compatibility Package Commands", + "1C", "Communication Commands ", + "1c", "Communication Commands", + "1F", "FMLI Commands ", + "1f", "FMLI Commands", + "1G", "Graphics and CAD Commands ", + "1g", "Graphics and CAD Commands ", + "1M", "Maintenance Commands", + "1m", "Maintenance Commands", + "1S", "SunOS Specific Commands", + "1s", "SunOS Specific Commands", + "2", "System Calls", + "3", "C Library Functions", + "3B", "SunOS/BSD Compatibility Library Functions", + "3b", "SunOS/BSD Compatibility Library Functions", + "3C", "C Library Functions", + "3c", "C Library Functions", + "3E", "C Library Functions", + "3e", "C Library Functions", + "3F", "Fortran Library Routines", + "3f", "Fortran Library Routines", + "3G", "C Library Functions", + "3g", "C Library Functions", + "3I", "Wide Character Functions", + "3i", "Wide Character Functions", + "3K", "Kernel VM Library Functions", + "3k", "Kernel VM Library Functions", + "3L", "Lightweight Processes Library", + "3l", "Lightweight Processes Library", + "3M", "Mathematical Library", + "3m", "Mathematical Library", + "3N", "Network Functions", + "3n", "Network Functions", + "3R", "Realtime Library", + "3r", "Realtime Library", + "3S", "Standard I/O Functions", + "3s", "Standard I/O Functions", + "3T", "Threads Library", + "3t", "Threads Library", + "3W", "C Library Functions", + "3w", "C Library Functions", + "3X", "Miscellaneous Library Functions", + "3x", "Miscellaneous Library Functions", + "4", "File Formats", + "4B", "SunOS/BSD Compatibility Package File Formats", + "4b", "SunOS/BSD Compatibility Package File Formats", + "5", "Headers, Tables, and Macros", + "6", "Games and Demos", + "7", "Special Files", + "7B", "SunOS/BSD Compatibility Special Files", + "7b", "SunOS/BSD Compatibility Special Files", + "8", "Maintenance Procedures", + "8C", "Maintenance Procedures", + "8c", "Maintenance Procedures", + "8S", "Maintenance Procedures", + "8s", "Maintenance Procedures", + "9", "DDI and DKI", + "9E", "DDI and DKI Driver Entry Points", + "9e", "DDI and DKI Driver Entry Points", + "9F", "DDI and DKI Kernel Functions", + "9f", "DDI and DKI Kernel Functions", + "9S", "DDI and DKI Data Structures", + "9s", "DDI and DKI Data Structures", + "L", "Local Commands", +*/ + NULL, "Misc. Reference Manual Pages", + NULL, NULL +}; + +static char * +section_name(char *c) +{ + int i=0; + + if (!c) return ""; + while (section_list[i] && strcmp(c,section_list[i])) i=i+2; + if (section_list[i+1]) return section_list[i+1]; + else return c; +} + +int manidxlen = 0; +char *manidx = NULL; +int subs = 0; +int mip = 0; /* current offset in manidx[] */ +char label[5]="lbAA"; + +static void +manidx_need(int m) { + if (mip + m >= manidxlen) { + manidxlen += 10000; + manidx = xrealloc(manidx, manidxlen); + } +} + +static void +add_to_index(int level, char *item) +{ + char *c = NULL; + + label[3]++; + if (label[3]>'Z') { + label[3]='A'; + label[2]++; + } + + if (level != subs) { + manidx_need(6); + if (subs) { + strcpy(manidx+mip, "</DL>\n"); + mip += 6; + } else { + strcpy(manidx+mip, "<DL>\n"); + mip += 5; + } + } + subs = level; + + scan_troff(item, 1, &c); + manidx_need(100 + strlen(c)); + sprintf(manidx+mip, "<DT><A HREF=\"#%s\">%s</A><DD>\n", label, c); + if (c) free(c); + while (manidx[mip]) mip++; +} + +static char * +skip_till_newline(char *c) +{ + int lvl=0; + + while (*c && (*c!='\n' || lvl>0)) { + if (*c=='\\') { + c++; + if (*c=='}') lvl--; else if (*c=='{') lvl++; + } + c++; + } + c++; + if (lvl<0 && newline_for_fun) { + newline_for_fun = newline_for_fun+lvl; + if (newline_for_fun<0) newline_for_fun=0; + } + return c; +} + +int ifelseval=0; + +static char * +scan_request(char *c) { + /* BSD Mandoc stuff - by Michael Hamilton */ + static int mandoc_synopsis=0; /* True if we are in the synopsis section */ + static int mandoc_command=0; /* True if this is mandoc page */ + static int mandoc_bd_options; /* Only copes with non-nested Bd's */ + static int inXo=0; + + int i,j,mode = 0; + char *h; + char *wordlist[20]; + int words; + char *sl; + STRDEF *owndef; + + while (*c == ' ' || *c == '\t') + c++; + if (c[0] == '\n') + return c+1; + if (c[1] == '\n') + j = 1; + else + j = 2; + while (c[j] == ' ' || c[j] == '\t') + j++; + if (c[0] == escapesym) { + /* some pages use .\" .\$1 .\} */ + /* .\$1 is too difficult/stupid */ + if (c[1] == '$') + c = skip_till_newline(c); + else + c = scan_escape(c+1); + } else { + i=V(c[0],c[1]); + switch (i) { + case V('a','b'): + h=c+j; + while (*h && *h !='\n') h++; + *h=0; + if (scaninbuff && buffpos) { + buffer[buffpos]=0; + printf("%s\n", buffer); + } + fprintf(stderr, "%s\n", c+2); /* XXX */ + exit(0); + break; + case V('d','i'): + { + STRDEF *de; + c=c+j; + i=V(c[0],c[1]); + if (*c == '\n') { c++;break; } + while (*c && *c!='\n') c++; + c++; + h=c; + while (*c && strncmp(c,".di",3)) while (*c && *c++!='\n'); + *c=0; + de=strdef; + while (de && de->nr !=i) de=de->next; + if (!de) { + de=(STRDEF*) xmalloc(sizeof(STRDEF)); + de->nr=i; + de->slen=0; + de->next=strdef; + de->st=NULL; + strdef=de; + } else { + if (de->st) free(de->st); + de->slen=0; + de->st=NULL; + } + scan_troff(h,0,&de->st); + *c='.'; + while (*c && *c++!='\n'); + break; + } + case V('d','s'): + mode=1; + case V('a','s'): + { + STRDEF *de; + int oldcurpos=curpos; + c=c+j; + while (*c == ' ') c++; + i=V(c[0],c[1]); + j=0; + while (c[j] && c[j]!='\n') j++; + if (j<3) { c=c+j; break; } + if (c[1] == ' ') c=c+1; else c=c+2; + while (isspace(*c)) c++; + if (*c == '"') c++; + de=strdef; + while (de && de->nr != i) de=de->next; + single_escape=1; + curpos=0; + if (!de) { + char *h; + de=(STRDEF*) xmalloc(sizeof(STRDEF)); + de->nr=i; + de->slen=0; + de->next=strdef; + de->st=NULL; + strdef=de; + h=NULL; + c=scan_troff(c, 1, &h); + de->st=h; + de->slen=curpos; + } else { + if (mode) { /* .ds */ + char *h=NULL; + c=scan_troff(c, 1, &h); + free(de->st); /* segfault XXX */ + de->slen=curpos; + de->st=h; + } else { /* .as */ + c=scan_troff(c,1,&de->st); /* XXX */ + de->slen+=curpos; + } + } + single_escape=0; + curpos=oldcurpos; + } + break; + case V('b','r'): + if (still_dd) out_html("<DD>"); + else out_html("<BR>\n"); + curpos=0; + c=c+j; + if (c[0] == escapesym) { c=scan_escape(c+1); } + c=skip_till_newline(c);break; + case V('c','2'): + c=c+j; + if (*c!='\n') { nobreaksym=*c; } + else nobreaksym='\''; + c=skip_till_newline(c); + break; + case V('c','c'): + c=c+j; + if (*c!='\n') { controlsym=*c; } + else controlsym='.'; + c=skip_till_newline(c); + break; + case V('c','e'): + c=c+j; + if (*c == '\n') { i=1; } + else { + i=0; + while ('0'<=*c && *c<='9') { + i=i*10+*c-'0'; + c++; + } + } + c=skip_till_newline(c); + /* center next i lines */ + if (i>0) { + out_html("<CENTER>\n"); + while (i && *c) { + char *line=NULL; + c=scan_troff(c,1, &line); + if (line && strncmp(line, "<BR>", 4)) { + out_html(line); + out_html("<BR>\n"); + i--; + } + } + out_html("</CENTER>\n"); + curpos=0; + } + break; + case V('e','c'): + c=c+j; + if (*c!='\n') { escapesym=*c; } + else escapesym='\\'; + break; + c=skip_till_newline(c); + case V('e','o'): + escapesym=0; + c=skip_till_newline(c); + break; + case V('e','x'): + exit(0); + break; + case V('f','c'): + c=c+j; + if (*c == '\n') { + fieldsym=padsym=0; + } else { + fieldsym=c[0]; + padsym=c[1]; + } + c=skip_till_newline(c); + break; + case V('f','i'): + if (!fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("</PRE>\n"); + } + curpos=0; + fillout=1; + c=skip_till_newline(c); + break; + case V('f','t'): + c=c+j; + if (*c == '\n') { + out_html(change_to_font(0)); + } else { + if (*c == escapesym) { + int fn; + c=scan_expression(c, &fn); + c--; + out_html(change_to_font(fn)); + } else { + out_html(change_to_font(*c)); + c++; + } + } + c=skip_till_newline(c); + break; + case V('e','l'): + /* .el anything : else part of if else */ + if (ifelseval) { + c=c+j; + c[-1]='\n'; + c=scan_troff(c,1,NULL); + } else + c=skip_till_newline(c+j); + break; + case V('i','e'): + /* .ie c anything : then part of if else */ + case V('i','f'): + /* .if c anything + * .if !c anything + * .if N anything + * .if !N anything + * .if 'string1'string2' anything + * .if !'string1'string2' anything + */ + c=c+j; + c=scan_expression(c, &i); + ifelseval=!i; + if (i) { + *c='\n'; + c++; + c=scan_troff(c,1,NULL); + } else + c=skip_till_newline(c); + break; + case V('i','g'): /* .ig: ignore until .. */ + { + char *endwith="..\n"; + i=3; + c=c+j; + while (*c == ' ') c++; + if (*c == escapesym && c[1] == '"') + while (*c != '\n') c++; + if (*c!='\n') { /* .ig yy: ignore until .yy, then call .yy */ + endwith=c-1;i=1; + c[-1]='.'; + while (*c && *c!='\n') c++,i++; + } + c++; + while (*c && strncmp(c,endwith,i)) + while (*c && *c++!='\n'); + while (*c && *c++!='\n'); + break; + } + case V('n','f'): + if (fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("<PRE>\n"); + } + curpos=0; + fillout=0; + c=skip_till_newline(c); + break; + case V('p','s'): + c=c+j; + if (*c == '\n') { + out_html(change_to_size('0')); + } else { + j=0;i=0; + if (*c == '-') { j= -1;c++; } else if (*c == '+') { j=1;c++;} + c=scan_expression(c, &i); + if (!j) { j=1; if (i>5) i=i-10; } + out_html(change_to_size(i*j)); + } + c=skip_till_newline(c); + break; + case V('s','p'): + c=c+j; + if (fillout) out_html("<P>"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('s','o'): + { + FILE *f; + struct stat stbuf; + int l; char *buf; + char *name = NULL; + + curpos=0; + c += j; /* skip .so part and whitespace */ + if (*c == '/') { + h = c; + } else { /* .so man3/cpow.3 -> ../man3/cpow.3 */ + h = c-3; + h[0] = '.'; + h[1] = '.'; + h[2] = '/'; + } + while (*c != '\n') c++; + while (c[-1] == ' ') c--; + while (*c != '\n') *c++ = 0; + *c = 0; + scan_troff(h,1, &name); + if (name[3] == '/') h=name+3; else h=name; + l = 0; + if (stat(h, &stbuf)!=-1) l=stbuf.st_size; + buf = (char*) xmalloc((l+4)*sizeof(char)); +#if NOCGI + if (!out_length) { + char *t,*s; + t=strrchr(fname, '/'); + if (!t) t=fname; + fprintf(stderr, "ln -s %s.html %s.html\n", h, t); + s=strrchr(t, '.');if (!s) s=t; + printf("<HTML><HEAD><TITLE> Manpage of %s</TITLE>\n" + "</HEAD><BODY>\n" + "See the manpage for <A HREF=\"%s.html\">%s</A>.\n" + "</BODY></HTML>\n", + s, h, h); + } else +#endif + { + /* this works alright, except for section 3 */ + if (!l || !(f = fopen(h,"r"))) { + fprintf(stderr, + "man2html: unable to open or read file %s\n", h); + out_html("<BLOCKQUOTE>" + "man2html: unable to open or read file\n"); + out_html(h); + out_html("</BLOCKQUOTE>\n"); + } else { + i=fread(buf+1,1,l,f); + fclose(f); + buf[0]=buf[l]='\n'; + buf[l+1]=buf[l+2]=0; + scan_troff(buf+1,0,NULL); + } + if (buf) free(buf); + } + *c++='\n'; + break; + } + case V('t','a'): + c=c+j; + j=0; + while (*c!='\n') { + sl=scan_expression(c, &tabstops[j]); + if (*c == '-' || *c == '+') tabstops[j]+=tabstops[j-1]; + c=sl; + while (*c == ' ' || *c == '\t') c++; + if (j+1 < SIZE(tabstops)) + j++; + } + maxtstop=j; + curpos=0; + break; + case V('t','i'): +#if 0 + dl_down(); +#endif + out_html("<BR>\n"); + c=c+j; + c=scan_expression(c, &j); + for (i=0; i<j; i++) out_html(" "); + curpos=j; + c=skip_till_newline(c); + break; + case V('t','m'): + c=c+j; + h=c; + while (*c!='\n') c++; + *c=0; + fprintf(stderr,"%s\n", h); /* XXX */ + *c='\n'; + break; + case V('B',' '): + case V('B','\n'): + case V('I',' '): + case V('I','\n'): + /* parse one line in a certain font */ + out_html(change_to_font(*c)); + trans_char(c, '"', '\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','P'): /* groff manpages use this construction */ + /* .OP a b : [ <B>a</B> <I>b</I> ] */ + mode=1; + c[0]='B'; c[1]='I'; + out_html(change_to_font('R')); + out_html("["); + curpos++; + case V('B','R'): + case V('B','I'): + case V('I','B'): + case V('I','R'): + case V('R','B'): + case V('R','I'): + { + char font[2]; + font[0] = c[0]; font[1] = c[1]; + c = c+j; + if (*c == '\n') c++; + sl = fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + /* .BR name (section) + ** indicates a link. It will be added in the output routine. + */ + for (i=0; i<words; i++) { + if (mode) { out_html(" "); curpos++; } + wordlist[i][-1]=' '; + out_html(change_to_font(font[i&1])); + scan_troff(wordlist[i],1,NULL); + } + out_html(change_to_font('R')); + if (mode) { out_html(" ]"); curpos++;} + out_html(NEWLINE); if (!fillout) curpos=0; else curpos++; + } + break; + case V('D','T'): + maxtstop = SIZE(tabstops); + for (j=0; j<maxtstop; j++) + tabstops[j]=(j+1)*8; + c=skip_till_newline(c); break; + case V('I','P'): + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + dl_begin(); + if (words) { + scan_troff(wordlist[0], 1,NULL); + } + out_html("<DD>"); + curpos = 0; + break; + case V('T','P'): + dl_begin(); + c=skip_till_newline(c); + /* somewhere a definition ends with '.TP' */ + if (!*c) still_dd=1; else { + c=scan_troff(c,1,NULL); + out_html("<DD>"); + } + curpos=0; + break; + case V('I','X'): + /* general index */ + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + j = 4; + while (idxlabel[j] == 'Z') idxlabel[j--]='A'; + idxlabel[j]++; +#ifdef MAKEINDEX + if (idxfile) { + fprintf(idxfile, "%s@%s@", fname, idxlabel); + for (j=0; j<words; j++) { + h=NULL; + scan_troff(wordlist[j], 1, &h); + fprintf(idxfile, "_\b@%s", h); + free(h); + } + fprintf(idxfile,"\n"); + } +#endif + out_html("<A NAME=\""); + out_html(idxlabel); + /* this will not work in mosaic (due to a bug). + ** Adding ' ' between '>' and '<' solves it, but creates + ** some space. A normal space does not work. + */ + out_html("\"></A>"); + break; + case V('L','P'): + case V('P','P'): + dl_end(); + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('H','P'): + dl_begin(); + still_dd=1; + c=skip_till_newline(c); + curpos=0; + break; + case V('P','D'): + c=skip_till_newline(c); + break; + case V('R','s'): /* BSD mandoc */ + case V('R','S'): + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + j = 1; + if (words>0) scan_expression(wordlist[0], &j); + if (j>=0) { + dl_newlevel(); + c=skip_till_newline(c); + curpos=0; + break; + } + case V('R','e'): /* BSD mandoc */ + case V('R','E'): + dl_endlevel(); + c=skip_till_newline(c); + curpos=0; + break; + case V('S','B'): + out_html(change_to_size(-1)); + out_html(change_to_font('B')); + c=scan_troff(c+j, 1, NULL); + out_html(change_to_font('R')); + out_html(change_to_size('0')); + break; + case V('S','M'): + c=c+j; + if (*c == '\n') c++; + out_html(change_to_size(-1)); + trans_char(c,'"','\a'); + c=scan_troff(c,1,NULL); + out_html(change_to_size('0')); + break; + case V('S','s'): /* BSD mandoc */ + mandoc_command = 1; + case V('S','S'): + mode=1; + goto sh_below; + case V('S','h'): /* BSD mandoc */ + mandoc_command = 1; + case V('S','H'): + sh_below: + c=c+j; + if (*c == '\n') c++; + dl_down(); + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + trans_char(c,'"', '\a'); + add_to_index(mode, c); + out_html("<A NAME=\""); + out_html(label); + /* for mosaic users */ + if (mode) out_html("\"> </A>\n<H3>"); + else out_html("\"> </A>\n<H2>"); + mandoc_synopsis = (strncmp(c, "SYNOPSIS", 8) == 0); + c = (mandoc_command ? scan_troff_mandoc : scan_troff)(c,1,NULL); + if (mode) out_html("</H3>\n"); + else out_html("</H2>\n"); + curpos=0; + break; + case V('T','S'): + c=scan_table(c); + break; + case V('D','t'): /* BSD mandoc */ + mandoc_command = 1; + case V('T','H'): + if (!output_possible) { + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, 0); + *sl = 0; + if (words > 1) { + output_possible=1; + out_html("<HTML><HEAD><TITLE>Manpage of "); + out_html(wordlist[0]); + out_html("</TITLE>\n</HEAD><BODY>\n<H1>"); + out_html(wordlist[0]); + out_html("</H1>\nSection: "); + if (words>4) + out_html(wordlist[4]); + else + out_html(section_name(wordlist[1])); + out_html(" ("); + out_html(wordlist[1]); + if (words>2) { + out_html(")<BR>Updated: "); + scan_troff(wordlist[2], 1, NULL); + } else out_html(")"); + out_html("<BR><A HREF=\"#index\">Index</A>\n"); + man_page_html(0,0); /* Return to Main Contents */ + *sl='\n'; + out_html("<HR>\n"); + if (mandoc_command) out_html("<BR>BSD mandoc<BR>"); + } + c = sl+1; + } else + c = skip_till_newline(c); + curpos=0; + break; + case V('T','X'): + sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + *sl=0; + out_html(change_to_font('I')); + if (words>1) wordlist[1][-1]=0; + c=lookup_abbrev(wordlist[0]); + curpos+=strlen(c); + out_html(c); + out_html(change_to_font('R')); + if (words>1) + out_html(wordlist[1]); + *sl='\n'; + c=sl+1; + break; + case V('r','m'): + /* .rm xx : Remove request, macro or string */ + case V('r','n'): + /* .rn xx yy : Rename request, macro or string xx to yy */ + { + STRDEF *de; + c=c+j; + i=V(c[0],c[1]); + c=c+2; + while (isspace(*c) && *c!='\n') c++; + j=V(c[0],c[1]); + while (*c && *c!='\n') c++; + c++; + de=strdef; + while (de && de->nr!=j) de=de->next; + if (de) { + if (de->st) free(de->st); + de->nr=0; + } + de=strdef; + while (de && de->nr!=i) de=de->next; + if (de) de->nr=j; + break; + } + case V('n','x'): + /* .nx filename : next file. */ + case V('i','n'): + /* .in +-N : Indent */ + c=skip_till_newline(c); + break; + case V('n','r'): + /* .nr R +-N M: define and set number register R by +-N; + ** auto-increment by M + */ + { + INTDEF *intd; + c=c+j; + i=V(c[0],c[1]); + c=c+2; + intd=intdef; + while (intd && intd->nr!=i) intd=intd->next; + if (!intd) { + intd = (INTDEF*) xmalloc(sizeof(INTDEF)); + intd->nr=i; + intd->val=0; + intd->incr=0; + intd->next=intdef; + intdef=intd; + } + while (*c == ' ' || *c == '\t') c++; + c=scan_expression(c,&intd->val); + if (*c!='\n') { + while (*c == ' ' || *c == '\t') c++; + c=scan_expression(c,&intd->incr); + } + c=skip_till_newline(c); + break; + } + case V('a','m'): + /* .am xx yy : append to a macro. */ + /* define or handle as .ig yy */ + mode=1; + case V('d','e'): + /* .de xx yy : define or redefine macro xx; end at .yy (..) */ + /* define or handle as .ig yy */ + { + STRDEF *de; + int olen=0; + c=c+j; + sl=fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); + i=V(c[0],c[1]);j=2; + if (words == 1) wordlist[1]=".."; else { + wordlist[1]--; + wordlist[1][0]='.'; + j=3; + } + c=sl+1; + sl=c; + while (*c && strncmp(c,wordlist[1],j)) c=skip_till_newline(c); + de=defdef; + while (de && de->nr!= i) de=de->next; + if (mode && de) olen=strlen(de->st); + j=olen+c-sl; + h= (char*) xmalloc((j*2+4)*sizeof(char)); + if (h) { + for (j=0; j<olen; j++) + h[j]=de->st[j]; + if (!j || h[j-1]!='\n') + h[j++]='\n'; + while (sl!=c) { + if (sl[0] == '\\' && sl[1] == '\\') { + h[j++]='\\'; sl++; + } else + h[j++]=*sl; + sl++; + } + h[j]=0; + if (de) { + if (de->st) free(de->st); + de->st=h; + } else { + de = (STRDEF*) xmalloc(sizeof(STRDEF)); + de->nr=i; + de->next=defdef; + de->st=h; + defdef=de; + } + } + } + c=skip_till_newline(c); + break; + + /* ----- BSD mandoc stuff below ----- */ + case V('U','x'): /* BSD mandoc */ + c=c+j; + out_html("UNIX"); + c=skip_till_newline(c); + break; + case V('A','t'): /* BSD mandoc - called with arg V */ + c=c+j; + out_html("AT&T System"); + break; + case V('B','l'): /* BSD mandoc */ + { + char *nl, t=0 /* just for gcc */; + c=c+j; + nl = strchr(c,'\n'); + if (nl) { + t = *nl; + *nl = 0; + } + if (strstr(c, "-bullet")) /* HTML Unnumbered List */ + dl_newlevel_type(UL); + else if (strstr(c, "-enum")) /* HTML Ordered List */ + dl_newlevel_type(OL); + else /* HTML Descriptive List */ + dl_newlevel_type(DL); + if (nl) + *nl = t; + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + } + case V('E','l'): /* BSD mandoc */ + c=c+j; + dl_endlevel_type(); + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('I','t'): /* BSD mandoc */ + c=c+j; + if (dl_type(DL)) { + out_html("<DT>"); + out_html(change_to_font('B')); + if (*c == '\n') { + /* Don't allow embedded comms after a newline */ + c++; + c=scan_troff(c,1,NULL); + } else { + /* Do allow embedded comms on the same line. */ + c=scan_troff_mandoc(c,1,NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (inXo) + still_dd = 1; + else + out_html("<DD>"); + } else if (dl_type(UL) || dl_type(OL)) { + out_html("<LI>"); + c=scan_troff_mandoc(c,1,NULL); + out_html(NEWLINE); + } + if (fillout) curpos++; else curpos=0; + break; + case V('X','o'): /* BSD mandoc */ + c=c+j; + inXo = 1; + break; + case V('X','c'): /* BSD mandoc - Xc closes an Xo */ + c=c+j; + if (inXo) { + if (still_dd) + out_html("<DD>"); + inXo = 0; + } + break; + case V('S','m'): /* BSD mandoc - called with arg on/off */ + c=skip_till_newline(c); + break; + case V('B','k'): /* BSD mandoc */ + case V('E','k'): /* BSD mandoc */ + case V('D','d'): /* BSD mandoc */ + case V('O','s'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('B','t'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + out_html(" is currently in beta test."); + if (fillout) curpos++; else curpos=0; + break; + case V('B','x'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("BSD "); + c=scan_troff_mandoc(c, 1, NULL); + if (fillout) curpos++; else curpos=0; + break; + case V('D','l'): /* BSD mandoc */ + c=c+j; + out_html(NEWLINE); + out_html("<BLOCKQUOTE>"); + out_html(change_to_font('L')); + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("</BLOCKQUOTE>"); + if (fillout) curpos++; else curpos=0; + break; + case V('B','d'): /* BSD mandoc */ + { /* Seems like a kind of example/literal mode */ + char *nl, t=0 /* just for gcc */; + c=c+j; + nl = strchr(c,'\n'); + if (nl) { + t = *nl; + *nl = 0; + } + out_html(NEWLINE); + mandoc_bd_options = 0; /* Remember options for terminating Bl */ + if (strstr(c, "-offset indent")) { + mandoc_bd_options |= BD_INDENT; + out_html("<BLOCKQUOTE>\n"); + } + if (strstr(c, "-literal") || strstr(c, "-unfilled")) { + if (fillout) { + mandoc_bd_options |= BD_LITERAL; + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("<PRE>\n"); + } + curpos=0; + fillout=0; + } + if (nl) + *nl = t; + c=skip_till_newline(c); + break; + } + case V('E','d'): /* BSD mandoc */ + if (mandoc_bd_options & BD_LITERAL) { + if (!fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("</PRE>\n"); + } + } + if (mandoc_bd_options & BD_INDENT) + out_html("</BLOCKQUOTE>\n"); + curpos=0; + fillout=1; + c=skip_till_newline(c); + break; + case V('B','e'): /* BSD mandoc */ + c=c+j; + if (fillout) out_html("<P>"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('X','r'): /* BSD mandoc */ + { + /* Translate xyz 1 to xyz(1) + * Allow for multiple spaces. Allow the section to be missing. + */ + char buff[100]; + char *bufptr; + trans_char(c,'"','\a'); + bufptr = buff; + c = c+j; + if (*c == '\n') c++; /* Skip spaces */ + while (isspace(*c) && *c != '\n') c++; + while (isalnum(*c) && bufptr < buff + SIZE(buff)-4) { + /* Copy the xyz part */ + *bufptr++ = *c++; + } + while (isspace(*c) && *c != '\n') c++; /* Skip spaces */ + if (isdigit(*c)) { /* Convert the number if there is one */ + *bufptr++ = '('; + while (isalnum(*c) && bufptr < buff + SIZE(buff)-3) { + *bufptr++ = *c++; + } + *bufptr++ = ')'; + } + while (*c != '\n' && bufptr < buff + SIZE(buff)-2) { + /* Copy the remainder */ + if (!isspace(*c)) { + *bufptr++ = *c; + } + c++; + } + *bufptr++ = '\n'; + *bufptr = 0; + scan_troff_mandoc(buff, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + } + break; + case V('F','l'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + out_html("-"); + if (*c!='\n') { + out_html(change_to_font('B')); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + } + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('P','a'): /* BSD mandoc */ + case V('P','f'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('P','p'): /* BSD mandoc */ + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('D','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("``"); + c=scan_troff_mandoc(c, 1, NULL); + out_html("''"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','p'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('R')); + out_html("["); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','o'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('R')); + out_html("["); + c=scan_troff_mandoc(c, 1, NULL); + if (fillout) curpos++; else curpos=0; + break; + case V('O','c'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + if (fillout) curpos++; else curpos=0; + break; + case V('P','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("("); + c=scan_troff_mandoc(c, 1, NULL); + out_html(")"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('Q','l'): /* BSD mandoc */ + { /* Single quote first word in the line */ + char *sp; + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + sp = c; + do { /* Find first whitespace after the + * first word that isn't a mandoc macro + */ + while (*sp && isspace(*sp)) sp++; + while (*sp && !isspace(*sp)) sp++; + } while (*sp && isupper(*(sp-2)) && islower(*(sp-1))); + + /* Use a newline to mark the end of text to + * be quoted + */ + if (*sp) *sp = '\n'; + out_html("`"); /* Quote the text */ + c=scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + } + case V('S','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("`"); + c=scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('A','r'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') { /* An empty Ar means "file ..." */ + out_html("file ..."); + } else { + c=scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('A','d'): /* BSD mandoc */ + case V('E','m'): /* BSD mandoc */ + case V('V','a'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('N','d'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(" - "); + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('N','m'): /* BSD mandoc */ + { + static char *mandoc_name = 0; + trans_char(c,'"','\a'); + c=c+j; + if (mandoc_synopsis) { + /* + * Break lines only in the Synopsis. + * The Synopsis section seems to be treated + * as a special case - Bummer! + */ + static int count = 0; /* Don't break on the first Nm */ + if (count) { + out_html("<BR>"); + } else { + char *end, t=0 /* just for gcc */; + end = strchr(c, '\n'); + if (end) { + t = *end; + *end = 0; + } + if (mandoc_name) + free(mandoc_name); + mandoc_name = xstrdup(c); + if (end) + *end = t; + } + count++; + } + out_html(change_to_font('B')); + while (*c == ' ' || *c == '\t') c++; + if (*c == '\n') { + /* + * If Nm has no argument, use one from an earlier + * Nm command that did have one. Hope there aren't + * too many commands that do this. + */ + if (mandoc_name) + out_html(mandoc_name); + } else { + c=scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + } + case V('C','d'): /* BSD mandoc */ + case V('C','m'): /* BSD mandoc */ + case V('I','c'): /* BSD mandoc */ + case V('M','s'): /* BSD mandoc */ + case V('O','r'): /* BSD mandoc */ + case V('S','y'): /* BSD mandoc */ + /* parse one line in bold */ + out_html(change_to_font('B')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('D','v'): /* BSD mandoc */ + case V('E','v'): /* BSD mandoc */ + case V('F','r'): /* BSD mandoc */ + case V('L','i'): /* BSD mandoc */ + case V('N','o'): /* BSD mandoc */ + case V('N','s'): /* BSD mandoc */ + case V('T','n'): /* BSD mandoc */ + case V('n','N'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('B')); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('%','A'): /* BSD mandoc biblio stuff */ + case V('%','D'): + case V('%','N'): + case V('%','O'): + case V('%','P'): + case V('%','Q'): + case V('%','V'): + c=c+j; + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ + if (fillout) curpos++; else curpos=0; + break; + case V('%','B'): + case V('%','J'): + case V('%','R'): + case V('%','T'): + c=c+j; + out_html(change_to_font('I')); + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ + out_html(change_to_font('R')); + if (fillout) curpos++; else curpos=0; + break; + /* ----- end of BSD mandoc stuff ----- */ + + default: + /* search macro database of self-defined macros */ + owndef = defdef; + while (owndef && owndef->nr!=i) owndef=owndef->next; + if (owndef) { + char **oldargument; + int deflen; + int onff; + sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + c=sl+1; + *sl=0; + for (i=1; i<words; i++) + wordlist[i][-1]=0; + for (i=0; i<words; i++) { + char *h=NULL; + if (mandoc_command) + scan_troff_mandoc(wordlist[i],1,&h); + else + scan_troff(wordlist[i],1,&h); + wordlist[i]=h; + } + for (i=words; i<SIZE(wordlist); i++) + wordlist[i]=NULL; + deflen = strlen(owndef->st); + owndef->st[deflen+1]='a'; + for (i=0; (owndef->st[deflen+2+i] = owndef->st[i]); i++); + oldargument=argument; + argument=wordlist; + onff=newline_for_fun; + if (mandoc_command) + scan_troff_mandoc(owndef->st+deflen+2, 0, NULL); + else + scan_troff(owndef->st+deflen+2, 0, NULL); + newline_for_fun=onff; + argument=oldargument; + for (i=0; i<words; i++) if (wordlist[i]) free(wordlist[i]); + *sl='\n'; + } else if (mandoc_command && + ((isupper(*c) && islower(c[1])) + || (islower(*c) && isupper(c[1])))) { + /* + * Let through any BSD mandoc commands that haven't + * been dealt with. + * I don't want to miss anything out of the text. + */ + char buf[4]; + strncpy(buf,c,2); + buf[2] = ' '; + buf[3] = 0; + out_html(buf); /* Print the command (it might just be text). */ + c=c+j; + trans_char(c,'"','\a'); + if (*c == '\n') c++; /* really? */ + out_html(change_to_font('R')); + c=scan_troff(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + } else + c=skip_till_newline(c); + break; + } + } + if (fillout) { out_html(NEWLINE); curpos++; } + NEWLINE[0]='\n'; + return c; +} + +static int contained_tab=0; +static int mandoc_line=0;/* Signals whether to look for embedded mandoc cmds */ + +static char * +scan_troff(char *c, int san, char **result) { /* san : stop at newline */ + char *h; + char intbuff[500]; + int ibp=0; +#define FLUSHIBP if (ibp) { intbuff[ibp]=0; out_html(intbuff); ibp=0; } + char *exbuffer; + int exbuffpos, exbuffmax, exscaninbuff, exnewline_for_fun; + int usenbsp = 0; + + exbuffer = buffer; + exbuffpos = buffpos; + exbuffmax = buffmax; + exnewline_for_fun = newline_for_fun; + exscaninbuff = scaninbuff; + newline_for_fun = 0; + if (result) { + if (*result) { + buffer = *result; + buffpos = strlen(buffer); + buffmax = buffpos; + } else { + buffer = (char *) xmalloc(1000*sizeof(char)); + buffpos = 0; + buffmax = 1000; + } + scaninbuff = 1; + } + h = c; + /* start scanning */ + while (*h && (!san || newline_for_fun || *h != '\n')) { + if (*h == escapesym) { + h++; + FLUSHIBP; + h = scan_escape(h); + } else if (*h == controlsym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else if (mandoc_line + && *(h) && isupper(*(h)) + && *(h+1) && islower(*(h+1)) + && *(h+2) && isspace(*(h+2))) { + /* BSD imbedded command eg ".It Fl Ar arg1 Fl Ar arg2" */ + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else if (*h == nobreaksym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else { + if (h[-1] == '\n' && still_dd && isalnum(*h)) { + /* sometimes a .HP request is not followed by a .br request */ + FLUSHIBP; + out_html("<DD>"); + curpos=0; + still_dd=0; + } + switch (*h) { + case '&': + intbuff[ibp++]='&'; + intbuff[ibp++]='a'; + intbuff[ibp++]='m'; + intbuff[ibp++]='p'; + intbuff[ibp++]=';'; + curpos++; + break; + case '<': + intbuff[ibp++]='&'; + intbuff[ibp++]='l'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '>': + intbuff[ibp++]='&'; + intbuff[ibp++]='g'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '"': + intbuff[ibp++]='&'; + intbuff[ibp++]='q'; + intbuff[ibp++]='u'; + intbuff[ibp++]='o'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '\n': + if (h[-1] == '\n' && fillout) { + intbuff[ibp++]='<'; + intbuff[ibp++]='P'; + intbuff[ibp++]='>'; + } + if (contained_tab && fillout) { + intbuff[ibp++]='<'; + intbuff[ibp++]='B'; + intbuff[ibp++]='R'; + intbuff[ibp++]='>'; + } + contained_tab=0; + curpos=0; + usenbsp=0; + intbuff[ibp++]='\n'; + break; + case '\t': + { + int curtab=0; + contained_tab=1; + FLUSHIBP; + /* like a typewriter, not like TeX */ + tabstops[SIZE(tabstops)-1] = curpos+1; + while (curtab < maxtstop && tabstops[curtab] <= curpos) + curtab++; + if (curtab < maxtstop) { + if (!fillout) { + while (curpos<tabstops[curtab]) { + intbuff[ibp++]=' '; + if (ibp>480) { FLUSHIBP; } + curpos++; + } + } else { + out_html("<TT>"); + while (curpos < tabstops[curtab]) { + out_html(" "); + curpos++; + } + out_html("</TT>"); + } + } + } + break; + default: + if (*h == ' ' && (h[-1] == '\n' || usenbsp)) { + FLUSHIBP; + if (!usenbsp && fillout) { + out_html("<BR>"); + curpos=0; + } + usenbsp=fillout; + if (usenbsp) out_html(" "); else intbuff[ibp++]=' '; + } else if (*h > 31 && *h < 127) { + intbuff[ibp++]=*h; + } else if (((unsigned char)(*h)) > 127) { +#ifdef NO_8BIT + intbuff[ibp++]='&'; + intbuff[ibp++]='#'; + intbuff[ibp++]='0'+((unsigned char)(*h))/100; + intbuff[ibp++]='0'+(((unsigned char)(*h))%100)/10; + intbuff[ibp++]='0'+((unsigned char)(*h))%10; + intbuff[ibp++]=';'; +#else + intbuff[ibp++]=*h; +#endif + } + curpos++; + break; + } + if (ibp>480) FLUSHIBP; + h++; + } + } + FLUSHIBP; + if (buffer) buffer[buffpos]=0; + if (san && *h) h++; + newline_for_fun=exnewline_for_fun; + if (result) { + *result = buffer; + buffer=exbuffer; + buffpos=exbuffpos; + buffmax=exbuffmax; + scaninbuff=exscaninbuff; + } + return h; +} + +static char *scan_troff_mandoc(char *c, int san, char **result) { + char *ret, *end = c; + int oldval = mandoc_line; + mandoc_line = 1; + while (*end && *end != '\n') { + end++; + } + + if (end > c + 2 + && ispunct(*(end - 1)) + && isspace(*(end - 2)) && *(end - 2) != '\n') { + /* + * Don't format lonely punctuation. E.g. in "xyz ," format + * the xyz and then append the comma removing the space. + */ + *(end - 2) = '\n'; + ret = scan_troff(c, san, result); + *(end - 2) = *(end - 1); + *(end - 1) = ' '; + } else { + ret = scan_troff(c, san, result); + } + mandoc_line = oldval; + return ret; +} + +STRDEF *foundpages=NULL; + +static void +error_page(char *s, char *t, ...) { + va_list p; + + printf("<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n" + "<BODY>\n<H1>%s</H1>\n", s, s); + va_start(p, t); + vfprintf(stdout, t, p); + va_end(p); + printf("</BODY></HTML>\n"); + exit(0); +} + +char * +xstrdup(const char *s) { + char *p = strdup(s); + if (p == NULL) + error_page("Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +void * +xmalloc(size_t size) { + void *p = malloc(size); + if (p == NULL) + error_page("Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +void * +xrealloc(void *ptr, size_t size) { + void *p = realloc(ptr,size); + if (p == NULL) + error_page("Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +static void +usage(void) { + error_page("man2html: bad invocation", + "Call: man2html [-l|-h host.domain:port] [-p|-q] [filename]\n" + "or: man2html -r [filename]\n"); +} + +static void +goto_dir(char *path, char **dir, char **name) { + char *s, *t, *u; + + s = xstrdup(path); + t = strrchr(s, '/'); + if (t) { + *t = 0; + u = strrchr(s, '/'); + *t = '/'; + if (u) { + *u = 0; + if (chdir(s) == 0) { + if (dir) + *dir = s; + if (name) + *name = u+1; + } +#if 0 + else /* complain or not - this need not be fatal */ + error_page("Error", "man2html: could not chdir to %s", s); +#endif + } + } +} + +/* + * Call: man2html [-l] [filename] + * + * The contents of FILENAME (or STDIN, in case FILENAME is "-" or absent) + * are converted from man-style nroff to html, and printed on STDOUT. + * + * Possible errors are reflected in the output. The return status is 0. + */ +int +main(int argc, char **argv) { + FILE *f; + struct stat stbuf; + int l, c; + char *buf, *filename, *fnam = NULL; + +#ifdef __CYGWIN__ + int opterr; + + extern int optind; + extern char *optarg; +#endif + + printf("Content-type: text/html\n\n"); + + opterr = 0; /* no stderr error messages */ + while ((c = getopt (argc, argv, "D:E:hH:lL:M:pqr?vVf")) != -1) { + switch(c) { + case 'D': + goto_dir(optarg, 0, 0); break; + case 'E': + error_page("Error", "%s", optarg); break; + case 'h': + set_cgibase("localhost"); break; + case 'H': + set_cgibase(optarg); break; + case 'l': + set_lynxcgibase("/home/httpd"); break; + case 'L': + set_lynxcgibase(optarg); break; + case 'M': + set_man2htmlpath(optarg); break; + case 'p': + set_separator('/'); break; + case 'q': + set_separator('?'); break; + case 'r': + set_relative_html_links(); break; + case 'v': + case 'V': + error_page("Version", "%s from man-%s", argv[0], version); + exit(0); + case '?': + default: + usage(); + case 'f': /* It is rumoured that some other + incarnation of man2html uses this flag; + ignore when given for compatibility. */ + /* case 'F': this will assign a format for man_page_html() */ + break; + } + } + + /* Find filename */ + if (argc == optind+1) + fnam = argv[optind]; + else if (argc != optind) + usage(); + + filename = fnam; + directory = 0; + + /* Open input file */ + if (!fnam || !strcmp(fnam, "-")) { + f = stdin; + fname = "(stdin)"; + } else { + /* do a chdir() first, to get .so expansion right */ + goto_dir(fnam, &directory, &fnam); + + f = fopen(fnam, "r"); + if (f == NULL) + error_page("File not found", "Could not open %s\n", filename); + fname = fnam; + } + + /* Read entire file into buf[1..l] */ +#define XTRA 5 + /* buf has 1 extra byte at the start, and XTRA extra bytes at the end */ + if (f == stdin) { + int sz = 1024; + int ct = 1, tot = 0; + char *p = NULL; + + clearerr(stdin); + while (ct > 0) { + tot += ct; + if (feof(stdin)) + break; + sz = 2*sz+tot; + p = xrealloc(p, sz); + ct = fread(p+tot,1,sz-tot-XTRA,stdin); + } + + buf = p; + l = tot-1; + } else { + int ct; + + l = 0; + if (fstat(fileno(f), &stbuf) != -1) + l = stbuf.st_size; + buf = (char *) xmalloc((l+1+XTRA)*sizeof(char)); + ct = fread(buf+1,1,l,f); + if (ct < l) + l = ct; + fclose(f); + } + + buf[0] = '\n'; + buf[l+1] = '\n'; + buf[l+2] = buf[l+3] = 0; + +#ifdef MAKEINDEX + idxfile = fopen(INDEXFILE, "a"); +#endif + stdinit(); + + scan_troff(buf+1,0,NULL); + dl_down(); + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + out_html(NEWLINE); + if (output_possible) { + /* for mosaic users */ + printf("<HR>\n<A NAME=\"index\"> </A><H2>Index</H2>\n<DL>\n"); + manidx[mip]=0; + printf("%s", manidx); + if (subs) printf("</DL>\n"); + printf("</DL>\n"); + print_sig(); + printf("</BODY>\n</HTML>\n"); + } else { + if (!filename) + filename = fname; + if (*filename == '/') + error_page("Invalid Manpage", + "The requested file %s is not a valid (unformatted) " + "man page.\nIf the file is a formatted manpage, " + "you could try to load the\n" + "<A HREF=\"file://localhost%s\">plain file</A>.\n", + filename, filename); + else + error_page("Invalid Manpage", + "The requested file %s is not a valid (unformatted) " + "man page.", filename); + } + if (idxfile) + fclose(idxfile); + if (buf) + free(buf); + return 0; +} diff --git a/man2html/scripts/cgi-aux/man/man.aux b/man2html/scripts/cgi-aux/man/man.aux new file mode 100644 index 0000000..e381b01 --- /dev/null +++ b/man2html/scripts/cgi-aux/man/man.aux @@ -0,0 +1,75 @@ +Content-type: text/html + +<HTML> +<HEAD> +<TITLE>Manual Pages - Main Contents</TITLE> +<!-- Note: this is not html, but requires preprocessing --> +<!-- It is used by /home/httpd/cgi-bin/man/man2html --> +</HEAD> +<BODY> +<H1>Manual Pages - Main Contents</H1> +<HR> + +<H2>Name and Section lookup</H2> +<ISINDEX> + +%lynx <i>Start a query</i> by typing an s. +You can enter a program name, possibly preceded by the section, +the directories to search (with -M) or a full name. +For example: +<UL> + <LI><TT>find</TT> + <LI><TT>1 find</TT> + <LI><TT>-M /usr/man:/usr/X11R6/man:/usr/lib/perl5/man find</TT> + <LI><TT>/local/gcc/man/man1/gperf.1</TT> +</UL> + +<HR> + +<H2>Index of pages by name and description</H2> +Sections: + <A HREF="%cg/manwhatis?%cg+1">1. User Commands</A>; + <A HREF="%cg/manwhatis?%cg+2">2. System Calls</A>; + <A HREF="%cg/manwhatis?%cg+3">3. Library Functions</A>; + <A HREF="%cg/manwhatis?%cg+4">4. Special Files</A>; + <A HREF="%cg/manwhatis?%cg+5">5. File Formats</A>; + <A HREF="%cg/manwhatis?%cg+6">6. Games</A>; + <A HREF="%cg/manwhatis?%cg+7">7. Miscellany</A>; + <A HREF="%cg/manwhatis?%cg+8">8. Administration and Privileged Commands</A>; + <A HREF="%cg/manwhatis?%cg+l">l. Postgresql Commands</A>; + <A HREF="%cg/manwhatis?%cg+n">n. Tcl Commands</A>. +<P> +<HR> +<H2>Index of pages by name only</H2> + <A HREF="%cg/mansec?%cg+1">1. User Commands</A>; + <A HREF="%cg/mansec?%cg+2">2. System Calls</A>; + <A HREF="%cg/mansec?%cg+3">3. Library Functions</A>; + <A HREF="%cg/mansec?%cg+4">4. Special Files</A>; + <A HREF="%cg/mansec?%cg+5">5. File Formats</A>; + <A HREF="%cg/mansec?%cg+6">6. Games</A>; + <A HREF="%cg/mansec?%cg+7">7. Miscellany</A>; + <A HREF="%cg/mansec?%cg+8">8. Administration and Privileged Commands</A>; + <A HREF="%cg/mansec?%cg+l">l. Postgresql Commands</A>; + <A HREF="%cg/mansec?%cg+n">n. Tcl Commands</A>; + <A HREF="%cg/mansec?%cg+all">All Sections</A>. +<P> +<hr> + +<H2>Manual Pages full text search</H2> + +<A HREF="%cg/mansearch"> +Search the full text of the Manual Pages. +</A> + +<P> +<HR> + +The original man2html program and scripts are due to +<A HREF="http://wsinwp01.win.tue.nl:1234/index.html"> +Richard Verhoeven</A> and +<A HREF="mailto:michael@actrix.gen.nz"> +Michael Hamilton</A>. +This version is from man-1.6g maintained by <A HREF="mailto:flucifredi@acm.org"> +Federico Lucifredi</A>. +</body> +</HTML> diff --git a/man2html/scripts/cgi-aux/man/mansearch.aux b/man2html/scripts/cgi-aux/man/mansearch.aux new file mode 100644 index 0000000..f1d19a2 --- /dev/null +++ b/man2html/scripts/cgi-aux/man/mansearch.aux @@ -0,0 +1,49 @@ +Content-type: text/html + +<HTML> +<HEAD> +<TITLE>Manual Pages - Text Search</TITLE> +<!-- Changed by: Michael Hamilton, 6-Apr-1996 --> +<!-- Note: this is not html, but requires preprocessing --> +</HEAD> +<BODY> +<H1>Manual Pages - Text Search</H1> + +<A HREF="%cg/man2html">Return to Main Contents</A> +<P> +<ISINDEX> + +%lynx <i>Start a query</i> by typing an s. + +Examples: +<UL> + <LI><TT>pwd;directory</TT> - Find both in the same man page. + <LI><TT>pwd,directory</TT> - Find either. + <LI><TT>pwd directory</TT> - Find the exact phrase. + <LI><TT>-F 1 pwd</TT> - Look in section 1 only. + <LI><TT>-B glipmse</TT> - Find the best match (allow for misspelling). + <LI><TT>-L 0:10 pwd</TT> - Only show the first 10 man pages matched. +</UL> + +<HR> +<P> +The index uses the <I>Glimpse</I> +(<A HREF="%cg/man2html?1+glimpse">glimpse(1)</A>) +text indexing system. Many of the glimpse +options, regular expressions, and wildcards are valid: +see the <A HREF="%cg/mansearchhelp">help page</A> for a summary. +<P> +<HR> + +<P> +Glimpse +was developed by Udi Manber and Burra Gopal of the University of +Arizona, and Sun Wu of the National Chung-Cheng University, Taiwan. +You may contact the authors at <A HREF="mailto:glimpse@cs.arizona.edu"> +glimpse@cs.arizona.edu</A> +<P> +The Manual Page text search interface was created for Linux by +<A HREF="mailto:michael@actrix.gen.nz"> +Michael Hamilton</A>. +</BODY> +</HTML> diff --git a/man2html/scripts/cgi-aux/man/mansearchhelp.aux b/man2html/scripts/cgi-aux/man/mansearchhelp.aux new file mode 100644 index 0000000..200b509 --- /dev/null +++ b/man2html/scripts/cgi-aux/man/mansearchhelp.aux @@ -0,0 +1,295 @@ +Content-type: text/html + +<HTML> +<HEAD> +<TITLE>Manual Pages - Search Help</TITLE> +<!-- Changed by: Michael Hamilton, 6-Apr-1996 --> +<!-- Note: this is not html, but requires preprocessing --> +</HEAD> +<BODY> +<H1>Manual Pages - Search Help</H1> + +<A HREF="%cg/mansearch">Perform another search</A> +<BR> +<A HREF="%cg/man2html">Return to Main Contents</A> +<P> +<HR> +<P> +The full text index uses the <I>Glimpse</I> text indexing system. +The +<A HREF="%cg/man2html?1+glimpse">glimpse(1)</A> +manual page documents glimpse in full. This summary documents those +features of glimpse that are valid when searching through the manual pages. +<P> +<HR> + +<H2>Search Options</H2> + +The following search options must be at the start of the search string. + +<DL COMPACT> + +<DT><B>-</B> <I>#</I> +<DD> +<I>#</I> is an integer between 1 and 8 +specifying the maximum number of errors +permitted in finding the approximate matches (the default is zero). +Generally, each insertion, deletion, or substitution counts as one error. +Since the index stores only lower case characters, errors of +substituting upper case with lower case may be missed. + +<DT><B>-B</B> +<DD> +Best match mode. (Warning: -B sometimes misses matches. It is safer +to specify the number of errors explicitly.) +When -B is specified and no exact matches are found, glimpse +will continue to search until the closest matches (i.e., the ones +with minimum number of errors) +are found. +In general, -B may be slower than -#, but not by very much. +Since the index stores only lower case characters, errors of +substituting upper case with lower case may be missed. + +<DT><B>-L <I>x</I> | <I>x</I>:<I>y</I> | <I>x</I>:<I>y</I>:<I>z</I></B> +<DD> +A non-zero value of <I>x</I> limits the number of matches +that will be shown. +A non-zero value of <I>y</I> limits the number of man pages +that will be shown. +A non-zero valye of <I>z</I> will only show pages that have +less that z matches. +For example, -L 0:10 will output all matches for the first 10 files that +contain a match. + +<DT><B>-F</B> <I>pattern</I> +<DD> +The -F option provides a pattern that restricts the search results to +those filenames that match the pattern. +or example, <I>-F 8</I> effectively restricts matches to section 8. + +<DT><B>-w</B> +<DD> +Search for the pattern as a word - i.e., surrounded by non-alphanumeric +characters. For example, +<I>-w -1 car</I> will match cars, but not characters and not +car10. +The non-alphanumeric <I>must</I> +surround the match; they cannot be counted as errors. +This option does not work with regular expressions. + +<DT><B>-W</B> +<DD> +The default for Boolean AND queries is that they cover one record +(the default for a record is one line) at a time. +For example, glimpse 'good;bad' will output all lines containing +both 'good' and 'bad'. +The -W option changes the scope of Booleans to be the whole file. +Within a file glimpse will output all matches to any of the patterns. +So, glimpse -W 'good;bad' will output all lines containing 'good' +<I>or</I> 'bad', but only in files that contain both patterns. + +<DT><B>-k</B> +<DD> +No symbol in the pattern is treated as a meta character. +For example, <I>-k a(b|c)*d</I> will find +the occurrences of a(b|c)*d whereas <I>a(b|c)*d</I> +will find substrings that match the regular expression 'a(b|c)*d'. +(The only exception is ^ at the beginning of the pattern and $ at the +end of the pattern, which are still interpreted in the usual way. +Use \^ or \$ if you need them verbatim.) + +</DL> + +<P> +<HR> + +<H2>Patterns</H2> + +<I>Glimpse</I> +supports a large variety of patterns, including simple +strings, strings with classes of characters, sets of strings, +wild cards, and regular expressions (see <A HREF="#limitations">LIMITATIONS</A>). + +<DL COMPACT> +<DT><B>Strings </B><DD> +Strings are any sequence of characters, including the special symbols +`^' for beginning of line and `$' for end of line. +The following special characters ( +`<B>$</B>', + +`^<B>',</B> + +`<B>*</B>', + +`<B>[</B>'<B>,</B> + +`<B>^</B>', + +`<B>|</B>', + +`<B>(</B>', + +`<B>)</B>', + +`<B>!</B>', + +and +`<B>\</B>' + +) +as well as the following meta characters special to glimpse (and agrep): +`<B>;</B>', + +`<B>,</B>', + +`<B>#</B>', + +`<B><</B>', + +`<B>></B>', + +`<B>-</B>', + +and +`<B>.</B>', + +should be preceded by `\' if they are to be matched as regular +characters. For example, \^abc\\ corresponds to the string ^abc\, +whereas ^abc corresponds to the string abc at the beginning of a +line. +<DT><B>Classes of characters</B><DD> +a list of characters inside [] (in order) corresponds to any character +from the list. For example, [a-ho-z] is any character between a and h +or between o and z. The symbol `^' inside [] complements the list. +For example, [^i-n] denote any character in the character set except +character 'i' to 'n'. +The symbol `^' thus has two meanings, but this is consistent with +egrep. +The symbol `.' (don't care) stands for any symbol (except for the +newline symbol). +<DT><B>Boolean operations</B><DD> +<B>Glimpse </B> + +supports an `AND' operation denoted by the symbol `;' +an `OR' operation denoted by the symbol `,', +or any combination. +For example, +<I>glimpse 'pizza;cheeseburger'</I> will output all lines containing +both patterns. +<I>glimpse -F 'gnu;\.c$' 'define;DEFAULT'</I> +will output all lines containing both 'define' and 'DEFAULT' +(anywhere in the line, not necessarily in order) in +files whose name contains 'gnu' and ends with .c. +<I>glimpse '{political,computer};science'</I> will match 'political science' +or 'science of computers'. +<DT><B>Wild cards</B><DD> +The symbol '#' is used to denote a sequence +of any number (including 0) +of arbitrary characters (see <A HREF="#limitations">LIMITATIONS</A>). +The symbol # is equivalent to .* in egrep. +In fact, .* will work too, because it is a valid regular expression +(see below), but unless this is part of an actual regular expression, +# will work faster. +(Currently glimpse is experiencing some problems with #.) +<DT><B>Combination of exact and approximate matching</B><DD> +Any pattern inside angle brackets <> must match the text exactly even +if the match is with errors. For example, <mathemat>ics matches +mathematical with one error (replacing the last s with an a), but +mathe<matics> does not match mathematical no matter how many errors are +allowed. +(This option is buggy at the moment.) +<DT><B>Regular expressions</B><DD> +Since the index is word based, a regular expression must match +words that appear in the index for glimpse to find it. +Glimpse first strips the regular expression from all non-alphabetic +characters, and searches the index for all remaining words. +It then applies the regular expression matching algorithm to the +files found in the index. +For example, <I>glimpse</I> 'abc.*xyz' will search the index +for all files that contain both 'abc' and 'xyz', and then +search directly for 'abc.*xyz' in those files. +(If you use glimpse -w 'abc.*xyz', then 'abcxyz' will not be found, +because glimpse +will think that abc and xyz need to be matches to whole words.) +The syntax of regular expressions in <B>glimpse</B> is in general the same as +that for <B>agrep</B>. The union operation `|', Kleene closure `*', +and parentheses () are all supported. +Currently '+' is not supported. +Regular expressions are currently limited to approximately 30 +characters (generally excluding meta characters). Some options +(-d, -w, -t, -x, -D, -I, -S) do not +currently work with regular expressions. +The maximal number of errors for regular expressions that use '*' +or '|' is 4. (See <A HREF="#limitations">LIMITATIONS</A>.) + +</DL> + +<HR> + +<H2><A NAME="limitations">Limitations</A></H2> + +The index of glimpse is word based. A pattern that contains more than +one word cannot be found in the index. The way glimpse overcomes this +weakness is by splitting any multi-word pattern into its set of words +and looking for all of them in the index. +For example, <B>glimpse 'linear programming'</B> will first consult the index +to find all files containing both <I>linear</I> and <I>programming</I>, +and then apply agrep to find the combined pattern. +This is usually an effective solution, but it can be slow for +cases where both words are very common, but their combination is not. +<P> + +As was mentioned in the section on PATTERNS above, some characters +serve as meta characters for glimpse and need to be +preceded by '\' to search for them. The most common +examples are the characters '.' (which stands for a wild card), +and '*' (the Kleene closure). +So, "glimpse ab.de" will match abcde, but "glimpse ab\.de" +will not, and "glimpse ab*de" will not match ab*de, but +"glimpse ab\*de" will. +The meta character - is translated automatically to a hyphen +unless it appears between [] (in which case it denotes a range of +characters). +<P> + +The index of glimpse stores all patterns in lower case. +When glimpse searches the index it first converts +all patterns to lower case, finds the appropriate files, +and then searches the actual files using the original +patterns. +So, for example, <I>glimpse ABCXYZ</I> will first find all +files containing abcxyz in any combination of lower and upper +cases, and then searches these files directly, so only the +right cases will be found. +One problem with this approach is discovering misspellings +that are caused by wrong cases. +For example, <I>glimpse -B abcXYZ</I> will first search the +index for the best match to abcxyz (because the pattern is +converted to lower case); it will find that there are matches +with no errors, and will go to those files to search them +directly, this time with the original upper cases. +If the closest match is, say AbcXYZ, glimpse may miss it, +because it doesn't expect an error. +Another problem is speed. If you search for "ATT", it will look +at the index for "att". Unless you use -w to match the whole word, +glimpse may have to search all files containing, for example, "Seattle" +which has "att" in it. +<P> + +There is no size limit for simple patterns and simple patterns +within Boolean expressions. +More complicated patterns, such as regular expressions, +are currently limited to approximately 30 characters. +Lines are limited to 1024 characters. +Records are limited to 48K, and may be truncated if they are larger +than that. +The limit of record length can be +changed by modifying the parameter Max_record in agrep.h. +<P> + +Glimpseindex does not index words of size > 64. +<A NAME="lbAQ"> </A> + +<HR> +</BODY> +</HTML> diff --git a/man2html/scripts/cgi-bin/man/man2html b/man2html/scripts/cgi-bin/man/man2html new file mode 100755 index 0000000..7c515d1 --- /dev/null +++ b/man2html/scripts/cgi-bin/man/man2html @@ -0,0 +1,109 @@ +#!/bin/sh +# man2html cgi script - uses /usr/bin/man2html to format man pages +# auxiliary text files in /home/httpd/cgi-aux/man +# aeb@cwi.nl - 980109 + +MAN2HTML="/usr/bin/man2html" +MANX="/home/httpd/cgi-aux/man/man.aux" + +# Do we need lynxcgi URLs? For the moment our criterion is +# 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. +AGENT="${HTTP_USER_AGENT-unknown}" + +case "$AGENT" in + Lynx*|lynx*) + HH="${HTTP_HOST-nohh}" + SED="s/%lynx //" + ;; + *) + HH=nolynx + SED="/%lynx/d" + ;; +esac + +SERVER="${SERVER_NAME-localhost}" +case "$HH" in + nohh) + LL="-l" + CG="lynxcgi:/home/httpd/cgi-bin/man" + ;; + *) + LL="-H$SERVER" + CG="http://$SERVER/cgi-bin/man" + ;; +esac + +# Find the required page - expect to be called with "man2html [sec] page". +# There may a prefixed "-M manpath" option. +if [ $# -ge 2 -a x"$1" = x-M ]; then + MANPATH="$2" + export MANPATH + shift; shift + MP=" using the given MANPATH" +else + MP="" +fi + +# If no arguments given, show a start page. +if [ $# = 0 ]; then + if [ -r $MANX ]; then + cat $MANX | sed "s#%cg#$CG#g; $SED" + else + "$MAN2HTML" -E "man2html: cannot open $MANX" + fi + exit 0 +fi + +if [ $# -gt 2 ]; then + "$MAN2HTML" -E "man2html: bad invocation: too many arguments" + exit 0 +fi + +# A single argument may be an explicitly give path name +# Otherwise, ask man where to find it +if [ $# = 1 ]; then + case "$1" in + /*) + PAGE="$1" + ;; + *) + PAGE=`man -w -c "$@" 2>/dev/null` + ;; + esac +else + PAGE=`man -w -c "$@" 2>/dev/null` +fi + +if [ x"$PAGE" = x ]; then + complaint="man2html: cannot find a page" + if [ $# = 1 ]; then + "$MAN2HTML" -E "$complaint for $1$MP" + else + "$MAN2HTML" -E "$complaint for $2 in section $1$MP" + fi + exit 0 +fi + +if [ -r "$PAGE" ] +then + case "$PAGE" in + *.gz) + zcat "$PAGE" | "$MAN2HTML" "$LL" -D "$PAGE" + ;; + *.bz2) + bzcat "$PAGE" | "$MAN2HTML" "$LL" -D "$PAGE" + ;; + *) + "$MAN2HTML" "$LL" "$PAGE" + ;; + esac +elif [ -r "$PAGE".gz ] +then + zcat "$PAGE".gz | "$MAN2HTML" "$LL" -D "$PAGE" +elif [ -r "$PAGE".bz2 ] +then + bzcat "$PAGE".bz2 | "$MAN2HTML" "$LL" -D "$PAGE" +else + "$MAN2HTML" -E "Strange... Cannot find (or read) $PAGE." +fi +exit 0 diff --git a/man2html/scripts/cgi-bin/man/mansearch b/man2html/scripts/cgi-bin/man/mansearch new file mode 100755 index 0000000..2644db6 --- /dev/null +++ b/man2html/scripts/cgi-bin/man/mansearch @@ -0,0 +1,192 @@ +#!/bin/sh +# +# Interface to a glimpse search of the man pages. +# Michael Hamilton <michael@actrix.gen.nz> +# Small changes - aeb, 980109 +# + +# Do we need lynxcgi URLs? For the moment our criterion is +# 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. +AGENT="${HTTP_USER_AGENT-unknown}" + +case "$AGENT" in + Lynx*|lynx*) + HH="${HTTP_HOST-nohh}" + SED="s/%lynx //" + ;; + *) + HH=nolynx + SED="/%lynx/d" + ;; +esac + +SERVER="${SERVER_NAME-localhost}" +case "$HH" in + nohh) + CG="lynxcgi:/home/httpd/cgi-bin/man" + ;; + *) + CG="http://$SERVER/cgi-bin/man" + ;; +esac +QUOTE="'" +export CG QUOTE SED + +exec awk ' +function removeopts(string) { + gsub(/^[ \t]/, "", string); # Remove leading spaces + gsub(/[ \t]$/, "", string); # Remove trailing spaces + gsub(/[ \t\\];/, ";", string); # Remove spaces before ; + gsub(/[ \t];/, ",", string); # Remove spaces before , + while (match(string, /^-[FLBwk1-8]/)) { + if (match(string, /^-[FL]( |.)[^ \t]+[ \t]+/)) { # Option with arg + options = options " " substr(string, RSTART, RLENGTH); + string = substr(string, RSTART + RLENGTH); + } + else if (match(string, /^-[Bwk1-8][ \t]+/)) { # Option without arg + options = options " " substr(string, RSTART, RLENGTH); + string = substr(string, RSTART + RLENGTH); + } + else if (match(string, /^-[^ \t]/)) { # Remove it + string = substr(string, RSTART + RLENGTH); + } + } + return string; +} + +BEGIN { + + searchdocument = "/home/httpd/cgi-aux/man/mansearch.aux"; + quote = ENVIRON["QUOTE"]; + cgipath = ENVIRON["CG"]; + sedcmd = ENVIRON["SED"]; + truncate_at = 11; # Single page display match limit. + + glimpse_cmd = "glimpse -z -H /var/man2html -y -W -i " + + for (i = 1; i < ARGC; i++) { + string = string " " ARGV[i]; + } + # Have to be careful to single quote this + # string later. + gsub(/[^a-zA-Z0-9-_+ \t\/@%:;,$*|]/, " ", string); + + string = removeopts(string); + + gsub(/[^a-zA-Z0-9-_+ \t\/@%:,]/, " ", options); + + if (!string) { + if (system("test -r " searchdocument ) != 0) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>mansearch - file not found</title>"; + print "</head>\n<body>"; + print "Sorry - cannot read " searchdocument "."; + print "</body>"; + exit; + } + system("sed " quote "s#%cg#" cgipath "#g;" sedcmd quote " " searchdocument ); + exit; + } + + print "Content-type: text/html"; + print ""; + print "<HTML>"; + print "<HEAD>"; + print "<TITLE>Manual Pages - Search Results: " string "</TITLE>"; + print "</HEAD>"; + print "<BODY>"; + + print "<H1>Manual Pages - Search Results</H1>"; + print "<H2>Target text: " options " " string "</H2>"; + + print "<A HREF=\"" cgipath "/mansearch\">"; + print "Perform another search"; + print "</A><BR>"; + print "<A HREF=\"" cgipath "/man2html\">"; + print "Return to Main Contents"; + print "</A>"; + + print "<HR>"; + + print "<DL>"; + # Unless you like being hacked, the single + # forward quotes are most important. + cmd = glimpse_cmd " " options " " quote string quote " 2>/dev/null" ; + + while ((cmd | getline matchline) > 0) { + if (split(matchline, part, ": ") == 1) { + continue; + } + else { + fullname = part[1]; + } + + if (fullname == "glimpse") { + print "<DT><B>"fullname"</B>:"; + } + else if (fullname != last_fullname) { + mcount++; + tcount = 0; + last_fullname = fullname ; + last_text = ""; + + if (match(fullname, ".*/")) { + dirname = substr(fullname, 1, RLENGTH); + filename = substr(fullname, RLENGTH + 1); + if (dirname != last_dirname) { + last_dirname = dirname; + print "</DL>"; + print "<H3>Location: " dirname "</H3>"; + print "<DL>"; + } + } + else { + filename = fullname; + } + + if (match(filename, /\.[^.]+$/)) { + ref = substr(filename, 1, RSTART - 1) "+" substr(filename, RSTART + 1); + } + else { + ref = filename; + } + print "<DT> <a href=\"" cgipath "/man2html?" fullname "\">"; + textname = filename; + sub(/\.(gz)|Z|z$/, "", textname); + sub(/\./, "(", textname); + textname = textname ")"; + print textname; + print "</A>"; + } + + text = substr(matchline, length(fullname) + 2); + tcount++; + if (tcount < truncate_at) { + sub(/^ *.[^ ]+ /, "", text); + sub(/ +$/, "", text); + gsub(/\\f./, "", text); + gsub(/\\&/, "", text); + gsub(/\\/, "", text); + print "<DD>" text; + } + else if (tcount == truncate_at) { + print "<DD> <I>...additional matches not shown.</I>"; + } + } + + print "</DL>"; + if (mcount == 0) { + print "No matches found."; + } + else if (mcount == 1) { + print "<HR>\n<P>1 match found." + } + else { + print "<HR>\n<P>" mcount " matches found." + } + print "</BODY>"; + print "</HTML>"; + exit; +}' "$@" + diff --git a/man2html/scripts/cgi-bin/man/mansearchhelp b/man2html/scripts/cgi-bin/man/mansearchhelp new file mode 100755 index 0000000..a96e796 --- /dev/null +++ b/man2html/scripts/cgi-bin/man/mansearchhelp @@ -0,0 +1,32 @@ +#!/bin/sh +MAN2HTML=/usr/bin/man2html +MANSH=/home/httpd/cgi-aux/man/mansearchhelp.aux + +# Do we need lynxcgi URLs? For the moment our criterion is +# 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. +AGENT="${HTTP_USER_AGENT-unknown}" +case "$AGENT" in + Lynx*|lynx*) + HH="${HTTP_HOST-nohh}" + ;; + *) + HH=nolynx + ;; +esac + +SERVER="${SERVER_NAME-localhost}" +case "$HH" in + nohh) + CG="lynxcgi:/home/httpd/cgi-bin/man" + ;; + *) + CG="http://$SERVER/cgi-bin/man" + ;; +esac + +if [ -r $MANSH ]; then + sed s#%cg#$CG#g $MANSH +else + $MAN2HTML -E "man2html: cannot open $MANSH" +fi +exit 0 diff --git a/man2html/scripts/cgi-bin/man/mansec b/man2html/scripts/cgi-bin/man/mansec new file mode 100755 index 0000000..24c189e --- /dev/null +++ b/man2html/scripts/cgi-bin/man/mansec @@ -0,0 +1,183 @@ +#!/usr/bin/awk -f +# +# Generate an index into a manual section by using find. +# Michael Hamilton <michael@actrix.gen.nz> +# Small changes - aeb, 980109 +# +BEGIN { + + OFS=""; + + if (ARGC != 3) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>manwhatis - bad call</title>"; + print "</head>\n<body>"; + print "manwhatis: wrong number of arguments"; + print "</body>"; + exit; + } + cgipath = ARGV[1]; + section = ARGV[2]; + + if (section !~ /^[1-8ln]$/ && section != "all") { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>Manual - Illegal section</title>"; + print "<body>"; + print "Illegal section number '" section "'." ; + print "Must be one of 1,2,3,4,5,6,7,8,l,n or all"; + print "</body>"; + exit; + } + + "echo $PPID" | getline pid; + + if (cgipath ~ /lynxcgi/) { + cache_suffix = "l"; + } + else { + cache_suffix = "h"; + } + + cache_dir = "/var/man2html"; + cache_file = "manindex" cache_suffix "-" section ".html"; + cache = cache_dir "/" cache_file; + cache_tmp = cache "_" pid; + buffer_tmp = cache "_items_" pid; + + # Find out the man path + "man -w" | getline man_path + man_path = man_path ":"; + gsub(":", " ", man_path); + # See if anything is out of date. + # Check all man[1-8] dir dates vs cache date + if (section == "all") { + if (system("test -f " cache) == 0) { + cmd = "find " man_path " -maxdepth 1 -name 'man[1-8]' -newer " cache; + cmd | getline need_update; + } + else { + need_update = 1; + } + } + else { + if (system("test -f " cache) == 0) { + cmd = "find " man_path " -maxdepth 1 -name man" section " -newer " cache; + cmd | getline need_update; + } + else { + need_update = 1; + } + } + + if (need_update != "") { + if (system("test -w " cache_dir "/.") != 0) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>mansec - no cache</title>"; + print "</head>\n<body>"; + print "Sorry - cannot create index."; + print "No writable cache directory " cache_dir " exists."; + print "</body>"; + exit; + } + + sec_name[1] = "User Commands"; + sec_name[2] = "System Calls"; + sec_name[3] = "Library Functions"; + sec_name[4] = "Special Files"; + sec_name[5] = "File Formats"; + sec_name[6] = "Games"; + sec_name[7] = "Miscellany"; + sec_name[8] = "Administration and Privileged Commands"; + sec_name["all"] = "All available manual pages"; + num_sections = 8; + + # Print heading + print "Content-type: text/html\n\n" > cache_tmp; + print "<html>\n<head>" > cache_tmp; + print "<title>Manual Pages - Names: " section ". " sec_name[section] "</title>"> cache_tmp; + print "</head>\n<body>" > cache_tmp; + print "<h1>Manual Pages - Page Names</h1>" > cache_tmp; + print "<h2>Section " section ": " sec_name[section] "</h2>" > cache_tmp; + + "hostname" | getline hostname; + "date" | getline date; + print hostname " (" date ")" > cache_tmp; + + if (section != "all") { + sec_sub_dir = "/man" section; + } + else { + sec_sub_dir = "/man*"; + } + gsub(" ", sec_sub_dir " ", man_path); + + print "<p>Manual pages found under " man_path "." > cache_tmp; + + # Find any man[1-8]/filenames + while ((("find " man_path " -follow -type f -printf '%f\n' | sort -f ") | getline manpage) > 0) { + # Check for new letter of alphabet + letter = tolower(substr(manpage,1,1)); + if (letter != last_letter) { + last_letter = letter; + letter_index[++num_letters] = letter; + # Start a new alphabetic heading + print "<h2> <a name=\"", letter, "\">", toupper(letter), "</a></h2>" > buffer_tmp; + # Print out alphabetic quick index and other links + } + # Split page.n into "page" and "n" and generate an entry + sub(/[.]([zZ]|(gz))$/, "", manpage); + match(manpage, /[.][^.]+$/); + title = substr(manpage, 1, RSTART - 1); + if (section != "all") { + print "<a href=\"" cgipath "/man2html?", section, "+", title, "\">", title, "(", substr(manpage, RSTART + 1), ")</a>" > buffer_tmp; + } + else { + sec = substr(manpage, RSTART + 1) + print "<a href=\"" cgipath "/man2html?", sec, "+", title, "\">", title, "(", sec, ")</a>" > buffer_tmp; + } + } + + close(buffer_tmp); + + print "<p>" > cache_tmp; + + # Print out alphabetic quick index and other links + for (i = 1; i <= num_letters; i++) { + print "<a href=\"#" letter_index[i] "\">" toupper(letter_index[i]) "</a>" > cache_tmp; + } + + print "<p><hr>" > cache_tmp; + print "<a href=\"" cgipath "/man2html\">Return to Main Contents</a>" > cache_tmp; + + print "<p>Other sections:" > cache_tmp; + for (i=1; i<=num_sections; i++) { + if (i != section) { # Dont print an entry for the section we are in + print "<a href=\"" cgipath "/mansec?" cgipath "+" i "\">" i ". " sec_name[i] "</a> " > cache_tmp; + } + } + print "<hr><p>" > cache_tmp; + # Print out the accumulated index entries + while ((getline < buffer_tmp) > 0) print > cache_tmp; + print "<hr><p>" > cache_tmp; + # Print out alphabetic quick index and other links + for (i = 1; i <= num_letters; i++) { + print "<a href=\"#" letter_index[i] "\">" toupper(letter_index[i]) "</a>" > cache_tmp; + } + print "<hr>" > cache_tmp; + print "<p><a href=\"" cgipath "/man2html\">Return to Main Contents</a>" > cache_tmp; + print "<p>Other sections:" > cache_tmp; + for (i=1; i<=num_sections; i++) { + if (i != section) { # Dont print an entry for the section we are in + print "<a href=\"" cgipath "/mansec?" cgipath "+" i "\">" i ". " sec_name[i] "</a> " > cache_tmp; + } + } + print "</body>\n</html>" > cache_tmp; + system("/bin/mv " cache_tmp " " cache); + system("/bin/rm -f " buffer_tmp); + } + system("/bin/cat " cache); + exit; +} diff --git a/man2html/scripts/cgi-bin/man/manwhatis b/man2html/scripts/cgi-bin/man/manwhatis new file mode 100755 index 0000000..d14a516 --- /dev/null +++ b/man2html/scripts/cgi-bin/man/manwhatis @@ -0,0 +1,208 @@ +#!/usr/bin/awk -f +# +# Generate a whatis index into the manual pages by using find to +# locate all the whatis files. +# Michael Hamilton <michael@actrix.gen.nz> +# Small changes - aeb, 980109 +# +BEGIN { + + OFS=""; + + if (ARGC != 3) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>manwhatis - bad call</title>"; + print "</head>\n<body>"; + print "manwhatis: wrong number of arguments"; + print "</body>"; + exit; + } + cgipath = ARGV[1]; + section = ARGV[2]; + + if (section !~ /^[1-8ln]$/) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>Manual - Illegal section</title>"; + print "</head>\n<body>"; + print "Illegal section number '" section "'." ; + print "Must be one of 1,2,3,4,5,6,7,8,l,n"; + print "</body>"; + exit; + } + + if (cgipath ~ /lynxcgi/) { + cache_suffix = "l"; + } + else { + cache_suffix = "h"; + } + + cache_dir = "/var/man2html"; + cache_file = "whatis" cache_suffix "-" section ".html"; + cache = cache_dir "/" cache_file; + + + # Find out the man path + "man -w" | getline man_path + gsub(":", " ", man_path); + # See if anything is out of date. + if (system("test -f " cache) == 0) { + cmd = "find " man_path " -maxdepth 1 -name whatis -newer " cache; + cmd | getline need_update; + } + else { + need_update = 1; + } + + if (need_update != "") { + + if (system("test -w " cache_dir "/.") != 0) { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>manwhatis - no cache</title>"; + print "</head>\n<body>"; + print "Sorry - cannot create index."; + print "No writable cache directory " cache_dir " exists."; + print "</body>"; + exit; + } + + "echo $PPID" | getline pid; + + cache_tmp = cache "_" pid; + sort_tmp = cache_dir "/manwhatis_tmp_" pid ; + buffer_tmp = cache_dir "/manwhatis_tmp2_" pid; + + sec_name[1] = "User Commands"; + sec_name[2] = "System Calls"; + sec_name[3] = "Library Functions"; + sec_name[4] = "Special Files"; + sec_name[5] = "File Formats"; + sec_name[6] = "Games"; + sec_name[7] = "Miscellany"; + sec_name[8] = "Administration and Privileged Commands"; + num_sections = 8; + # Print heading + print "Content-type: text/html\n\n" > cache_tmp; + print "<html>\n<head>" > cache_tmp; + print "<title>Manual Pages - Names and Descriptions: " section ". " sec_name[section] "</title>" > cache_tmp; + + print "</head>\n<body>" > cache_tmp; + print "<h1>Manual Pages - Names and Descriptions</h1>" > cache_tmp; + print "<h1>Section " section ": " sec_name[section] "</h1>" > cache_tmp; + "hostname" | getline hostname; + "date" | getline date; + print hostname " (" date ")" > cache_tmp; + # Find out the man path + "man -w" | getline; + $1 = $1 ":"; + gsub(":", " ", $1); + + find_cmd = "find " man_path " -maxdepth 1 -name whatis -printf '%p '"; + find_cmd | getline whatis_files; + close(find_cmd); + + if (whatis_files == "") { + print "Content-type: text/html\n\n"; + print "<head>"; + print "<title>Manwhatis - Error updating index</title>"; + print "</head>\n<body>"; + print "Unable to find whatis files - Sorry." + print "</body>"; + exit; + } + # Try to parse valid entries - those that contain ([0-9]) + # Note that egrep is sometimes in /bin, sometimes in /usr/bin + extract_cmd = "egrep -h '\\(" section "[A-Za-z]*\\)' " whatis_files ; + + print "<br>Manual pages referenced in " whatis_files "<p>" > cache_tmp; + + # Note that sort sometimes lives in /bin and sometimes in /usr/bin + sort_cmd = "sort -f >> " sort_tmp; + + while ( (extract_cmd | getline) > 0 ) { + if (bracket_pos = index($0, "(")) { + sec_full_num = substr($0, bracket_pos + 1, index($0, ")") - bracket_pos - 1); + names = substr($0, 1, bracket_pos - 2); + # Get rid of blanks and commas. + n = split(names, name_list, " *, *"); + description = substr($0, bracket_pos + length(sec_full_num) + 2); + # Get rid of AT&T + gsub("&", "\&", description); + # Generate a entry for each name + for (i = 1; i <= n; i++) { + print name_list[i] " " sec_full_num " " name_list[1] " / " description | sort_cmd; + } + } + } + close(extract_cmd); + close(sort_cmd); + + while ((getline < sort_tmp) > 0) { + + letter = tolower(substr($1,1,1)); + if (letter != last_letter) { + if (last_letter) { + print "</dl><p>" > buffer_tmp; + } + last_letter = letter; + letter_index[++num_letters] = letter; + # Terminate list, start a new one + + print "<h2> <a name=\"", letter, "\">", toupper(letter), "</a></h2>\n<dl>" > buffer_tmp ; + } + # Generate a <dt> for the name + if ($3 != last_file || $1 != last_name) { # Don't repeat the same entry link. + print "<dt><a href=\"" cgipath "/man2html?", $2, "+", $3, "\">", $1, "(", $2, ")", "</a>" > buffer_tmp; + last_file = $3; + last_name = $1; + } + print "<dd>", substr($0, match($0, "/") + 1) > buffer_tmp; + } + # Finish off last list + + print "\n</dl><p>" > buffer_tmp; + close(buffer_tmp); + + system("/bin/rm " sort_tmp); + + # Print out alphabetic quick index and other links + for (i = 1; i <= num_letters; i++) { + print "<a href=\"#" letter_index[i] "\">" toupper(letter_index[i]) "</a>" > cache_tmp; + } + print "<hr>" > cache_tmp; + print "<a href=\"" cgipath "/man2html\">Return to Main Contents</a>" > cache_tmp; + + print "<p>Other sections:" > cache_tmp; + for (i=1; i<=num_sections; i++) { + if (i != section) { # Dont print an entry for the section we are in + print "<a href=\"" cgipath "/manwhatis?" cgipath "+" i "\">" i ". " sec_name[i] "</a> " > cache_tmp; + } + } + print "<hr><p>" > cache_tmp; + # Print out the accumulated contents entries + while ((getline < buffer_tmp) > 0) print > cache_tmp; + print "<hr><p>" > cache_tmp; + + for (i = 1; i <= num_letters; i++) { + print "<a href=\"#" letter_index[i] "\">" toupper(letter_index[i]) "</a>" > cache_tmp; + } + print "<hr>" > cache_tmp; + print "<p><a href=\"" cgipath "/man2html\">Return to Main Contents</a>" > cache_tmp; + + print "<p>Other sections:" > cache_tmp; + for (i=1; i<=num_sections; i++) { + if (i != section) { # Dont print an entry for the section we are in + print "<a href=\"" cgipath "/manwhatis?" cgipath "+" i "\">" i ". " sec_name[i] "</a> " > cache_tmp; + } + } + print "</body>" > cache_tmp; + print "</html>" > cache_tmp; + system("/bin/mv " cache_tmp " " cache); + system("/bin/rm " buffer_tmp); + } + system("/bin/cat " cache); + exit; +} diff --git a/man2html/strdefs.c b/man2html/strdefs.c new file mode 100644 index 0000000..8515b82 --- /dev/null +++ b/man2html/strdefs.c @@ -0,0 +1,176 @@ +#include "defs.h" + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +int nroff = 1; + +#define NROFF (-666) +#define TROFF (-667) + +STRDEF *chardef, *strdef, *defdef; +INTDEF *intdef; + +static INTDEF standardint[] = { + { V('n',' '), NROFF, 0, NULL }, + { V('t',' '), TROFF, 0, NULL }, + { V('o',' '), 1, 0, NULL }, + { V('e',' '), 0, 0, NULL }, + { V('.','l'), 70, 0, NULL }, + { V('.','$'), 0, 0, NULL }, + { V('.','A'), NROFF, 0, NULL }, + { V('.','T'), TROFF, 0, NULL }, + { V('.','V'), 1, 0, NULL }, /* the me package tests for this */ + { 0, 0, 0, NULL } }; + +static STRDEF standardstring[] = { + { V('R',' '), 1, "®", NULL }, + { V('l','q'), 2, "``", NULL }, + { V('r','q'), 2, "''", NULL }, + { 0, 0, NULL, NULL} +}; + + +static STRDEF standardchar[] = { + { V('*','*'), 1, "*", NULL }, /* math star */ + { V('*','A'), 1, "A", NULL }, + { V('*','B'), 1, "B", NULL }, + { V('*','C'), 2, "Xi", NULL }, + { V('*','D'), 5, "Delta", NULL }, + { V('*','E'), 1, "E", NULL }, + { V('*','F'), 3, "Phi", NULL }, + { V('*','G'), 5, "Gamma", NULL }, + { V('*','H'), 5, "Theta", NULL }, + { V('*','I'), 1, "I", NULL }, + { V('*','K'), 1, "K", NULL }, + { V('*','L'), 6, "Lambda", NULL }, + { V('*','M'), 1, "M", NULL }, + { V('*','N'), 1, "N", NULL }, + { V('*','O'), 1, "O", NULL }, + { V('*','P'), 2, "Pi", NULL }, + { V('*','Q'), 3, "Psi", NULL }, + { V('*','R'), 1, "P", NULL }, + { V('*','S'), 5, "Sigma", NULL }, + { V('*','T'), 1, "T", NULL }, + { V('*','U'), 1, "Y", NULL }, + { V('*','W'), 5, "Omega", NULL }, + { V('*','X'), 1, "X", NULL }, + { V('*','Y'), 1, "H", NULL }, + { V('*','Z'), 1, "Z", NULL }, + { V('*','a'), 5, "alpha", NULL }, + { V('*','b'), 4, "beta", NULL }, + { V('*','c'), 2, "xi", NULL }, + { V('*','d'), 5, "delta", NULL }, + { V('*','e'), 7, "epsilon", NULL }, + { V('*','f'), 3, "phi", NULL }, + { V('*','g'), 5, "gamma", NULL }, + { V('*','h'), 5, "theta", NULL }, + { V('*','i'), 4, "iota", NULL }, + { V('*','k'), 5, "kappa", NULL }, + { V('*','l'), 6, "lambda", NULL }, + { V('*','m'), 1, "µ", NULL }, + { V('*','n'), 2, "nu", NULL }, + { V('*','o'), 1, "o", NULL }, + { V('*','p'), 2, "pi", NULL }, + { V('*','q'), 3, "psi", NULL }, + { V('*','r'), 3, "rho", NULL }, + { V('*','s'), 5, "sigma", NULL }, + { V('*','t'), 3, "tau", NULL }, + { V('*','u'), 7, "upsilon", NULL }, + { V('*','w'), 5, "omega", NULL }, + { V('*','x'), 3, "chi", NULL }, + { V('*','y'), 3, "eta", NULL }, + { V('*','z'), 4, "zeta", NULL }, + { V('+','-'), 1, "±", NULL }, + { V('1','2'), 1, "½", NULL }, + { V('1','4'), 1, "¼", NULL }, + { V('3','4'), 1, "¾", NULL }, + { V('F','i'), 3, "ffi", NULL }, + { V('F','l'), 3, "ffl", NULL }, + { V('a','a'), 1, "´", NULL }, + { V('a','p'), 1, "~", NULL }, + { V('b','r'), 1, "|", NULL }, + { V('b','u'), 1, "*", NULL }, /* bullet */ + { V('b','v'), 1, "|", NULL }, + { V('c','i'), 1, "o", NULL }, /* circle */ + { V('c','o'), 1, "©", NULL }, + { V('c','t'), 1, "¢", NULL }, + { V('d','e'), 1, "°", NULL }, + { V('d','g'), 1, "+", NULL }, /* dagger */ + { V('d','i'), 1, "÷", NULL }, + { V('e','m'), 3, "---", NULL }, /* em dash */ + { V('e','n'), 1, "-", NULL }, /* en dash */ + { V('e','q'), 1, "=", NULL }, + { V('e','s'), 1, "Ø", NULL }, + { V('f','f'), 2, "ff", NULL }, + { V('f','i'), 2, "fi", NULL }, + { V('f','l'), 2, "fl", NULL }, + { V('f','m'), 1, "´", NULL }, + { V('g','a'), 1, "`", NULL }, + { V('h','y'), 1, "-", NULL }, + { V('l','c'), 2, "|¯", NULL }, + { V('i','f'), 8, "Infinity", NULL }, /* infinity sign */ + { V('i','s'), 8, "Integral", NULL }, /* integral sign */ + { V('l','f'), 2, "|_", NULL }, + { V('l','k'), 1, "<FONT SIZE=\"+2\">{</FONT>", NULL }, + { V('m','i'), 1, "-", NULL }, + { V('m','u'), 1, "×", NULL }, + { V('n','o'), 1, "¬", NULL }, + { V('o','r'), 1, "|", NULL }, + { V('p','d'), 1, "d", NULL }, /* partial derivative */ + { V('p','l'), 1, "+", NULL }, + { V('r','c'), 2, "¯|", NULL }, + { V('r','f'), 2, "_|", NULL }, + { V('r','g'), 1, "®", NULL }, + { V('r','k'), 1, "<FONT SIZE=\"+2\">}</FONT>", NULL }, + { V('r','n'), 1, "¯", NULL }, + { V('r','u'), 1, "_", NULL }, + { V('s','c'), 1, "§", NULL }, + { V('s','l'), 1, "/", NULL }, + { V('s','q'), 2, "[]", NULL }, + { V('t','s'), 1, "s", NULL }, /* should be terminal sigma */ + { V('u','l'), 1, "_", NULL }, + { V('>','='), 1, ">", NULL }, + { V('<','='), 1, "<", NULL }, + { 0, 0, NULL, NULL } +}; + +void stdinit(void) { + STRDEF *stdf; + int i; + + stdf = &standardchar[0]; + i = 0; + while (stdf->nr) { + if (stdf->st) stdf->st = xstrdup(stdf->st); + stdf->next = &standardchar[i]; + stdf = stdf->next; + i++; + } + chardef=&standardchar[0]; + + stdf=&standardstring[0]; + i=0; + while (stdf->nr) { + /* waste a little memory, and make a copy, to avoid + the segfault when we free non-malloced memory */ + if (stdf->st) stdf->st = xstrdup(stdf->st); + stdf->next = &standardstring[i]; + stdf = stdf->next; + i++; + } + strdef=&standardstring[0]; + + intdef=&standardint[0]; + i=0; + while (intdef->nr) { + if (intdef->nr == NROFF) intdef->nr = nroff; else + if (intdef->nr == TROFF) intdef->nr = !nroff; + intdef->next = &standardint[i]; + intdef = intdef->next; + i++; + } + intdef = &standardint[0]; + defdef = NULL; +} |