├── Makefile ├── Makefile.in ├── README ├── TODO ├── abbrev.c ├── cgibase.c ├── defs.h ├── glimpse_filters ├── hman.1 ├── hman.sh ├── locales ├── en │ ├── hman.1 │ └── man2html.1 ├── fr │ └── man2html.1 └── it │ ├── hman.1 │ └── man2html.1 ├── man2html.1 ├── man2html.c ├── scripts ├── cgi-aux │ └── man │ │ ├── man.aux │ │ ├── mansearch.aux │ │ └── mansearchhelp.aux └── cgi-bin │ └── man │ ├── man2html │ ├── mansearch │ ├── mansearchhelp │ ├── mansec │ └── manwhatis └── strdefs.c /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Generated automatically from Makefile.in by the 3 | # configure script. 4 | # 5 | CC = gcc 6 | CFLAGS += -Wall -Wstrict-prototypes -Wmissing-prototypes 7 | OBJECTS = man2html.o cgibase.o abbrev.o strdefs.o 8 | bindir = /usr/local/bin 9 | mandir = /usr/local/share/man 10 | vardir = /usr/local/var 11 | httpdir = /home/httpd 12 | cgiowner = nobody 13 | cgigroup = nobody 14 | 15 | all: man2html hman 16 | 17 | man2html: $(OBJECTS) 18 | $(CC) $(LDFLAGS) -o man2html $(OBJECTS) 19 | 20 | # man2html: ../src/version.h 21 | 22 | # This installs the man2html utility 23 | install: man2html 24 | mkdir -p $(bindir) 25 | install -m 755 man2html $(bindir) 26 | mkdir -p $(mandir)/man1 27 | install -m 644 man2html.1 $(mandir)/man1/man2html.1 28 | 29 | install-scripts: install-man-scripts install-glimpse-stuff install-hman 30 | 31 | # These are the scripts that allow pointing a browser at 32 | # http://localhost/cgi-bin/man/man2html 33 | # to work. 34 | install-man-scripts: 35 | mkdir -p $(httpdir)/cgi-bin/man 36 | mkdir -p $(httpdir)/cgi-aux/man 37 | install -m 755 scripts/cgi-bin/man/* $(httpdir)/cgi-bin/man 38 | install -m 644 scripts/cgi-aux/man/* $(httpdir)/cgi-aux/man 39 | install -d -o $(cgiowner) -g $(cgigroup) -m 775 $(vardir)/man2html 40 | # (aux was renamed to cgi-aux since aux causes problems under DOS) 41 | 42 | # If you have installed glimpse, and have compressed man pages, 43 | # then perhaps you also want these filters. 44 | install-glimpse-stuff: 45 | install -m 644 glimpse_filters $(vardir)/man2html/.glimpse_filters 46 | 47 | # In order not to have to type a long command like 48 | # netscape http://localhost/cgi-bin/man/man2html?section+topic 49 | # or 50 | # lynx lynxcgi:/home/httpd/cgi-bin/man/man2html?section+topic 51 | # it is convenient to have some shell script as a wrapper. 52 | # The script hman can be aliased to man. It uses an environment 53 | # variable MANHTMLPAGER to find out which browser you use, and 54 | # you can set MANHTMLHOST if the pages are not on localhost. 55 | hman: hman.sh 56 | rm -f hman 57 | sed -e 's,%version%,man-1.6f,' hman.sh > hman 58 | 59 | install-hman: hman 60 | install -m 555 hman $(bindir)/hman 61 | install -m 644 hman.1 $(mandir)/man1/hman.1 62 | 63 | clean: 64 | rm -f core hman man2html $(OBJECTS) *~ 65 | 66 | spotless: clean 67 | rm -f Makefile 68 | 69 | $(OBJECTS): defs.h 70 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | CC = @CC@ 2 | CFLAGS += -Wall -Wstrict-prototypes -Wmissing-prototypes 3 | OBJECTS = man2html.o cgibase.o abbrev.o strdefs.o 4 | bindir = $(DESTDIR)$(PREFIX)/usr/bin 5 | mandir = $(DESTDIR)$(PREFIX)@mandir@ 6 | vardir = $(DESTDIR)$(PREFIX)/var 7 | httpdir = $(DESTDIR)$(PREFIX)/home/httpd 8 | cgiowner = nobody 9 | cgigroup = nobody 10 | 11 | all: man2html hman 12 | 13 | man2html: $(OBJECTS) 14 | $(CC) $(LDFLAGS) -o man2html $(OBJECTS) 15 | 16 | # man2html: ../src/version.h 17 | 18 | # This installs the man2html utility 19 | install: man2html 20 | mkdir -p $(bindir) 21 | install -m 755 man2html $(bindir) 22 | mkdir -p $(mandir)/man1 23 | install -m 644 man2html.1 $(mandir)/man1/man2html.@man1ext@ 24 | 25 | install-scripts: install-man-scripts install-glimpse-stuff install-hman 26 | 27 | # These are the scripts that allow pointing a browser at 28 | # http://localhost/cgi-bin/man/man2html 29 | # to work. 30 | install-man-scripts: 31 | mkdir -p $(httpdir)/cgi-bin/man 32 | mkdir -p $(httpdir)/cgi-aux/man 33 | install -m 755 scripts/cgi-bin/man/* $(httpdir)/cgi-bin/man 34 | install -m 644 scripts/cgi-aux/man/* $(httpdir)/cgi-aux/man 35 | install -d -o $(cgiowner) -g $(cgigroup) -m 775 $(vardir)/man2html 36 | # (aux was renamed to cgi-aux since aux causes problems under DOS) 37 | 38 | # If you have installed glimpse, and have compressed man pages, 39 | # then perhaps you also want these filters. 40 | install-glimpse-stuff: 41 | install -m 644 glimpse_filters $(vardir)/man2html/.glimpse_filters 42 | 43 | # In order not to have to type a long command like 44 | # netscape http://localhost/cgi-bin/man/man2html?section+topic 45 | # or 46 | # lynx lynxcgi:/home/httpd/cgi-bin/man/man2html?section+topic 47 | # it is convenient to have some shell script as a wrapper. 48 | # The script hman can be aliased to man. It uses an environment 49 | # variable MANHTMLPAGER to find out which browser you use, and 50 | # you can set MANHTMLHOST if the pages are not on localhost. 51 | hman: hman.sh 52 | rm -f hman 53 | sed -e 's,%version%,@version@,' hman.sh > hman 54 | 55 | install-hman: hman 56 | install -m 555 hman $(bindir)/hman 57 | install -m 644 hman.1 $(mandir)/man1/hman.@man1ext@ 58 | 59 | clean: 60 | rm -f core hman man2html $(OBJECTS) *~ 61 | 62 | spotless: clean 63 | rm -f Makefile 64 | 65 | $(OBJECTS): defs.h 66 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This directory contains the following. 2 | 3 | 1. man2html 4 | 5 | This is a pure manroff -> html converter. 6 | No manpath search etc. 7 | 8 | Call: man2html [-l | -H host.domain:port] [filename] 9 | 10 | The contents of FILENAME (or STDIN, in case FILENAME is "-" or absent) 11 | are converted from man-style nroff to html, and printed on STDOUT. 12 | 13 | With "-l" URLs of the form "lynxcgi:/home/httpd/cgi-bin/..." are generated. 14 | With "-H host" we make URLs of the form "http://host/cgi-bin/...". 15 | The default is "http://localhost/cgi-bin/...". 16 | 17 | 2. A collection of scripts 18 | 19 | This part is not installed by "make install" of the global Makefile. 20 | There are security considerations: it is very unlikely that these 21 | scripts (still in alpha) are secure, so for the time being they 22 | should only be used where security is not a major concern. 23 | 24 | If you are not afraid, or are not running a httpd, do 25 | "make install-scripts" in this directory. 26 | This does three things: install man stuff, install glimpse stuff, 27 | and install user interface stuff. 28 | 29 | 2A. man stuff 30 | 31 | This first part (that can be done separately with "make install-man-scripts") 32 | puts various scripts under /home/httpd/cgi-bin and /home/httpd/cgi-aux 33 | in a subdirectory man. 34 | It will create a directory /var/man2html to hold the indices. 35 | (This directory should be writable by the cgi scripts; 36 | probably that means that the owner should be nobody. 37 | Choose a group and add all non-httpd users that should be 38 | able to write this directory to that group.) 39 | 40 | Structure of the collection of scripts: 41 | man2html is the main script. 42 | It uses man.aux when called without arguments. 43 | It uses manwhatis when asked for an index of manpages+descriptions. 44 | It uses mansec when asked for a compact index of manpages. 45 | It uses mansearch when asked for a glimpse search. 46 | In its turn mansearch uses mansearch.aux when called 47 | without arguments. It uses mansearchhelp (which uses 48 | mansearchhelp.aux) when asked for help. 49 | 50 | 2B. glimpse stuff 51 | The second part (that can be done separately with 52 | "make install-glimpse-stuff") installs .glimpse_filters 53 | in /var/man2html, in order to tell glimpse what decompressors to use. 54 | 55 | 2C. user interface stuff 56 | The third part (that can be done separately with "make install-hman") 57 | installs a user interface to these scripts in /usr/bin/hman. 58 | Now people can say 59 | alias man=/usr/bin/hman 60 | and have a man that uses a html browser. 61 | The browser is chosen via environment variables - look at the script. 62 | 63 | 3. Glimpse. 64 | 65 | For the glimpse part, I quote Michael Hamilton: 66 | ---------------------------------------------------------------------- 67 | To use the Glimpse full text searching, you will need to install 68 | glimpse in /usr/bin. Redhat rpm users can get glimpse from 69 | 70 | ftp://ftp.redhat.com/pub/contrib/i386/glimpse-4.0-6.i386.rpm 71 | 72 | The glimpse home ftp site is cs.arizona.edu. N.B. glimpse is not 73 | freely redistributable for commercial use, I'd be very interested in a 74 | more liberal alternative. Having installed glimpse, you will need to 75 | build a glimpse index in /var/man2html. This doesn't take too long - 76 | about 3 minutes on my 486DX2/66 16MB machine. As root do: 77 | 78 | /usr/bin/glimpseindex -z -H /var/man2html /usr/man/man* /usr/X11R6/man/man* \ 79 | /usr/local/man/man* /opt/man/man* 80 | chmod ugo+r /var/man2html/.glimpse* 81 | 82 | The -z option causes glimpse to apply any filters (for decompression etc) 83 | specified in /var/man2html/.glimpse_filters. 84 | 85 | This could be set up as a cron job in /etc/crontab, e.g. (the following 86 | must be all on one line): 87 | 88 | 21 04 * * 1 root /usr/bin/glimpseindex -z -H /var/man2html /usr/man/man* 89 | /usr/X11R6/man/man* /usr/local/man/man* /opt/man/man* ; 90 | chmod +r /var/man2html/.glimpse* 91 | -------------------------------------------------------------------------- 92 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | There are still many problems with man2html. 2 | Partly these are caused by the imprecise definition 3 | of the man file format. (And the many buggy man pages.) 4 | Partly by the incomplete implementation of the man/doc macro packages. 5 | Partly by the imperfect emulation of troff. 6 | Partly by the variation between various browsers in the 7 | accepted html. 8 | Partly just because man2html is buggy. 9 | 10 | Of course in reality a man2html converter must contain 11 | large parts of the troff source, so that it can be fed 12 | with the defining macro packages and always do the right thing. 13 | 14 | On a RedHat 5.0 system: 15 | - /usr/man/mann/DirDlg.n is not formatted correctly. 16 | (It does not start with .TH) 17 | - bug_readline@prep.ai.mit.edu does not generate 18 | a mailto: link. It should generate 19 | nroff and troff", 31 | "INDEX", "Global Index", 32 | "CPG", "C Programmer's Guide", 33 | "CREF", "C Reference Manual", 34 | "ASSY", "Assembly Language Reference", 35 | "PUL", "Programming Utilities and Libraries", 36 | "DEBUG", "Debugging Tools", 37 | "NETP", "Network Programming", 38 | "DRIVER", "Writing Device Drivers", 39 | "STREAMS", "STREAMS Programming", 40 | "SBDK", "SBus Developer's Kit", 41 | "WDDS", "Writing Device Drivers for the SBus", 42 | "FPOINT", "Floating-Point Programmer's Guide", 43 | "SVPG", "SunView 1 Programmer's Guide", 44 | "SVSPG", "SunView 1 System Programmer's Guide", 45 | "PIXRCT", "Pixrect Reference Manual", 46 | "CGI", "SunCGI Reference Manual", 47 | "CORE", "SunCore Reference Manual", 48 | "4ASSY", "Sun-4 Assembly Language Reference", 49 | "SARCH", "SPARC Architecture Manual", 50 | "KR", "The C Programming Language", 51 | 0, 0 }; 52 | 53 | char *lookup_abbrev (char *s) 54 | { 55 | int i=0; 56 | 57 | if (!s) 58 | return ""; 59 | while (abbrev_list[i] && strcmp(s, abbrev_list[i])) 60 | i = i+2; 61 | return abbrev_list[i] ? abbrev_list[i+1] : s; 62 | } 63 | -------------------------------------------------------------------------------- /cgibase.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Here are the routines of man2html that output a HREF string. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include /* tolower() */ 9 | #include /* strlen() */ 10 | #include "defs.h" 11 | 12 | /* 13 | * The default is to use cgibase. With relative html style 14 | * we generate URLs of the form "../manX/page.html". 15 | */ 16 | static int relat_html_style = 0; 17 | 18 | /* 19 | * The default is to use cgibase. With current html style 20 | * we generate URLs of the form "./page.html". 21 | */ 22 | static int current_html_style = 0; 23 | 24 | /* 25 | * Either the user is non-local (or local, but using httpd), 26 | * in which case we use http:/cgi-bin, or the user is local 27 | * and uses lynx, and we use lynxcgi:/home/httpd/cgi-bin. 28 | */ 29 | 30 | static char *man2htmlpath = "/cgi-bin/man/man2html"; /* default */ 31 | static char *cgibase_format = "http://%s"; /* host.domain:port */ 32 | static char *cgibase_ll_format = "lynxcgi:%s"; /* directory */ 33 | static char *cgibase = "http://localhost"; /* default */ 34 | 35 | /* 36 | * Separator between URL and argument string. 37 | * 38 | * With http:/a/b?c+d+e the script is called 39 | * with PATH_INFO=/a/b and QUERY_STRING=c+d+e and args $1=c, $2=d, $3=e. 40 | * With lynxcgi:?c+d+e no PATH_INFO is possible. 41 | */ 42 | static char sep = '?'; /* or '/' */ 43 | 44 | void 45 | set_separator(char s) { 46 | sep = s; 47 | } 48 | 49 | void 50 | set_lynxcgibase(char *s) { 51 | int n = strlen(cgibase_ll_format) + strlen(s); 52 | char *t = (char *) xmalloc(n); 53 | 54 | sprintf(t, cgibase_ll_format, s); 55 | cgibase = t; 56 | } 57 | 58 | void 59 | set_cgibase(char *s) { 60 | int n = strlen(cgibase_format) + strlen(s); 61 | char *t = (char *) xmalloc(n); 62 | 63 | sprintf(t, cgibase_format, s); 64 | cgibase = t; 65 | } 66 | 67 | void 68 | set_man2htmlpath(char *s) { 69 | man2htmlpath = xstrdup(s); 70 | } 71 | 72 | void 73 | set_relative_html_links(void) { 74 | relat_html_style = 1; 75 | } 76 | void 77 | set_current_html_links(void) { 78 | current_html_style = 1; 79 | } 80 | 81 | /* What shall we say in case of relat_html_style? */ 82 | static char *signature = "
\n" 83 | "This document was created by\n" 84 | "
man2html,\n" 85 | "using the manual pages.
\n" 86 | "%s\n"; 87 | 88 | #define TIMEFORMAT "%T GMT, %B %d, %Y" 89 | #define TIMEBUFSZ 500 90 | 91 | void print_sig() 92 | { 93 | char timebuf[TIMEBUFSZ]; 94 | struct tm *timetm; 95 | time_t clock; 96 | 97 | timebuf[0] = 0; 98 | #ifdef TIMEFORMAT 99 | sprintf(timebuf, "Time: "); 100 | clock=time(NULL); 101 | timetm=gmtime(&clock); 102 | strftime(timebuf+6, TIMEBUFSZ-6, TIMEFORMAT, timetm); 103 | timebuf[TIMEBUFSZ-1] = 0; 104 | #endif 105 | //printf(signature, cgibase, man2htmlpath, timebuf); 106 | printf(signature, timebuf); 107 | } 108 | 109 | void 110 | include_file_html(char *g) { 111 | printf("%s>", g,g); 112 | } 113 | 114 | void 115 | man_page_html(char *sec, char *h) { 116 | if (current_html_style) { 117 | if (!h) 118 | printf("" 119 | "Return to Main Contents"); 120 | else 121 | printf("%s", 122 | h, h); 123 | } else if (relat_html_style) { 124 | if (!h) 125 | printf("" 126 | "Return to Main Contents"); 127 | else 128 | printf("%s", 129 | sec, h, sec, h); 130 | } else { 131 | if (!h) 132 | printf("Return to Main Contents", 133 | cgibase, man2htmlpath); 134 | else if (!sec) 135 | printf("%s", 136 | cgibase, man2htmlpath, sep, h, h); 137 | else 138 | printf("%s", 139 | cgibase, man2htmlpath, sep, sec, h, h); 140 | } 141 | } 142 | 143 | void 144 | ftp_html(char *f) { 145 | printf("%s", f, f); 146 | } 147 | 148 | void 149 | www_html(char *f) { 150 | printf("%s", f, f); 151 | } 152 | 153 | void 154 | mailto_html(char *g) { 155 | printf("%s", g, g); 156 | } 157 | 158 | void 159 | url_html(char *g) { 160 | printf("%s", g, g); 161 | } 162 | -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | extern int nroff; 2 | extern int local_lynx; 3 | 4 | typedef struct STRDEF STRDEF; 5 | struct STRDEF { 6 | int nr,slen; 7 | char *st; 8 | STRDEF *next; 9 | }; 10 | 11 | typedef struct INTDEF INTDEF; 12 | struct INTDEF { 13 | int nr; 14 | int val; 15 | int incr; 16 | INTDEF *next; 17 | }; 18 | 19 | extern STRDEF *chardef, *strdef, *defdef; 20 | extern INTDEF *intdef; 21 | 22 | #define V(A,B) ((A)*256+(B)) 23 | 24 | #include 25 | extern void stdinit(void); 26 | extern void print_sig(void); 27 | extern char *lookup_abbrev(char *); 28 | extern void include_file_html(char *); 29 | extern void man_page_html(char*, char *); 30 | extern void ftp_html(char *); 31 | extern void www_html(char *); 32 | extern void mailto_html(char *); 33 | extern void url_html(char *); 34 | extern void set_separator(char); 35 | extern void set_lynxcgibase(char *); 36 | extern void set_cgibase(char *); 37 | extern void set_man2htmlpath(char *); 38 | extern void set_relative_html_links(void); 39 | extern void set_current_html_links(void); 40 | extern void *xmalloc(size_t size); 41 | extern void *xrealloc(void *ptr, size_t size); 42 | extern char *xstrdup(const char *s); 43 | -------------------------------------------------------------------------------- /glimpse_filters: -------------------------------------------------------------------------------- 1 | *.gz gzip -d -c 2 | *.Z gzip -d -c 3 | 4 | -------------------------------------------------------------------------------- /hman.1: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 1998 Andries Brouwer 2 | .\" 3 | .\" You may distribute under the terms of the GNU General Public 4 | .\" License as specified in the README file that comes with the man 1.0 5 | .\" distribution. 6 | .TH hman 1 "19 January 1998" 7 | .LO 1 8 | .SH NAME 9 | hman \- browse the on-line manual pages 10 | .SH SYNOPSIS 11 | .B hman 12 | [ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] \fIname\fP 13 | .br 14 | .B hman 15 | [ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] [ index ] 16 | .SH DESCRIPTION 17 | The 18 | .B hman 19 | script is an interface to man2html(1) that allows you to enter man page 20 | requests at the command line and view the output in your favourite 21 | browser. 22 | The behaviour reminds of that of 23 | .BR man (1) 24 | so that many people will be able to alias 25 | .B hman 26 | to 27 | .BR man . 28 | If the browser used is netscape, and an incarnation of netscape 29 | is running already, 30 | .B hman 31 | will pass the request to the existing browser. 32 | 33 | .SH OPTIONS 34 | .TP 35 | .B \-\^P " browser" 36 | Specify which browser (like lynx, xmosaic, arena, chimera, 37 | netscape, amaya, ...) to use. 38 | This option overrides the 39 | .B MANHTMLPAGER 40 | environment variable. 41 | The default is the non-httpd version of 42 | .BR lynx . 43 | .TP 44 | .B \-\^H " host" 45 | Specify from what host to get the man pages. 46 | This option overrides the 47 | .B MANHTMLHOST 48 | environment variable. 49 | The default is 50 | .BR localhost . 51 | 52 | .SH ENVIRONMENT 53 | .TP 54 | MANHTMLPAGER 55 | The default browser to use is selected using this environment variable. 56 | .TP 57 | MANHTMLHOST 58 | The default host to use is selected using this environment variable. 59 | 60 | .SH "SEE ALSO" 61 | .BR man (1), 62 | .BR man2html (1), 63 | .BR arena (1), 64 | .BR lynx (1), 65 | .BR netscape (1), 66 | .BR xmosaic (1), 67 | .BR glimpse (1) 68 | 69 | http://www.mcom.com/newsref/std/x-remote.html 70 | -------------------------------------------------------------------------------- /hman.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # hman - interface to the man2html scripts 4 | # 5 | # Michael Hamilton , Apr 1996 6 | # Andries Brouwer , Jan 1998. 7 | # 8 | # Usage examples: 9 | # hman - get start page 10 | # hman man2html - get man page for man2html 11 | # hman 7 locale - get section 7 man page for locale 12 | # hman 1 - section 1 index of names only 13 | # hman 3 index - section 3 index names+descriptions 14 | # hman -k editor - search all man pages for some string 15 | # hman -P arena ./twm.man - specify browser; specify man page 16 | # 17 | # hman from %version% 18 | # 19 | 20 | if [ x"$1" = x"-v" -o x"$1" = x"-V" ]; then 21 | echo "`basename $0` from %version%" 22 | exit 0 23 | fi 24 | 25 | # The user has to set MANHTMLPAGER (or he will get httpd-free lynx). 26 | # Pick your favorite browser: lynx, xmosaic, netscape, arena, amaya, grail, ... 27 | BROWSER=${MANHTMLPAGER-lynxcgi} 28 | # 29 | # If the man pages are on a remote host, specify it in MANHTMLHOST. 30 | HOST=${MANHTMLHOST-localhost} 31 | 32 | # Perhaps the browser was specified on the command line? 33 | if [ $# -gt 1 -a "$1" = "-P" ]; then 34 | BROWSER="$2" 35 | shift; shift 36 | fi 37 | 38 | # Perhaps the host was specified on the command line? 39 | if [ $# -gt 1 -a "$1" = "-H" ]; then 40 | HOST="$2" 41 | shift; shift 42 | fi 43 | 44 | # Interface to a live (already running) netscape browser. 45 | function nsfunc () { 46 | if ( /bin/ps xc | grep -q 'netscape$' ) ; then 47 | if [ -x netscape-remote ] ; then 48 | exec netscape-remote -remote "openURL($1,new_window)" 49 | else 50 | exec netscape -remote "openURL($1,new_window)" 51 | fi 52 | else 53 | netscape $1 & 54 | fi 55 | } 56 | 57 | case $BROWSER in 58 | lynxcgi) 59 | BROWSER=lynx 60 | CG="lynxcgi:/home/httpd/cgi-bin/man" 61 | ;; 62 | netscape) 63 | BROWSER=nsfunc 64 | CG="http://$HOST/cgi-bin/man" 65 | ;; 66 | *) 67 | CG="http://$HOST/cgi-bin/man" 68 | ;; 69 | esac 70 | 71 | case $# in 72 | 0) $BROWSER $CG/man2html ;; 73 | 1) case "$1" in 74 | 1|2|3|4|5|6|7|8|l|n) 75 | $BROWSER "$CG/mansec?$CG+$1" ;; 76 | /*) 77 | $BROWSER "$CG/man2html?$1" ;; 78 | */*) 79 | $BROWSER "$CG/man2html?$PWD/$1" ;; 80 | *) 81 | $BROWSER "$CG/man2html?$1" ;; 82 | esac ;; 83 | 2) case "$1" in 84 | -k) 85 | $BROWSER "$CG/mansearch?$2" ;; 86 | *) 87 | if [ "$2" = index ]; then 88 | $BROWSER "$CG/manwhatis?$CG+$1" 89 | else 90 | $BROWSER "$CG/man2html?$1+$2" 91 | fi ;; 92 | esac ;; 93 | *) echo "bad number of args" ;; 94 | esac 95 | 96 | exit 0 97 | -------------------------------------------------------------------------------- /locales/en/hman.1: -------------------------------------------------------------------------------- 1 | .\" Copyright (c) 1998 Andries Brouwer 2 | .\" 3 | .\" You may distribute under the terms of the GNU General Public 4 | .\" License as specified in the README file that comes with the man 1.0 5 | .\" distribution. 6 | .TH hman 1 "19 January 1998" 7 | .LO 1 8 | .SH NAME 9 | hman \- browse the on-line manual pages 10 | .SH SYNOPSIS 11 | .B hman 12 | [ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] \fIname\fP 13 | .br 14 | .B hman 15 | [ -P \fIbrowser\fP ] [ -H \fIhost\fP ] [ \fIsection\fP ] [ index ] 16 | .SH DESCRIPTION 17 | The 18 | .B hman 19 | script is an interface to man2html(1) that allows you to enter man page 20 | requests at the command line and view the output in your favourite 21 | browser. 22 | The behaviour reminds of that of 23 | .BR man (1) 24 | so that many people will be able to alias 25 | .B hman 26 | to 27 | .BR man . 28 | If the browser used is netscape, and an incarnation of netscape 29 | is running already, 30 | .B hman 31 | will pass the request to the existing browser. 32 | 33 | .SH OPTIONS 34 | .TP 35 | .B \-\^P " browser" 36 | Specify which browser (like lynx, xmosaic, arena, chimera, 37 | netscape, amaya, ...) to use. 38 | This option overrides the 39 | .B MANHTMLPAGER 40 | environment variable. 41 | The default is the non-httpd version of 42 | .BR lynx . 43 | .TP 44 | .B \-\^H " host" 45 | Specify from what host to get the man pages. 46 | This option overrides the 47 | .B MANHTMLHOST 48 | environment variable. 49 | The default is 50 | .BR localhost . 51 | 52 | .SH ENVIRONMENT 53 | .TP 54 | MANHTMLPAGER 55 | The default browser to use is selected using this environment variable. 56 | .TP 57 | MANHTMLHOST 58 | The default host to use is selected using this environment variable. 59 | 60 | .SH "SEE ALSO" 61 | .BR man (1), 62 | .BR man2html (1), 63 | .BR arena (1), 64 | .BR lynx (1), 65 | .BR netscape (1), 66 | .BR xmosaic (1), 67 | .BR glimpse (1) 68 | 69 | http://www.mcom.com/newsref/std/x-remote.html 70 | -------------------------------------------------------------------------------- /locales/en/man2html.1: -------------------------------------------------------------------------------- 1 | '\" t 2 | .\" Man page for man2html 3 | .\" aeb, 980101 4 | .\" 5 | .TH man2html 1 "1 January 1998" 6 | .LO 1 7 | .SH NAME 8 | man2html \- format a manual page in html 9 | .SH SYNOPSIS 10 | man2html [options] [file] 11 | .SH DESCRIPTION 12 | .B man2html 13 | converts a manual page as found in 14 | .I file 15 | (or stdin, in case no file argument, or the argument "-", is given) 16 | from man-style nroff into html, and prints the result on stdout. 17 | It does support tbl but does not know about eqn. 18 | The exit status is 0. If something goes wrong, 19 | an error page is printed on stdout. 20 | 21 | This can be used as a stand-alone utility, but is mainly intended 22 | as an auxiliary, to enable users to browse their man pages using 23 | a html browser like 24 | .BR lynx (1), 25 | .BR xmosaic (1) 26 | or 27 | .BR netscape (1). 28 | ./" (See 29 | ./" .BR man (1) 30 | ./" for info on how to browse man pages via 31 | ./" .BR man2html . 32 | ./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx" 33 | ./" in the environment.) 34 | 35 | The main part of 36 | .B man2html 37 | is the troff-to-html engine written by Richard Verhoeven (rcb5@win.tue.nl). 38 | It adds hyperlinks for the following constructs: 39 | .LP 40 | .TS 41 | l l. 42 | foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo" 43 | method://string "method://string" 44 | www.host.name "http://www.host.name" 45 | ftp.host.name "ftp://ftp.host.name" 46 | name@host "mailto:name@host" 47 | "file:/usr/include/string.h" 48 | .TE 49 | .LP 50 | (The first of these can be tuned by options - see below.) 51 | No lookup is done - the links generated need not exist. 52 | Also an index with internal hyperlinks to the various sections 53 | is generated, so that it is easier to find one's way 54 | in large man pages like 55 | .BR bash (1). 56 | 57 | .SH OPTIONS 58 | When reading from stdin, it is not always clear how to 59 | do .so expansion. The \-D option allows a script to define 60 | the working directory. 61 | .LP 62 | .TP 63 | .B \-\^D pathname 64 | Strip the last two parts from the pathname, and do a 65 | \fIchdir\fP(\fIdir\fP) before starting the conversion. 66 | .LP 67 | The \-E option allows the easy generation of error messages 68 | from a cgi script. 69 | .LP 70 | .TP 71 | .B \-\^E string 72 | Output an error page containing the given error message. 73 | .LP 74 | The general form of a hyperlink generated for a man page reference is 75 | .IP 76 | 77 | .LP 78 | with a default as shown above. The parts of this hyperlink 79 | are set using the various options. 80 | .TP 81 | .B \-\^h 82 | Set method:cgipath to http://localhost. This is the default. 83 | .TP 84 | .BI \-\^H " host[.domain][:port]" 85 | Set method:cgipath to 86 | .RI http:// host.domain:port . 87 | .TP 88 | .B \-\^l 89 | Set method:cgipath to 90 | .RI lynxcgi: /home/httpd . 91 | .TP 92 | .BI \-\^L " dir" 93 | Set method:cgipath to 94 | .RI lynxcgi: dir . 95 | .TP 96 | .BI \-\^M " man2htmlpath" 97 | Set the man2htmlpath to use. The default is 98 | .IR /cgi-bin/man/man2html . 99 | .TP 100 | .B \-\^p 101 | Set separator to '/'. 102 | .TP 103 | .B \-\^q 104 | Set separator to '?'. This is the default. 105 | .TP 106 | .B \-\^r 107 | Use relative html paths, instead of cgi-bin paths. 108 | .LP 109 | On a machine without running 110 | .BR httpd , 111 | one can use 112 | .B lynx 113 | to browse the man pages, using the lynxcgi method. 114 | When some http daemon is running, lynx, or any other browser, 115 | can be used to browse the man pages, using the http method. 116 | The option \-l (for `lynxcgi') selects the former behaviour. 117 | With it, the default cgipath is \fI/home/httpd\fP. 118 | 119 | In general, a cgi script can be called by 120 | .IP 121 | /? 122 | .LP 123 | and the environment variables PATH_INFO and QUERY_STRING 124 | will be set to and , respectively. 125 | Since lynxcgi does not handle the PATH_INFO part, we generate 126 | hyperlinks with `?' as a separator by default. 127 | The option \-p (for `path') selects '/' as a separator, while 128 | the option \-q (for `query') selects '?' as a separator. 129 | 130 | The option \-H \fIhost\fP will specify the host to use 131 | (instead of \fIlocalhost\fP). A cgi script could use 132 | .IP 133 | man2html -H $SERVER_NAME 134 | .LP 135 | if the variable SERVER_NAME is set. This would allow your machine 136 | to act as a server and export man pages. 137 | 138 | .SH BUGS 139 | There are many heuristics. The output will not always be perfect. 140 | The lynxcgi method will not work if lynx was compiled without 141 | selecting support for it. There may be problems with security. 142 | 143 | .SH AUTHOR 144 | Richard Verhoeven was the original author of 145 | .BR "man2html" . 146 | Michael Hamilton and Andries Brouwer subsequently improved on it. 147 | Federico Lucifredi is the current maintainer. 148 | 149 | .SH "SEE ALSO" 150 | .BR lynx (1), 151 | .BR man (1) 152 | -------------------------------------------------------------------------------- /locales/fr/man2html.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamano/man2html/1aa68673319324345be01ea709e56cc921f6ceeb/locales/fr/man2html.1 -------------------------------------------------------------------------------- /locales/it/hman.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamano/man2html/1aa68673319324345be01ea709e56cc921f6ceeb/locales/it/hman.1 -------------------------------------------------------------------------------- /locales/it/man2html.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamano/man2html/1aa68673319324345be01ea709e56cc921f6ceeb/locales/it/man2html.1 -------------------------------------------------------------------------------- /man2html.1: -------------------------------------------------------------------------------- 1 | '\" t 2 | .\" Man page for man2html 3 | .\" aeb, 980101 4 | .\" 5 | .TH man2html 1 "1 January 1998" 6 | .LO 1 7 | .SH NAME 8 | man2html \- format a manual page in html 9 | .SH SYNOPSIS 10 | man2html [options] [file] 11 | .SH DESCRIPTION 12 | .B man2html 13 | converts a manual page as found in 14 | .I file 15 | (or stdin, in case no file argument, or the argument "-", is given) 16 | from man-style nroff into html, and prints the result on stdout. 17 | It does support tbl but does not know about eqn. 18 | The exit status is 0. If something goes wrong, 19 | an error page is printed on stdout. 20 | 21 | This can be used as a stand-alone utility, but is mainly intended 22 | as an auxiliary, to enable users to browse their man pages using 23 | a html browser like 24 | .BR lynx (1), 25 | .BR xmosaic (1) 26 | or 27 | .BR netscape (1). 28 | ./" (See 29 | ./" .BR man (1) 30 | ./" for info on how to browse man pages via 31 | ./" .BR man2html . 32 | ./" Usually it would suffice to put "MANHTMLPAGER=/usr/bin/lynx" 33 | ./" in the environment.) 34 | 35 | The main part of 36 | .B man2html 37 | is the troff-to-html engine written by Richard Verhoeven (rcb5@win.tue.nl). 38 | It adds hyperlinks for the following constructs: 39 | .LP 40 | .TS 41 | l l. 42 | foo(3x) "http://localhost/cgi-bin/man/man2html?3x+foo" 43 | method://string "method://string" 44 | www.host.name "http://www.host.name" 45 | ftp.host.name "ftp://ftp.host.name" 46 | name@host "mailto:name@host" 47 | "file:/usr/include/string.h" 48 | .TE 49 | .LP 50 | (The first of these can be tuned by options - see below.) 51 | No lookup is done - the links generated need not exist. 52 | Also an index with internal hyperlinks to the various sections 53 | is generated, so that it is easier to find one's way 54 | in large man pages like 55 | .BR bash (1). 56 | 57 | .SH OPTIONS 58 | When reading from stdin, it is not always clear how to 59 | do .so expansion. The \-D option allows a script to define 60 | the working directory. 61 | .LP 62 | .TP 63 | .B \-\^D pathname 64 | Strip the last two parts from the pathname, and do a 65 | \fIchdir\fP(\fIdir\fP) before starting the conversion. 66 | .LP 67 | The \-E option allows the easy generation of error messages 68 | from a cgi script. 69 | .LP 70 | .TP 71 | .B \-\^E string 72 | Output an error page containing the given error message. 73 | .LP 74 | The general form of a hyperlink generated for a man page reference is 75 | .IP 76 | 77 | .LP 78 | with a default as shown above. The parts of this hyperlink 79 | are set using the various options. 80 | .TP 81 | .B \-\^h 82 | Set method:cgipath to http://localhost. This is the default. 83 | .TP 84 | .BI \-\^H " host[.domain][:port]" 85 | Set method:cgipath to 86 | .RI http:// host.domain:port . 87 | .TP 88 | .B \-\^l 89 | Set method:cgipath to 90 | .RI lynxcgi: /home/httpd . 91 | .TP 92 | .BI \-\^L " dir" 93 | Set method:cgipath to 94 | .RI lynxcgi: dir . 95 | .TP 96 | .BI \-\^M " man2htmlpath" 97 | Set the man2htmlpath to use. The default is 98 | .IR /cgi-bin/man/man2html . 99 | .TP 100 | .B \-\^p 101 | Set separator to '/'. 102 | .TP 103 | .B \-\^q 104 | Set separator to '?'. This is the default. 105 | .TP 106 | .B \-\^r 107 | Use relative html paths, instead of cgi-bin paths. 108 | .LP 109 | On a machine without running 110 | .BR httpd , 111 | one can use 112 | .B lynx 113 | to browse the man pages, using the lynxcgi method. 114 | When some http daemon is running, lynx, or any other browser, 115 | can be used to browse the man pages, using the http method. 116 | The option \-l (for `lynxcgi') selects the former behaviour. 117 | With it, the default cgipath is \fI/home/httpd\fP. 118 | 119 | In general, a cgi script can be called by 120 | .IP 121 | /? 122 | .LP 123 | and the environment variables PATH_INFO and QUERY_STRING 124 | will be set to and , respectively. 125 | Since lynxcgi does not handle the PATH_INFO part, we generate 126 | hyperlinks with `?' as a separator by default. 127 | The option \-p (for `path') selects '/' as a separator, while 128 | the option \-q (for `query') selects '?' as a separator. 129 | 130 | The option \-H \fIhost\fP will specify the host to use 131 | (instead of \fIlocalhost\fP). A cgi script could use 132 | .IP 133 | man2html -H $SERVER_NAME 134 | .LP 135 | if the variable SERVER_NAME is set. This would allow your machine 136 | to act as a server and export man pages. 137 | 138 | .SH BUGS 139 | There are many heuristics. The output will not always be perfect. 140 | The lynxcgi method will not work if lynx was compiled without 141 | selecting support for it. There may be problems with security. 142 | 143 | .SH AUTHOR 144 | Richard Verhoeven was the original author of 145 | .BR "man2html" . 146 | Michael Hamilton and Andries Brouwer subsequently improved on it. 147 | Federico Lucifredi is the current maintainer. 148 | 149 | .SH "SEE ALSO" 150 | .BR lynx (1), 151 | .BR man (1) 152 | -------------------------------------------------------------------------------- /man2html.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** This program was written by Richard Verhoeven (NL:5482ZX35) 3 | ** at the Eindhoven University of Technology. Email: rcb5@win.tue.nl 4 | ** 5 | ** Permission is granted to distribute, modify and use this program 6 | ** as long as this comment is not removed or changed. 7 | */ 8 | 9 | /* BSD mandoc stuff added by Michael Hamilton. */ 10 | 11 | /* This program is rather buggy, but in spite of that it often works. 12 | Improved things a little - April 1997 & January 1998 & Dec 2001 - 13 | aeb@cwi.nl. */ 14 | 15 | /* some code added by Tsukasa Hamnao. */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "defs.h" 25 | //#include "../src/version.h" 26 | static char version[] = "1.6f-1"; 27 | 28 | /* BSD mandoc Bd/Ed example(?) blocks */ 29 | #define BD_LITERAL 1 30 | #define BD_INDENT 2 31 | 32 | #define SIZE(a) (sizeof(a)/sizeof(*a)) 33 | 34 | static char NEWLINE[2]="\n"; 35 | static char idxlabel[6] = "ixAAA"; 36 | 37 | #define INDEXFILE "/tmp/manindex.list" 38 | 39 | char *fname; 40 | char *directory; 41 | FILE *idxfile; 42 | 43 | char eqndelimopen=0, eqndelimclose=0; 44 | char escapesym='\\', nobreaksym='\'', controlsym='.', fieldsym=0, padsym=0; 45 | 46 | char *buffer=NULL; 47 | int buffpos=0, buffmax=0; 48 | int scaninbuff=0; 49 | int still_dd=0; 50 | int tabstops[20] = { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 }; 51 | int maxtstop=12; 52 | int curpos=0; 53 | 54 | static char *scan_troff(char *c, int san, char **result); 55 | static char *scan_troff_mandoc(char *c, int san, char **result); 56 | 57 | static char **argument=NULL; 58 | 59 | static char charb[3]; 60 | 61 | static char * 62 | expand_char(int nr) 63 | { 64 | STRDEF *h; 65 | 66 | if (!nr) 67 | return NULL; 68 | 69 | h = chardef; 70 | if (h->nr != V('*','*')) { 71 | printf("chardef corrupted\n"); 72 | exit(1); 73 | } 74 | 75 | for (h = chardef; h; h = h->next) 76 | if (h->nr == nr) { 77 | curpos += h->slen; 78 | return h->st; 79 | } 80 | charb[0] = nr/256; 81 | charb[1] = nr%256; 82 | charb[2] = 0; 83 | curpos += 2; 84 | return charb; 85 | } 86 | 87 | static char * 88 | expand_string(int nr) 89 | { 90 | STRDEF *h; 91 | 92 | if (!nr) 93 | return NULL; 94 | for (h = strdef; h; h = h->next) 95 | if (h->nr == nr) { 96 | curpos += h->slen; 97 | return h->st; 98 | } 99 | return NULL; 100 | } 101 | 102 | 103 | static char outbuffer[1024]; 104 | static int obp=0; 105 | static int no_newline_output=0; /* boolean, set by \c */ 106 | static int newline_for_fun=0; 107 | static int output_possible=0; 108 | static int out_length=0; 109 | 110 | static void 111 | add_links(char *c) 112 | { 113 | /* 114 | ** Add the links to the output. 115 | ** At the moment the following are recognized: 116 | ** 117 | ** name(*) -> ../man?/name.* 118 | ** method://string -> method://string 119 | ** www.host.name -> http://www.host.name 120 | ** ftp.host.name -> ftp://ftp.host.name 121 | ** name@host -> mailto:name@host 122 | ** -> file:/usr/include/name.h (guess) 123 | ** 124 | ** Other possible links to add in the future: 125 | ** 126 | ** /dir/dir/file -> file:/dir/dir/file 127 | */ 128 | int i,j,nr; 129 | char *f, *g, *h; 130 | char *idtest[6]; /* url, mailto, www, ftp, manpage, include file */ 131 | 132 | out_length+=strlen(c); 133 | 134 | nr=0; 135 | idtest[0]=strstr(c+1,"://"); 136 | /* idtest[1]=strchr(c+1,'@'); */ 137 | idtest[1]=NULL; /* don't create mailto links. */ 138 | idtest[2]=strstr(c,"www."); 139 | idtest[3]=strstr(c,"ftp."); 140 | idtest[4]=strchr(c+1,'('); 141 | idtest[5]=strstr(c+1,".h>"); 142 | for (i=0; i<6; i++) nr += (idtest[i]!=NULL); 143 | while (nr) { 144 | j=-1; 145 | for (i=0; i<6; i++) 146 | if (idtest[i] && (j<0 || idtest[i] */ 149 | f=idtest[5]; 150 | h=f+2; 151 | g=f; 152 | while (g>c && g[-1]!=';') g--; 153 | if (g!=c) { 154 | char t; 155 | t=*g; 156 | *g=0; 157 | printf("%s",c); 158 | *g=t;*h=0; 159 | include_file_html(g); 160 | c=f+6; 161 | } else { 162 | f[5]=0; 163 | printf("%s",c); 164 | f[5]=';'; 165 | c=f+5; 166 | } 167 | break; 168 | case 4: /* manpage? */ 169 | f=idtest[j]; 170 | /* find section - accept (1), (3F), (3Xt), (n), (l) */ 171 | g=strchr(f,')'); 172 | if (g && g-f<7 /* section has length at most 5, like 3Xlib */ 173 | /* preceded by name or html markup */ 174 | && (isalnum(f[-1]) || f[-1]=='>') 175 | /* section is n or l or starts with a digit */ 176 | && strchr("123456789nl", f[1]) 177 | && (g-f == 2 || (g-f == 3 && isdigit(f[1]) && isalpha(f[2])) 178 | || (f[2] == 'X' && isdigit(f[1]))) 179 | ) { 180 | /* this might be a link */ 181 | h=f-1; 182 | /* skip html markup */ 183 | while (h>c && *h=='>') { 184 | while (h!=c && *h!='<') h--; 185 | if (h!=c) h--; 186 | } 187 | if (isalnum(*h)) { 188 | char t,te,tg,*e; 189 | e=h+1; 190 | while (h>c && (isalnum(h[-1]) || h[-1]=='_' || 191 | h[-1]=='-' || h[-1]=='.' || h[-1]==':')) 192 | h--; 193 | t=*h; *h=0; 194 | printf("%s", c); 195 | *h=t; 196 | tg=*g; *g=0; 197 | te=*e; *e=0; 198 | man_page_html(f+1, h); /* section, page */ 199 | *e=te; 200 | *g=tg; 201 | c=e; 202 | } 203 | } 204 | *f=0; 205 | printf("%s", c); 206 | *f='('; 207 | idtest[4]=f-1; 208 | c=f; 209 | break; /* manpage */ 210 | case 3: /* ftp */ 211 | case 2: /* www */ 212 | g=f=idtest[j]; 213 | while (*g && (isalnum(*g) || *g=='_' || *g=='-' || *g=='+' || 214 | *g=='.')) g++; 215 | if (g[-1]=='.') g--; 216 | if (g-f>4) { 217 | char t; 218 | t=*f; *f=0; 219 | printf("%s",c); 220 | *f=t; t=*g;*g=0; 221 | if (j==3) 222 | ftp_html(f); 223 | else 224 | www_html(f); 225 | *g=t; 226 | c=g; 227 | } else { 228 | f[3]=0; 229 | printf("%s",c); 230 | c=f+3; 231 | f[3]='.'; 232 | } 233 | break; 234 | case 1: /* mailto */ 235 | g=f=idtest[1]; 236 | while (g>c && (isalnum(g[-1]) || g[-1]=='_' || g[-1]=='-' || 237 | g[-1]=='+' || g[-1]=='.' || g[-1]=='%')) g--; 238 | h=f+1; 239 | while (*h && (isalnum(*h) || *h=='_' || *h=='-' || *h=='+' || 240 | *h=='.')) h++; 241 | if (h[-1]=='.') h--; 242 | if (h-f>4 && f-g>1) { 243 | char t; 244 | t=*g; 245 | *g=0; 246 | printf("%s",c); 247 | *g=t;t=*h;*h=0; 248 | mailto_html(g); 249 | *h=t; 250 | c=h; 251 | } else { 252 | *f=0; 253 | printf("%s",c); 254 | *f='@'; 255 | idtest[1]=c; 256 | c=f; 257 | } 258 | break; 259 | case 0: /* url */ 260 | g=f=idtest[0]; 261 | while (g>c && isalpha(g[-1]) && islower(g[-1])) g--; 262 | h=f+3; 263 | while (*h && !isspace(*h) && *h!='<' && *h!='>' && *h!='"' && 264 | *h!='&') h++; 265 | if (f-g>2 && f-g<7 && h-f>3) { 266 | char t; 267 | t=*g; 268 | *g=0; 269 | printf("%s", c); 270 | *g=t; t=*h; *h=0; 271 | url_html(g); 272 | *h=t; 273 | c=h; 274 | } else { 275 | f[1]=0; 276 | printf("%s", c); 277 | f[1]='/'; 278 | c=f+1; 279 | } 280 | break; 281 | default: 282 | break; 283 | } 284 | nr=0; 285 | if (idtest[0] && idtest[0]= buffmax) { 324 | buffer = xrealloc(buffer, buffmax*2); 325 | buffmax = buffmax*2; 326 | } 327 | if (*c != '\a') 328 | buffer[buffpos++] = *c; 329 | c++; 330 | } 331 | } else if (output_possible) { 332 | while (*c) { 333 | if (*c != '\a') 334 | outbuffer[obp++] = *c; 335 | if (*c == '\n' || obp > 1000) { 336 | outbuffer[obp] = 0; 337 | add_links(outbuffer); 338 | obp = 0; 339 | } 340 | c++; 341 | } 342 | } 343 | } 344 | 345 | /* --------------------------------------------------------------- */ 346 | /* All references to dl_set and itemdepth are here. */ 347 | /* --------------------------------------------------------------- */ 348 | static int itemdepth=0; 349 | static int dl_set[30]= { 0 }; 350 | #define noDL 0 351 | #define DL 1 352 | #define UL 2 353 | #define OL 3 354 | static char *dl_open[4] = { "", "
\n", "
    ", "
      " }; 355 | static char *dl_close[4] = { "", "
\n", "", "" }; 356 | 357 | static inline void 358 | dl_begin(void) { 359 | if (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == noDL) { 360 | out_html(dl_open[DL]); 361 | dl_set[itemdepth]=DL; 362 | } 363 | out_html("
"); 364 | } 365 | 366 | static inline void 367 | dl_end(void) { 368 | if (itemdepth < SIZE(dl_set)) { 369 | int type = dl_set[itemdepth]; 370 | if (type == DL) { 371 | out_html(dl_close[type]); 372 | dl_set[itemdepth]=noDL; 373 | } 374 | } 375 | } 376 | 377 | static inline void 378 | dl_newlevel(void) { 379 | itemdepth++; 380 | if (itemdepth < SIZE(dl_set)) 381 | dl_set[itemdepth]=noDL; 382 | out_html("
"); 383 | } 384 | 385 | static inline void 386 | dl_endlevel(void) { 387 | if (itemdepth) { 388 | dl_end(); 389 | out_html("
\n"); 390 | itemdepth--; 391 | } 392 | } 393 | 394 | static inline void 395 | dl_down(void) { 396 | while (itemdepth) 397 | dl_endlevel(); 398 | dl_end(); 399 | } 400 | 401 | static inline int 402 | dl_type(int type) { 403 | return (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == type); 404 | } 405 | 406 | static inline void 407 | dl_newlevel_type(int type) { 408 | itemdepth++; 409 | if (itemdepth < SIZE(dl_set)) { 410 | dl_set[itemdepth]=type; 411 | out_html(dl_open[type]); 412 | } 413 | } 414 | 415 | static inline void 416 | dl_endlevel_type(void) { 417 | if (itemdepth) { 418 | if (itemdepth < SIZE(dl_set)) 419 | out_html(dl_close[dl_set[itemdepth]]); 420 | itemdepth--; 421 | } 422 | } 423 | /* --------------------------------------------------------------- */ 424 | /* This stuff is broken. 425 | It generates 426 |
TIOCLINUX, subcode=0
427 | Dump the screen. 428 | argp points to a 429 | from 430 | .IP "\fBTIOCLINUX, subcode=0" 431 | Dump the screen. 432 | \fIargp\fP points to a 433 | Bug 1: incorrect nesting: is needed before
. 434 | Bug 2: incorrect font: after the .IP things are roman again. 435 | */ 436 | 437 | #define FO0 "" 438 | #define FC0 "" 439 | #define FO1 "" 440 | #define FC1 "" 441 | #define FO2 "" 442 | #define FC2 "" 443 | #define FO3 "" 444 | #define FC3 "" 445 | 446 | char *switchfont[16] = { "" , FC0 FO1, FC0 FO2, FC0 FO3, 447 | FC1 FO0, "" , FC1 FO2, FC1 FO3, 448 | FC2 FO0, FC2 FO1, "" , FC2 FO3, 449 | FC3 FO0, FC3 FO1, FC3 FO2, "" }; 450 | 451 | static char * 452 | change_to_font(int nr) 453 | { 454 | int i; 455 | switch (nr) { 456 | case '0': nr++; 457 | case '1': case '2': case '3': case '4': 458 | nr = nr-'1'; break; 459 | case V('C','W'): nr=3; break; 460 | case 'L': nr=3; break; 461 | case 'B': nr=2; break; 462 | case 'I': nr=1; break; 463 | case 0: case 1: case 2: case 3: 464 | break; 465 | case 'P': case 'R': 466 | default: nr=0; break; 467 | } 468 | i= current_font*4+nr%4; 469 | current_font=nr%4; 470 | return switchfont[i]; 471 | } 472 | 473 | static char sizebuf[200]; 474 | 475 | static char * 476 | change_to_size(int nr) 477 | { 478 | int i; 479 | switch (nr) { 480 | case '0': case '1': case '2': case '3': case '4': case '5': case '6': 481 | case '7': case '8': case '9': nr=nr-'0'; break; 482 | case '\0': break; 483 | default: nr=current_size+nr; if (nr>9) nr=9; if (nr< -9) nr=-9; break; 484 | } 485 | if (nr==current_size) return ""; 486 | i=current_font; 487 | sizebuf[0]=0; 488 | strcat(sizebuf, change_to_font(0)); 489 | if (current_size) strcat(sizebuf, ""); 490 | current_size=nr; 491 | if (nr) { 492 | int l; 493 | strcat(sizebuf, "0) sizebuf[l++]='+'; else sizebuf[l++]='-',nr=-nr; 496 | sizebuf[l++]=nr+'0'; 497 | sizebuf[l++]='"'; 498 | sizebuf[l++]='>'; 499 | sizebuf[l]=0; 500 | } 501 | strcat(sizebuf, change_to_font(i)); 502 | return sizebuf; 503 | } 504 | 505 | int asint=0; 506 | int intresult=0; 507 | 508 | #define SKIPEOL while (*c && *c++!='\n') 509 | 510 | static int skip_escape=0; 511 | static int single_escape=0; 512 | 513 | static char * 514 | scan_escape(char *c) { 515 | char *h=NULL; 516 | char b[5]; 517 | INTDEF *intd; 518 | int exoutputp,exskipescape; 519 | int i,j; 520 | 521 | intresult=0; 522 | switch (*c) { 523 | case 'e': h="\\"; curpos++;break; 524 | case '0': 525 | case ' ': h=" ";curpos++; break; 526 | case '|': h=""; break; 527 | case '"': SKIPEOL; c--; h=""; break; 528 | case '$': 529 | if (argument) { 530 | c++; 531 | i=(*c -'1'); 532 | if (!(h=argument[i])) h=""; 533 | } 534 | break; 535 | case 'z': 536 | c++; 537 | if (*c=='\\') { c=scan_escape(c+1); c--;h=""; } 538 | else { 539 | b[0]=*c; 540 | b[1]=0; 541 | h=""; 542 | } 543 | break; 544 | case 'k': c++; if (*c=='(') c+=2; 545 | case '^': 546 | case '!': 547 | case '%': 548 | case 'a': 549 | case 'd': 550 | case 'r': 551 | case 'u': 552 | case '\n': 553 | case '&': h=""; break; 554 | case '(': 555 | c++; 556 | i= c[0]*256+c[1]; 557 | c++; 558 | h = expand_char(i); 559 | break; 560 | case '*': 561 | c++; 562 | if (*c=='(') { 563 | c++; 564 | i= c[0]*256+c[1]; 565 | c++; 566 | } else 567 | i= *c *256+' '; 568 | h = expand_string(i); 569 | break; 570 | case 'f': 571 | c++; 572 | if (*c=='\\') { 573 | c++; 574 | c=scan_escape(c); 575 | c--; 576 | i=intresult; 577 | } else if (*c != '(') 578 | i=*c; 579 | else { 580 | c++; 581 | i=c[0]*256+c[1]; 582 | c++; 583 | } 584 | if (!skip_escape) h=change_to_font(i); else h=""; 585 | break; 586 | case 's': 587 | c++; 588 | j=0;i=0; 589 | if (*c=='-') {j= -1; c++;} else if (*c=='+') {j=1; c++;} 590 | if (*c=='0') c++; else if (*c=='\\') { 591 | c++; 592 | c=scan_escape(c); 593 | i=intresult; if (!j) j=1; 594 | } else 595 | while (isdigit(*c) && (!i || (!j && i<4))) i=i*10+(*c++)-'0'; 596 | if (!j) { j=1; if (i) i=i-10; } 597 | if (!skip_escape) h=change_to_size(i*j); else h=""; 598 | c--; 599 | break; 600 | case 'n': 601 | c++; 602 | j=0; 603 | switch (*c) { 604 | case '+': j=1; c++; break; 605 | case '-': j=-1; c++; break; 606 | default: break; 607 | } 608 | if (*c=='(') { 609 | c++; 610 | i=V(c[0],c[1]); 611 | c=c+1; 612 | } else { 613 | i=V(c[0],' '); 614 | } 615 | intd=intdef; 616 | while (intd && intd->nr!=i) intd=intd->next; 617 | if (intd) { 618 | intd->val=intd->val+j*intd->incr; 619 | intresult=intd->val; 620 | } else { 621 | switch (i) { 622 | case V('.','s'): intresult=current_size; break; 623 | case V('.','f'): intresult=current_font; break; 624 | default: intresult=0; break; 625 | } 626 | } 627 | h=""; 628 | break; 629 | case 'w': 630 | c++; 631 | i=*c; 632 | c++; 633 | exoutputp=output_possible; 634 | exskipescape=skip_escape; 635 | output_possible=0; 636 | skip_escape=1; 637 | j=0; 638 | while (*c!=i) { 639 | j++; 640 | if (*c==escapesym) c=scan_escape(c+1); else c++; 641 | } 642 | output_possible=exoutputp; 643 | skip_escape=exskipescape; 644 | intresult=j; 645 | break; 646 | case 'l': h="
"; curpos=0; 647 | case 'b': 648 | case 'v': 649 | case 'x': 650 | case 'o': 651 | case 'L': 652 | case 'h': 653 | c++; 654 | i=*c; 655 | c++; 656 | exoutputp=output_possible; 657 | exskipescape=skip_escape; 658 | output_possible=0; 659 | skip_escape=1; 660 | while (*c != i) 661 | if (*c==escapesym) c=scan_escape(c+1); 662 | else c++; 663 | output_possible=exoutputp; 664 | skip_escape=exskipescape; 665 | break; 666 | case 'c': no_newline_output=1; break; 667 | case '{': newline_for_fun++; h="";break; 668 | case '}': if (newline_for_fun) newline_for_fun--; h="";break; 669 | case 'p': h="
\n";curpos=0; break; 670 | case 't': h="\t";curpos=(curpos+8)&0xfff8; break; 671 | case '<': h="<";curpos++; break; 672 | case '>': h=">";curpos++; break; 673 | case '\\': if (single_escape) { c--; break;} 674 | default: b[0]=*c; b[1]=0; h=b; curpos++; break; 675 | } 676 | c++; 677 | if (!skip_escape) out_html(h); 678 | return c; 679 | } 680 | 681 | typedef struct TABLEITEM TABLEITEM; 682 | 683 | struct TABLEITEM { 684 | char *contents; 685 | int size,align,valign,colspan,rowspan,font,vleft,vright,space,width; 686 | TABLEITEM *next; 687 | }; 688 | 689 | static TABLEITEM emptyfield = {NULL,0,0,0,1,1,0,0,0,0,0,NULL}; 690 | typedef struct TABLEROW TABLEROW; 691 | 692 | struct TABLEROW { 693 | TABLEITEM *first; 694 | TABLEROW *prev, *next; 695 | }; 696 | 697 | static char *tableopt[]= { "center", "expand", "box", "allbox", "doublebox", 698 | "tab", "linesize", "delim", NULL }; 699 | static int tableoptl[] = { 6,6,3,6,9,3,8,5,0}; 700 | 701 | 702 | static void clear_table(TABLEROW *table) 703 | { 704 | TABLEROW *tr1,*tr2; 705 | TABLEITEM *ti1,*ti2; 706 | 707 | tr1=table; 708 | while (tr1->prev) tr1=tr1->prev; 709 | while (tr1) { 710 | ti1=tr1->first; 711 | while (ti1) { 712 | ti2=ti1->next; 713 | if (ti1->contents) free(ti1->contents); 714 | free(ti1); 715 | ti1=ti2; 716 | } 717 | tr2=tr1; 718 | tr1=tr1->next; 719 | free(tr2); 720 | } 721 | } 722 | 723 | char *scan_expression(char *c, int *result); 724 | 725 | static char *scan_format(char *c, TABLEROW **result, int *maxcol) 726 | { 727 | TABLEROW *layout, *currow; 728 | TABLEITEM *curfield; 729 | int i,j; 730 | if (*result) { 731 | clear_table(*result); 732 | } 733 | layout= currow=(TABLEROW*) xmalloc(sizeof(TABLEROW)); 734 | currow->next=currow->prev=NULL; 735 | currow->first=curfield=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); 736 | *curfield=emptyfield; 737 | while (*c && *c!='.') { 738 | switch (*c) { 739 | case 'C': case 'c': case 'N': case 'n': 740 | case 'R': case 'r': case 'A': case 'a': 741 | case 'L': case 'l': case 'S': case 's': 742 | case '^': case '_': 743 | if (curfield->align) { 744 | curfield->next=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); 745 | curfield=curfield->next; 746 | *curfield=emptyfield; 747 | } 748 | curfield->align=toupper(*c); 749 | c++; 750 | break; 751 | case 'i': case 'I': case 'B': case 'b': 752 | curfield->font = toupper(*c); 753 | c++; 754 | break; 755 | case 'f': case 'F': 756 | c++; 757 | curfield->font = toupper(*c); 758 | c++; 759 | if (!isspace(*c)) c++; 760 | break; 761 | case 't': case 'T': curfield->valign='t'; c++; break; 762 | case 'p': case 'P': 763 | c++; 764 | i=j=0; 765 | if (*c=='+') { j=1; c++; } 766 | if (*c=='-') { j=-1; c++; } 767 | while (isdigit(*c)) i=i*10+(*c++)-'0'; 768 | if (j) curfield->size= i*j; else curfield->size=j-10; 769 | break; 770 | case 'v': case 'V': 771 | case 'w': case 'W': 772 | // c=scan_expression(c+2,&curfield->width); 773 | c++; 774 | if (*c == '(') { 775 | c=scan_expression(c+1,&curfield->width); 776 | } else { 777 | i=0; 778 | while (isdigit(*c)) i=i*10+(*c++)-'0'; 779 | curfield->width=i; 780 | } 781 | break; 782 | case '|': 783 | if (curfield->align) curfield->vleft++; 784 | else curfield->vright++; 785 | c++; 786 | break; 787 | case 'e': case 'E': 788 | c++; 789 | break; 790 | case '0': case '1': case '2': case '3': case '4': 791 | case '5': case '6': case '7': case '8': case '9': 792 | i=0; 793 | while (isdigit(*c)) i=i*10+(*c++)-'0'; 794 | curfield->space=i; 795 | break; 796 | case ',': case '\n': 797 | currow->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); 798 | currow->next->prev=currow; 799 | currow=currow->next; 800 | currow->next=NULL; 801 | curfield=currow->first=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); 802 | *curfield=emptyfield; 803 | c++; 804 | break; 805 | default: 806 | c++; 807 | break; 808 | } 809 | } 810 | if (*c=='.') while (*c++!='\n'); 811 | *maxcol=0; 812 | currow=layout; 813 | while (currow) { 814 | curfield=layout->first; 815 | i=0; 816 | while (curfield) { 817 | i++; 818 | curfield=curfield->next; 819 | } 820 | if (i>*maxcol) *maxcol=i; 821 | currow=currow->next; 822 | } 823 | *result=layout; 824 | return c; 825 | } 826 | 827 | static TABLEROW * 828 | next_row(TABLEROW *tr) 829 | { 830 | if (tr->next) { 831 | tr=tr->next; 832 | if (!tr->next) next_row(tr); 833 | return tr; 834 | } else { 835 | TABLEITEM *ti, *ti2; 836 | tr->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); 837 | tr->next->prev=tr; 838 | ti=tr->first; 839 | tr=tr->next; 840 | tr->next=NULL; 841 | if (ti) tr->first=ti2=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); 842 | else tr->first=ti2=NULL; 843 | while (ti!=ti2) { 844 | *ti2=*ti; 845 | ti2->contents=NULL; 846 | if ((ti=ti->next)) { 847 | ti2->next=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); 848 | } 849 | ti2=ti2->next; 850 | } 851 | return tr; 852 | } 853 | } 854 | 855 | char itemreset[20]="\\fR\\s0"; 856 | 857 | static char * 858 | scan_table(char *c) { 859 | char *h; 860 | char *g; 861 | int center=0, expand=0, box=0, border=0, linesize=1; 862 | int i,j,maxcol=0, finished=0; 863 | int oldfont, oldsize,oldfillout; 864 | char itemsep='\t'; 865 | TABLEROW *layout=NULL, *currow; 866 | TABLEITEM *curfield; 867 | while (*c++!='\n'); /* skip TS */ 868 | h=c; 869 | if (*h=='.') return c-1; 870 | oldfont=current_font; 871 | oldsize=current_size; 872 | oldfillout=fillout; 873 | out_html(change_to_font(0)); 874 | out_html(change_to_size(0)); 875 | if (!fillout) { 876 | fillout=1; 877 | out_html(""); 878 | } 879 | while (*h && *h!='\n') h++; 880 | if (h[-1]==';') { 881 | /* scan table options */ 882 | while (cfirst; 908 | i=0; 909 | while (!finished && *c) { 910 | /* search item */ 911 | h=c; 912 | if ((*c=='_' || *c=='=') && (c[1]==itemsep || c[1]=='\n')) { 913 | if (c[-1]=='\n' && c[1]=='\n') { 914 | if (currow->prev) { 915 | currow->prev->next=(TABLEROW*) xmalloc(sizeof(TABLEROW)); 916 | currow->prev->next->next=currow; 917 | currow->prev->next->prev=currow->prev; 918 | currow->prev=currow->prev->next; 919 | } else { 920 | currow->prev=layout=(TABLEROW*) xmalloc(sizeof(TABLEROW)); 921 | currow->prev->prev=NULL; 922 | currow->prev->next=currow; 923 | } 924 | curfield=currow->prev->first= 925 | (TABLEITEM*) xmalloc(sizeof(TABLEITEM)); 926 | *curfield=emptyfield; 927 | curfield->align=*c; 928 | curfield->colspan=maxcol; 929 | curfield=currow->first; 930 | c=c+2; 931 | } else { 932 | if (curfield) { 933 | curfield->align=*c; 934 | do { 935 | curfield=curfield->next; 936 | } while (curfield && curfield->align=='S'); 937 | } 938 | if (c[1]=='\n') { 939 | currow=next_row(currow); 940 | curfield=currow->first; 941 | } 942 | c=c+2; 943 | } 944 | } else if (*c=='T' && c[1]=='{') { 945 | h=c+2; 946 | c=strstr(h,"\nT}"); 947 | c++; 948 | *c=0; 949 | g=NULL; 950 | scan_troff(h, 0, &g); 951 | scan_troff(itemreset, 0, &g); 952 | *c='T'; 953 | c+=3; 954 | if (curfield) { 955 | curfield->contents=g; 956 | do { 957 | curfield=curfield->next; 958 | } while (curfield && curfield->align=='S'); 959 | } else 960 | if (g) free(g); 961 | if (c[-1]=='\n') { 962 | currow=next_row(currow); 963 | curfield=currow->first; 964 | } 965 | } else if (*c=='.' && c[1]=='T' && c[2]=='&' && c[-1]=='\n') { 966 | TABLEROW *hr; 967 | while (*c++!='\n'); 968 | hr=currow; 969 | currow=currow->prev; 970 | hr->prev=NULL; 971 | c=scan_format(c,&hr, &i); 972 | hr->prev=currow; 973 | currow->next=hr; 974 | currow=hr; 975 | next_row(currow); 976 | curfield=currow->first; 977 | } else if (*c=='.' && c[1]=='T' && c[2]=='E' && c[-1]=='\n') { 978 | finished=1; 979 | while (*c++!='\n'); 980 | if (currow->prev) 981 | currow->prev->next=NULL; 982 | currow->prev=NULL; 983 | clear_table(currow); 984 | } else if (*c=='.' && c[-1]=='\n' && !isdigit(c[1])) { 985 | /* skip troff request inside table (usually only .sp ) */ 986 | while (*c++!='\n'); 987 | } else { 988 | h=c; 989 | while (*c && (*c!=itemsep || c[-1]=='\\') && 990 | (*c!='\n' || c[-1]=='\\')) c++; 991 | i=0; 992 | if (*c==itemsep) {i=1; *c='\n'; } 993 | if (h[0]=='\\' && h[2]=='\n' && 994 | (h[1]=='_' || h[1]=='^')) { 995 | if (curfield) { 996 | curfield->align=h[1]; 997 | do { 998 | curfield=curfield->next; 999 | } while (curfield && curfield->align=='S'); 1000 | } 1001 | h=h+3; 1002 | } else { 1003 | g=NULL; 1004 | h=scan_troff(h,1,&g); 1005 | scan_troff(itemreset,0,&g); 1006 | if (curfield) { 1007 | curfield->contents=g; 1008 | do { 1009 | curfield=curfield->next; 1010 | } while (curfield && curfield->align=='S'); 1011 | } else if (g) free(g); 1012 | } 1013 | if (i) *c=itemsep; 1014 | c=h; 1015 | if (c[-1]=='\n') { 1016 | currow=next_row(currow); 1017 | curfield=currow->first; 1018 | } 1019 | } 1020 | } 1021 | /* calculate colspan and rowspan */ 1022 | currow=layout; 1023 | while (currow->next) currow=currow->next; 1024 | while (currow) { 1025 | TABLEITEM *ti, *ti1=NULL, *ti2=NULL; 1026 | ti=currow->first; 1027 | if (currow->prev) ti1=currow->prev->first; 1028 | while (ti) { 1029 | switch (ti->align) { 1030 | case 'S': 1031 | if (ti2) { 1032 | ti2->colspan++; 1033 | if (ti2->rowspanrowspan) ti2->rowspan=ti->rowspan; 1034 | } 1035 | break; 1036 | case '^': 1037 | if (ti1) ti1->rowspan++; 1038 | default: 1039 | if (!ti2) ti2=ti; 1040 | else { 1041 | do { 1042 | ti2=ti2->next; 1043 | } while (ti2 && curfield->align=='S'); 1044 | } 1045 | break; 1046 | } 1047 | ti=ti->next; 1048 | if (ti1) ti1=ti1->next; 1049 | } 1050 | currow=currow->prev; 1051 | } 1052 | /* produce html output */ 1053 | if (center) out_html("
"); 1054 | if (box==2) out_html(""); 1066 | curfield=currow->first; 1067 | while (curfield) { 1068 | if (curfield->align!='S' && curfield->align!='^') { 1069 | out_html("align) { 1071 | case 'N': 1072 | curfield->space+=4; 1073 | case 'R': 1074 | out_html(" ALIGN=right"); 1075 | break; 1076 | case 'C': 1077 | out_html(" ALIGN=center"); 1078 | default: 1079 | break; 1080 | } 1081 | if (!curfield->valign && curfield->rowspan>1) 1082 | out_html(" VALIGN=center"); 1083 | if (curfield->colspan>1) { 1084 | char buf[5]; 1085 | out_html(" COLSPAN="); 1086 | sprintf(buf, "%i", curfield->colspan); 1087 | out_html(buf); 1088 | } 1089 | if (curfield->rowspan>1) { 1090 | char buf[5]; 1091 | out_html(" ROWSPAN="); 1092 | sprintf(buf, "%i", curfield->rowspan); 1093 | out_html(buf); 1094 | } 1095 | j=j+curfield->colspan; 1096 | out_html(">"); 1097 | if (curfield->size) out_html(change_to_size(curfield->size)); 1098 | if (curfield->font) out_html(change_to_font(curfield->font)); 1099 | switch (curfield->align) { 1100 | case '=': out_html("

"); break; 1101 | case '_': out_html("
"); break; 1102 | default: 1103 | if (curfield->contents) out_html(curfield->contents); 1104 | break; 1105 | } 1106 | if (curfield->space) 1107 | for (i=0; ispace;i++) out_html(" "); 1108 | if (curfield->font) out_html(change_to_font(0)); 1109 | if (curfield->size) out_html(change_to_size(0)); 1110 | if (j>=maxcol && curfield->align>'@' && curfield->align!='_') 1111 | out_html("
"); 1112 | out_html(""); 1113 | } 1114 | curfield=curfield->next; 1115 | } 1116 | out_html("
\n"); 1117 | currow=currow->next; 1118 | } 1119 | if (box && !border) out_html("
"); 1055 | out_html("
\n"); 1062 | currow=layout; 1063 | while (currow) { 1064 | j=0; 1065 | out_html("
"); 1120 | out_html(""); 1121 | if (box==2) out_html(""); 1122 | if (center) out_html("
\n"); 1123 | else out_html("\n"); 1124 | if (!oldfillout) out_html("
");
1125 |     fillout=oldfillout;
1126 |     out_html(change_to_size(oldsize));
1127 |     out_html(change_to_font(oldfont));
1128 |     return c;
1129 | }
1130 | 
1131 | char *scan_expression(char *c, int *result) {
1132 |     int value=0,value2,sign=1,opex=0;
1133 |     char oper='c';
1134 | 
1135 |     if (*c=='!') {
1136 | 	c=scan_expression(c+1, &value);
1137 | 	value= (!value);
1138 |     } else if (*c=='n') {
1139 | 	c++;
1140 | 	value=nroff;
1141 |     } else if (*c=='t') {
1142 | 	c++;
1143 | 	value=1-nroff;
1144 |     } else if (*c=='\'' || *c=='"' || *c<' ' || (*c=='\\' && c[1]=='(')) {
1145 | 	/* ?string1?string2?
1146 | 	** test if string1 equals string2.
1147 | 	*/
1148 | 	char *st1=NULL, *st2=NULL, *h;
1149 | 	char *tcmp=NULL;
1150 | 	char sep;
1151 | 	sep=*c;
1152 | 	if (sep=='\\') {
1153 | 	    tcmp=c;
1154 | 	    c=c+3;
1155 | 	}
1156 | 	c++;
1157 | 	h=c;
1158 | 	while (*c!= sep && (!tcmp || strncmp(c,tcmp,4))) c++;
1159 | 	*c='\n';
1160 | 	scan_troff(h, 1, &st1);
1161 | 	*c=sep;
1162 | 	if (tcmp) c=c+3;
1163 | 	c++;
1164 | 	h=c;
1165 | 	while (*c!=sep && (!tcmp || strncmp(c,tcmp,4))) c++;
1166 | 	*c='\n';
1167 | 	scan_troff(h,1,&st2);
1168 | 	*c=sep;
1169 | 	if (!st1 && !st2) value=1;
1170 | 	else if (!st1 || !st2) value=0;
1171 | 	else value=(!strcmp(st1, st2));
1172 | 	if (st1) free(st1);
1173 | 	if (st2) free(st2);
1174 | 	if (tcmp) c=c+3;
1175 | 	c++;
1176 |     } else {
1177 | 	while (*c && !isspace(*c) && *c!=')') {
1178 | 	    opex=0;
1179 | 	    switch (*c) {
1180 | 	    case '(':
1181 | 		c=scan_expression(c+1, &value2);
1182 | 		value2=sign*value2;
1183 | 		opex=1;
1184 | 		break;
1185 | 	    case '.':
1186 | 	    case '0': case '1':
1187 | 	    case '2': case '3':
1188 | 	    case '4': case '5':
1189 | 	    case '6': case '7':
1190 | 	    case '8': case '9': {
1191 | 		int num=0,denum=1;
1192 | 		value2=0;
1193 | 		while (isdigit(*c)) value2=value2*10+((*c++)-'0');
1194 | 		if (*c=='.') {
1195 | 		    c++;
1196 | 		    while (isdigit(*c)) {
1197 | 			num=num*10+((*c++)-'0');
1198 | 			denum=denum*10;
1199 | 		    }
1200 | 		}
1201 | 		if (isalpha(*c)) {
1202 | 		    /* scale indicator */
1203 | 		    switch (*c) {
1204 | 		    case 'i': /* inch -> 10pt */
1205 | 			value2=value2*10+(num*10+denum/2)/denum;
1206 | 			num=0;
1207 | 			break;
1208 | 		    default:
1209 | 			break;
1210 | 		    }
1211 | 		    c++;
1212 | 		}
1213 | 		value2=value2+(num+denum/2)/denum;
1214 | 		value2=sign*value2;
1215 | 		opex=1;
1216 | 		break;
1217 | 	    }
1218 | 	    case '\\':
1219 | 		c=scan_escape(c+1);
1220 | 		value2=intresult*sign;
1221 | 		if (isalpha(*c)) c++; /* scale indicator */
1222 | 		opex=1;
1223 | 		break;
1224 | 	    case '-':
1225 | 		if (oper) { sign=-1; c++; break; }
1226 | 	    case '>':
1227 | 	    case '<':
1228 | 	    case '+':
1229 | 	    case '/':
1230 | 	    case '*':
1231 | 	    case '%':
1232 | 	    case '&':
1233 | 	    case '=':
1234 | 	    case ':':
1235 | 		if (c[1]=='=') oper=(*c++) +16; else oper=*c;
1236 | 		c++;
1237 | 		break;
1238 | 	    default: c++; break;
1239 | 	    }
1240 | 	    if (opex) {
1241 | 		sign=1;
1242 | 		switch (oper) {
1243 | 		case 'c': value=value2; break;
1244 | 		case '-': value=value-value2; break;
1245 | 		case '+': value=value+value2; break;
1246 | 		case '*': value=value*value2; break;
1247 | 		case '/': if (value2) value=value/value2; break;
1248 | 		case '%': if (value2) value=value%value2; break;
1249 | 		case '<': value=(value': value=(value>value2); break;
1251 | 		case '>'+16: value=(value>=value2); break;
1252 | 		case '<'+16: value=(value<=value2); break;
1253 | 		case '=': case '='+16: value=(value==value2); break;
1254 | 		case '&': value = (value && value2); break;
1255 | 		case ':': value = (value || value2); break;
1256 | 		default: fprintf(stderr,
1257 | 				 "man2html: Unknown operator %c.\n", oper);
1258 | 		}
1259 | 		oper=0;
1260 | 	    }
1261 | 	}
1262 | 	if (*c==')') c++;
1263 |     }
1264 |     *result=value;
1265 |     return c;
1266 | }
1267 | 
1268 | static void
1269 | trans_char(char *c, char s, char t) {
1270 | 	char *sl = c;
1271 | 	int slash = 0;
1272 | 
1273 | 	while (*sl && (*sl != '\n' || slash)) {
1274 | 		if (!slash) {
1275 | 			if (*sl == escapesym)
1276 | 				slash = 1;
1277 | 			else if (*sl == s)
1278 | 				*sl = t;
1279 | 		} else
1280 | 			slash = 0;
1281 | 		sl++;
1282 | 	}
1283 | }
1284 | 
1285 | /*
1286 |  * Read STR until end-of-line (not preceded by \).
1287 |  * Find whitespace separated words, and store starts in WORDS of lth MAXN.
1288 |  * Return number of words in N.
1289 |  * Replace each end-of-word by the character EOW (usually \n or 0).
1290 |  * Return pointer to last char seen (either \n or 0).
1291 |  *
1292 |  * A part \"... is skipped.
1293 |  * Quotes not preceded by \ are replaced by \a.
1294 |  */
1295 | static char *
1296 | fill_words(char *str, char *words[], int maxn, int *n, char eow) {
1297 | 	char *s = str;
1298 | 	int backslash = 0;
1299 | 	int skipspace = 0;	/* 1 if space is not end-of-word */
1300 | 
1301 | 	*n = 0;
1302 | 	words[*n] = s;
1303 | 	while (*s && (*s != '\n' || backslash)) {
1304 | 		if (!backslash) {
1305 | 			if (*s == '"') {
1306 | 				*s = '\a';
1307 | 				skipspace = !skipspace;
1308 | 			} else if (*s == escapesym) {
1309 | 				backslash = 1;
1310 | 			} else if ((*s == ' ' || *s == '\t') && !skipspace) {
1311 | 				*s = eow;
1312 | 				if (words[*n] != s && *n < maxn-1)
1313 | 					(*n)++;
1314 | 				words[*n] = s+1;
1315 | 			}
1316 | 		} else {
1317 | 			if (*s == '"') {
1318 | 				s--;
1319 | 				*s = eow;
1320 | 				if (words[*n] != s && *n < maxn-1)
1321 | 					(*n)++;
1322 | 				s++;
1323 | 				while (*s && *s != '\n') s++;
1324 | 				words[*n] = s;
1325 | 				s--;
1326 | 			}
1327 | 			backslash = 0;
1328 | 		}
1329 | 		s++;
1330 | 	}
1331 | 	if (s != words[*n])
1332 | 		(*n)++;
1333 | 	return s;
1334 | }
1335 | 
1336 | 
1337 | char *section_list[] = {
1338 |     "1", "User Commands ",
1339 |     "1C", "User Commands",
1340 |     "1G", "User Commands",
1341 |     "1S", "User Commands",
1342 |     "1V", "User Commands ",
1343 |     "2", "System Calls",
1344 |     "2V", "System Calls",
1345 |     "3", "C Library Functions",
1346 |     "3C", "Compatibility Functions",
1347 |     "3F", "Fortran Library Routines",
1348 |     "3K", "Kernel VM Library Functions",
1349 |     "3L", "Lightweight Processes Library",
1350 |     "3M", "Mathematical Library",
1351 |     "3N", "Network Functions",
1352 |     "3R", "RPC Services Library",
1353 |     "3S", "Standard I/O Functions",
1354 |     "3V", "C Library Functions",
1355 |     "3X", "Miscellaneous Library Functions",
1356 |     "4", "Devices and Network Interfaces",
1357 |     "4F", "Protocol Families",
1358 |     "4I", "Devices and Network Interfaces",
1359 |     "4M", "Devices and Network Interfaces",
1360 |     "4N", "Devices and Network Interfaces",
1361 |     "4P", "Protocols",
1362 |     "4S", "Devices and Network Interfaces",
1363 |     "4V", "Devices and Network Interfaces",
1364 |     "5", "File Formats",
1365 |     "5V", "File Formats",
1366 |     "6", "Games and Demos",
1367 |     "7", "Environments, Tables, and Troff Macros",
1368 |     "7V", "Environments, Tables, and Troff Macros",
1369 |     "8", "Maintenance Commands",
1370 |     "8C", "Maintenance Commands",
1371 |     "8S", "Maintenance Commands",
1372 |     "8V", "Maintenance Commands",
1373 |     "L", "Local Commands",
1374 | /* for Solaris: 
1375 |     "1", "User Commands",
1376 |     "1B", "SunOS/BSD Compatibility Package Commands",
1377 |     "1b", "SunOS/BSD Compatibility Package Commands",
1378 |     "1C", "Communication Commands ",
1379 |     "1c", "Communication Commands",
1380 |     "1F", "FMLI Commands ",
1381 |     "1f", "FMLI Commands",
1382 |     "1G", "Graphics and CAD Commands ",
1383 |     "1g", "Graphics and CAD Commands ",
1384 |     "1M", "Maintenance Commands",
1385 |     "1m", "Maintenance Commands",
1386 |     "1S", "SunOS Specific Commands",
1387 |     "1s", "SunOS Specific Commands",
1388 |     "2", "System Calls",
1389 |     "3", "C Library Functions",
1390 |     "3B", "SunOS/BSD Compatibility Library Functions",
1391 |     "3b", "SunOS/BSD Compatibility Library Functions",
1392 |     "3C", "C Library Functions",
1393 |     "3c", "C Library Functions",
1394 |     "3E", "C Library Functions",
1395 |     "3e", "C Library Functions",
1396 |     "3F", "Fortran Library Routines",
1397 |     "3f", "Fortran Library Routines",
1398 |     "3G", "C Library Functions",
1399 |     "3g", "C Library Functions",
1400 |     "3I", "Wide Character Functions",
1401 |     "3i", "Wide Character Functions",
1402 |     "3K", "Kernel VM Library Functions",
1403 |     "3k", "Kernel VM Library Functions",
1404 |     "3L", "Lightweight Processes Library",
1405 |     "3l", "Lightweight Processes Library",
1406 |     "3M", "Mathematical Library",
1407 |     "3m", "Mathematical Library",
1408 |     "3N", "Network Functions",
1409 |     "3n", "Network Functions",
1410 |     "3R", "Realtime Library",
1411 |     "3r", "Realtime Library",
1412 |     "3S", "Standard I/O Functions",
1413 |     "3s", "Standard I/O Functions",
1414 |     "3T", "Threads Library",
1415 |     "3t", "Threads Library",
1416 |     "3W", "C Library Functions",
1417 |     "3w", "C Library Functions",
1418 |     "3X", "Miscellaneous Library Functions",
1419 |     "3x", "Miscellaneous Library Functions",
1420 |     "4", "File Formats",
1421 |     "4B", "SunOS/BSD Compatibility Package File Formats",
1422 |     "4b", "SunOS/BSD Compatibility Package File Formats",
1423 |     "5", "Headers, Tables, and Macros",
1424 |     "6", "Games and Demos",
1425 |     "7", "Special Files",
1426 |     "7B", "SunOS/BSD Compatibility Special Files",
1427 |     "7b", "SunOS/BSD Compatibility Special Files",
1428 |     "8", "Maintenance Procedures",
1429 |     "8C", "Maintenance Procedures",
1430 |     "8c", "Maintenance Procedures",
1431 |     "8S", "Maintenance Procedures",
1432 |     "8s", "Maintenance Procedures",
1433 |     "9", "DDI and DKI",
1434 |     "9E", "DDI and DKI Driver Entry Points",
1435 |     "9e", "DDI and DKI Driver Entry Points",
1436 |     "9F", "DDI and DKI Kernel Functions",
1437 |     "9f", "DDI and DKI Kernel Functions",
1438 |     "9S", "DDI and DKI Data Structures",
1439 |     "9s", "DDI and DKI Data Structures",
1440 |     "L", "Local Commands",
1441 | */
1442 |     NULL, "Misc. Reference Manual Pages",
1443 |     NULL, NULL
1444 | };
1445 | 
1446 | static char *
1447 | section_name(char *c)
1448 | {
1449 |     int i=0;
1450 | 
1451 |     if (!c) return "";
1452 |     while (section_list[i] && strcmp(c,section_list[i])) i=i+2;
1453 |     if (section_list[i+1]) return section_list[i+1];
1454 |     else return c;
1455 | }
1456 | 
1457 | int manidxlen = 0;
1458 | char *manidx = NULL;
1459 | int subs = 0;
1460 | int mip = 0;	/* current offset in manidx[] */
1461 | char label[5]="lbAA";
1462 | 
1463 | static void
1464 | manidx_need(int m) {
1465 | 	if (mip + m >= manidxlen) {
1466 | 		manidxlen += 10000;
1467 | 		manidx = xrealloc(manidx, manidxlen);
1468 | 	}
1469 | }
1470 | 
1471 | static void
1472 | add_to_index(int level, char *item)
1473 | {
1474 |     char *c = NULL;
1475 | 
1476 |     label[3]++;
1477 |     if (label[3]>'Z') {
1478 | 	label[3]='A';
1479 | 	label[2]++;
1480 |     }
1481 | 
1482 |     if (level != subs) {
1483 | 	manidx_need(6);
1484 | 	if (subs) {
1485 | 	    strcpy(manidx+mip, "\n");
1486 | 	    mip += 6;
1487 | 	} else {
1488 | 	    strcpy(manidx+mip, "
\n"); 1489 | mip += 5; 1490 | } 1491 | } 1492 | subs = level; 1493 | 1494 | scan_troff(item, 1, &c); 1495 | manidx_need(100 + strlen(c)); 1496 | sprintf(manidx+mip, "
%s
\n", label, c); 1497 | if (c) free(c); 1498 | while (manidx[mip]) mip++; 1499 | } 1500 | 1501 | static char * 1502 | skip_till_newline(char *c) 1503 | { 1504 | int lvl=0; 1505 | 1506 | while (*c && (*c!='\n' || lvl>0)) { 1507 | if (*c=='\\') { 1508 | c++; 1509 | if (*c=='}') lvl--; else if (*c=='{') lvl++; 1510 | } 1511 | c++; 1512 | } 1513 | c++; 1514 | if (lvl<0 && newline_for_fun) { 1515 | newline_for_fun = newline_for_fun+lvl; 1516 | if (newline_for_fun<0) newline_for_fun=0; 1517 | } 1518 | return c; 1519 | } 1520 | 1521 | int ifelseval=0; 1522 | 1523 | static char * 1524 | scan_request(char *c) { 1525 | /* BSD Mandoc stuff - by Michael Hamilton */ 1526 | static int mandoc_synopsis=0; /* True if we are in the synopsis section */ 1527 | static int mandoc_command=0; /* True if this is mandoc page */ 1528 | static int mandoc_bd_options; /* Only copes with non-nested Bd's */ 1529 | static int inXo=0; 1530 | 1531 | int i,j,mode = 0; 1532 | char *h; 1533 | char *wordlist[20]; 1534 | int words; 1535 | char *sl; 1536 | STRDEF *owndef; 1537 | 1538 | while (*c == ' ' || *c == '\t') 1539 | c++; 1540 | if (c[0] == '\n') 1541 | return c+1; 1542 | if (c[1] == '\n') 1543 | j = 1; 1544 | else 1545 | j = 2; 1546 | while (c[j] == ' ' || c[j] == '\t') 1547 | j++; 1548 | if (c[0] == escapesym) { 1549 | /* some pages use .\" .\$1 .\} */ 1550 | /* .\$1 is too difficult/stupid */ 1551 | if (c[1] == '$') 1552 | c = skip_till_newline(c); 1553 | else 1554 | c = scan_escape(c+1); 1555 | } else { 1556 | i=V(c[0],c[1]); 1557 | switch (i) { 1558 | case V('a','b'): 1559 | h=c+j; 1560 | while (*h && *h !='\n') h++; 1561 | *h=0; 1562 | if (scaninbuff && buffpos) { 1563 | buffer[buffpos]=0; 1564 | printf("%s\n", buffer); 1565 | } 1566 | fprintf(stderr, "%s\n", c+2); /* XXX */ 1567 | exit(0); 1568 | break; 1569 | case V('d','i'): 1570 | { 1571 | STRDEF *de; 1572 | c=c+j; 1573 | i=V(c[0],c[1]); 1574 | if (*c == '\n') { c++;break; } 1575 | while (*c && *c!='\n') c++; 1576 | c++; 1577 | h=c; 1578 | while (*c && strncmp(c,".di",3)) while (*c && *c++!='\n'); 1579 | *c=0; 1580 | de=strdef; 1581 | while (de && de->nr !=i) de=de->next; 1582 | if (!de) { 1583 | de=(STRDEF*) xmalloc(sizeof(STRDEF)); 1584 | de->nr=i; 1585 | de->slen=0; 1586 | de->next=strdef; 1587 | de->st=NULL; 1588 | strdef=de; 1589 | } else { 1590 | if (de->st) free(de->st); 1591 | de->slen=0; 1592 | de->st=NULL; 1593 | } 1594 | scan_troff(h,0,&de->st); 1595 | *c='.'; 1596 | while (*c && *c++!='\n'); 1597 | break; 1598 | } 1599 | case V('d','s'): 1600 | mode=1; 1601 | case V('a','s'): 1602 | { 1603 | STRDEF *de; 1604 | int oldcurpos=curpos; 1605 | c=c+j; 1606 | while (*c == ' ') c++; 1607 | i=V(c[0],c[1]); 1608 | j=0; 1609 | while (c[j] && c[j]!='\n') j++; 1610 | if (j<3) { c=c+j; break; } 1611 | if (c[1] == ' ') c=c+1; else c=c+2; 1612 | while (isspace(*c)) c++; 1613 | if (*c == '"') c++; 1614 | de=strdef; 1615 | while (de && de->nr != i) de=de->next; 1616 | single_escape=1; 1617 | curpos=0; 1618 | if (!de) { 1619 | char *h; 1620 | de=(STRDEF*) xmalloc(sizeof(STRDEF)); 1621 | de->nr=i; 1622 | de->slen=0; 1623 | de->next=strdef; 1624 | de->st=NULL; 1625 | strdef=de; 1626 | h=NULL; 1627 | c=scan_troff(c, 1, &h); 1628 | de->st=h; 1629 | de->slen=curpos; 1630 | } else { 1631 | if (mode) { /* .ds */ 1632 | char *h=NULL; 1633 | c=scan_troff(c, 1, &h); 1634 | free(de->st); /* segfault XXX */ 1635 | de->slen=curpos; 1636 | de->st=h; 1637 | } else { /* .as */ 1638 | c=scan_troff(c,1,&de->st); /* XXX */ 1639 | de->slen+=curpos; 1640 | } 1641 | } 1642 | single_escape=0; 1643 | curpos=oldcurpos; 1644 | } 1645 | break; 1646 | case V('b','r'): 1647 | if (still_dd) out_html("
"); 1648 | else out_html("
\n"); 1649 | curpos=0; 1650 | c=c+j; 1651 | if (c[0] == escapesym) { c=scan_escape(c+1); } 1652 | c=skip_till_newline(c);break; 1653 | case V('c','2'): 1654 | c=c+j; 1655 | if (*c!='\n') { nobreaksym=*c; } 1656 | else nobreaksym='\''; 1657 | c=skip_till_newline(c); 1658 | break; 1659 | case V('c','c'): 1660 | c=c+j; 1661 | if (*c!='\n') { controlsym=*c; } 1662 | else controlsym='.'; 1663 | c=skip_till_newline(c); 1664 | break; 1665 | case V('c','e'): 1666 | c=c+j; 1667 | if (*c == '\n') { i=1; } 1668 | else { 1669 | i=0; 1670 | while ('0'<=*c && *c<='9') { 1671 | i=i*10+*c-'0'; 1672 | c++; 1673 | } 1674 | } 1675 | c=skip_till_newline(c); 1676 | /* center next i lines */ 1677 | if (i>0) { 1678 | out_html("
\n"); 1679 | while (i && *c) { 1680 | char *line=NULL; 1681 | c=scan_troff(c,1, &line); 1682 | if (line && strncmp(line, "
", 4)) { 1683 | out_html(line); 1684 | out_html("
\n"); 1685 | i--; 1686 | } 1687 | } 1688 | out_html("
\n"); 1689 | curpos=0; 1690 | } 1691 | break; 1692 | case V('e','c'): 1693 | c=c+j; 1694 | if (*c!='\n') { escapesym=*c; } 1695 | else escapesym='\\'; 1696 | break; 1697 | c=skip_till_newline(c); 1698 | case V('e','o'): 1699 | escapesym=0; 1700 | c=skip_till_newline(c); 1701 | break; 1702 | case V('e','x'): 1703 | exit(0); 1704 | break; 1705 | case V('f','c'): 1706 | c=c+j; 1707 | if (*c == '\n') { 1708 | fieldsym=padsym=0; 1709 | } else { 1710 | fieldsym=c[0]; 1711 | padsym=c[1]; 1712 | } 1713 | c=skip_till_newline(c); 1714 | break; 1715 | case V('f','i'): 1716 | if (!fillout) { 1717 | out_html(change_to_font(0)); 1718 | out_html(change_to_size('0')); 1719 | out_html("
\n"); 1720 | } 1721 | curpos=0; 1722 | fillout=1; 1723 | c=skip_till_newline(c); 1724 | break; 1725 | case V('f','t'): 1726 | c=c+j; 1727 | if (*c == '\n') { 1728 | out_html(change_to_font(0)); 1729 | } else { 1730 | if (*c == escapesym) { 1731 | int fn; 1732 | c=scan_expression(c, &fn); 1733 | c--; 1734 | out_html(change_to_font(fn)); 1735 | } else { 1736 | out_html(change_to_font(*c)); 1737 | c++; 1738 | } 1739 | } 1740 | c=skip_till_newline(c); 1741 | break; 1742 | case V('e','l'): 1743 | /* .el anything : else part of if else */ 1744 | if (ifelseval) { 1745 | c=c+j; 1746 | c[-1]='\n'; 1747 | c=scan_troff(c,1,NULL); 1748 | } else 1749 | c=skip_till_newline(c+j); 1750 | break; 1751 | case V('i','e'): 1752 | /* .ie c anything : then part of if else */ 1753 | case V('i','f'): 1754 | /* .if c anything 1755 | * .if !c anything 1756 | * .if N anything 1757 | * .if !N anything 1758 | * .if 'string1'string2' anything 1759 | * .if !'string1'string2' anything 1760 | */ 1761 | c=c+j; 1762 | c=scan_expression(c, &i); 1763 | ifelseval=!i; 1764 | if (i) { 1765 | *c='\n'; 1766 | c++; 1767 | c=scan_troff(c,1,NULL); 1768 | } else 1769 | c=skip_till_newline(c); 1770 | break; 1771 | case V('i','g'): /* .ig: ignore until .. */ 1772 | { 1773 | char *endwith="..\n"; 1774 | i=3; 1775 | c=c+j; 1776 | while (*c == ' ') c++; 1777 | if (*c == escapesym && c[1] == '"') 1778 | while (*c != '\n') c++; 1779 | if (*c!='\n') { /* .ig yy: ignore until .yy, then call .yy */ 1780 | endwith=c-1;i=1; 1781 | c[-1]='.'; 1782 | while (*c && *c!='\n') c++,i++; 1783 | } 1784 | c++; 1785 | while (*c && strncmp(c,endwith,i)) 1786 | while (*c && *c++!='\n'); 1787 | while (*c && *c++!='\n'); 1788 | break; 1789 | } 1790 | case V('n','f'): 1791 | if (fillout) { 1792 | out_html(change_to_font(0)); 1793 | out_html(change_to_size('0')); 1794 | out_html("
\n");
1795 | 	    }
1796 | 	    curpos=0;
1797 | 	    fillout=0;
1798 | 	    c=skip_till_newline(c);
1799 | 	    break;
1800 | 	case V('p','s'):
1801 | 	    c=c+j;
1802 | 	    if (*c == '\n') {
1803 | 		out_html(change_to_size('0'));
1804 | 	    } else {
1805 | 		j=0;i=0;
1806 | 		if (*c == '-') { j= -1;c++; } else if (*c == '+') { j=1;c++;}
1807 | 		c=scan_expression(c, &i);
1808 | 		if (!j) { j=1; if (i>5) i=i-10; }
1809 | 		out_html(change_to_size(i*j));
1810 | 	    }
1811 | 	    c=skip_till_newline(c);
1812 | 	    break;
1813 | 	case V('s','p'):
1814 | 	    c=c+j;
1815 | 	    if (fillout) out_html("

"); else { 1816 | out_html(NEWLINE); 1817 | NEWLINE[0]='\n'; 1818 | } 1819 | curpos=0; 1820 | c=skip_till_newline(c); 1821 | break; 1822 | case V('s','o'): 1823 | { 1824 | FILE *f; 1825 | struct stat stbuf; 1826 | int l; char *buf; 1827 | char *name = NULL; 1828 | 1829 | curpos=0; 1830 | c += j; /* skip .so part and whitespace */ 1831 | if (*c == '/') { 1832 | h = c; 1833 | } else { /* .so man3/cpow.3 -> ../man3/cpow.3 */ 1834 | h = c-3; 1835 | h[0] = '.'; 1836 | h[1] = '.'; 1837 | h[2] = '/'; 1838 | } 1839 | while (*c != '\n') c++; 1840 | while (c[-1] == ' ') c--; 1841 | while (*c != '\n') *c++ = 0; 1842 | *c = 0; 1843 | scan_troff(h,1, &name); 1844 | if (name[3] == '/') h=name+3; else h=name; 1845 | l = 0; 1846 | if (stat(h, &stbuf)!=-1) l=stbuf.st_size; 1847 | buf = (char*) xmalloc((l+4)*sizeof(char)); 1848 | #if NOCGI 1849 | if (!out_length) { 1850 | char *t,*s; 1851 | t=strrchr(fname, '/'); 1852 | if (!t) t=fname; 1853 | fprintf(stderr, "ln -s %s.html %s.html\n", h, t); 1854 | s=strrchr(t, '.');if (!s) s=t; 1855 | printf(" Manpage of %s\n" 1856 | "\n" 1857 | "See the manpage for %s.\n" 1858 | "\n", 1859 | s, h, h); 1860 | } else 1861 | #endif 1862 | { 1863 | /* this works alright, except for section 3 */ 1864 | if (!l || !(f = fopen(h,"r"))) { 1865 | fprintf(stderr, 1866 | "man2html: unable to open or read file %s\n", h); 1867 | out_html("

" 1868 | "man2html: unable to open or read file\n"); 1869 | out_html(h); 1870 | out_html("
\n"); 1871 | } else { 1872 | i=fread(buf+1,1,l,f); 1873 | fclose(f); 1874 | buf[0]=buf[l]='\n'; 1875 | buf[l+1]=buf[l+2]=0; 1876 | scan_troff(buf+1,0,NULL); 1877 | } 1878 | if (buf) free(buf); 1879 | } 1880 | *c++='\n'; 1881 | break; 1882 | } 1883 | case V('t','a'): 1884 | c=c+j; 1885 | j=0; 1886 | while (*c!='\n') { 1887 | sl=scan_expression(c, &tabstops[j]); 1888 | if (*c == '-' || *c == '+') tabstops[j]+=tabstops[j-1]; 1889 | c=sl; 1890 | while (*c == ' ' || *c == '\t') c++; 1891 | if (j+1 < SIZE(tabstops)) 1892 | j++; 1893 | } 1894 | maxtstop=j; 1895 | curpos=0; 1896 | break; 1897 | case V('t','i'): 1898 | #if 0 1899 | dl_down(); 1900 | #endif 1901 | out_html("
\n"); 1902 | c=c+j; 1903 | c=scan_expression(c, &j); 1904 | for (i=0; ia b ] */ 1932 | mode=1; 1933 | c[0]='B'; c[1]='I'; 1934 | out_html(change_to_font('R')); 1935 | out_html("["); 1936 | curpos++; 1937 | case V('B','R'): 1938 | case V('B','I'): 1939 | case V('I','B'): 1940 | case V('I','R'): 1941 | case V('R','B'): 1942 | case V('R','I'): 1943 | { 1944 | char font[2]; 1945 | font[0] = c[0]; font[1] = c[1]; 1946 | c = c+j; 1947 | if (*c == '\n') c++; 1948 | sl = fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); 1949 | c = sl+1; 1950 | /* .BR name (section) 1951 | ** indicates a link. It will be added in the output routine. 1952 | */ 1953 | for (i=0; i"); 1977 | curpos = 0; 1978 | break; 1979 | case V('T','P'): 1980 | dl_begin(); 1981 | c=skip_till_newline(c); 1982 | /* somewhere a definition ends with '.TP' */ 1983 | if (!*c) still_dd=1; else { 1984 | c=scan_troff(c,1,NULL); 1985 | out_html("
"); 1986 | } 1987 | curpos=0; 1988 | break; 1989 | case V('I','X'): 1990 | /* general index */ 1991 | sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); 1992 | c = sl+1; 1993 | j = 4; 1994 | while (idxlabel[j] == 'Z') idxlabel[j--]='A'; 1995 | idxlabel[j]++; 1996 | #ifdef MAKEINDEX 1997 | if (idxfile) { 1998 | fprintf(idxfile, "%s@%s@", fname, idxlabel); 1999 | for (j=0; j' and '<' solves it, but creates 2012 | ** some space. A normal space does not work. 2013 | */ 2014 | out_html("\">"); 2015 | break; 2016 | case V('L','P'): 2017 | case V('P','P'): 2018 | dl_end(); 2019 | if (fillout) out_html("

\n"); else { 2020 | out_html(NEWLINE); 2021 | NEWLINE[0]='\n'; 2022 | } 2023 | curpos=0; 2024 | c=skip_till_newline(c); 2025 | break; 2026 | case V('H','P'): 2027 | dl_begin(); 2028 | still_dd=1; 2029 | c=skip_till_newline(c); 2030 | curpos=0; 2031 | break; 2032 | case V('P','D'): 2033 | c=skip_till_newline(c); 2034 | break; 2035 | case V('R','s'): /* BSD mandoc */ 2036 | case V('R','S'): 2037 | sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); 2038 | j = 1; 2039 | if (words>0) scan_expression(wordlist[0], &j); 2040 | if (j>=0) { 2041 | dl_newlevel(); 2042 | c=skip_till_newline(c); 2043 | curpos=0; 2044 | break; 2045 | } 2046 | case V('R','e'): /* BSD mandoc */ 2047 | case V('R','E'): 2048 | dl_endlevel(); 2049 | c=skip_till_newline(c); 2050 | curpos=0; 2051 | break; 2052 | case V('S','B'): 2053 | out_html(change_to_size(-1)); 2054 | out_html(change_to_font('B')); 2055 | c=scan_troff(c+j, 1, NULL); 2056 | out_html(change_to_font('R')); 2057 | out_html(change_to_size('0')); 2058 | break; 2059 | case V('S','M'): 2060 | c=c+j; 2061 | if (*c == '\n') c++; 2062 | out_html(change_to_size(-1)); 2063 | trans_char(c,'"','\a'); 2064 | c=scan_troff(c,1,NULL); 2065 | out_html(change_to_size('0')); 2066 | break; 2067 | case V('S','s'): /* BSD mandoc */ 2068 | mandoc_command = 1; 2069 | case V('S','S'): 2070 | mode=1; 2071 | goto sh_below; 2072 | case V('S','h'): /* BSD mandoc */ 2073 | mandoc_command = 1; 2074 | case V('S','H'): 2075 | sh_below: 2076 | c=c+j; 2077 | if (*c == '\n') c++; 2078 | dl_down(); 2079 | out_html(change_to_font(0)); 2080 | out_html(change_to_size(0)); 2081 | if (!fillout) { 2082 | fillout=1; 2083 | out_html("

"); 2084 | } 2085 | trans_char(c,'"', '\a'); 2086 | add_to_index(mode, c); 2087 | out_html(" \n

"); 2091 | else out_html("\"> \n

"); 2092 | mandoc_synopsis = (strncmp(c, "SYNOPSIS", 8) == 0); 2093 | c = (mandoc_command ? scan_troff_mandoc : scan_troff)(c,1,NULL); 2094 | if (mode) out_html("

\n"); 2095 | else out_html("\n"); 2096 | curpos=0; 2097 | break; 2098 | case V('T','S'): 2099 | c=scan_table(c); 2100 | break; 2101 | case V('D','t'): /* BSD mandoc */ 2102 | mandoc_command = 1; 2103 | case V('T','H'): 2104 | if (!output_possible) { 2105 | sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, 0); 2106 | *sl = 0; 2107 | if (words > 1) { 2108 | output_possible=1; 2109 | out_html("Manpage of "); 2110 | out_html(wordlist[0]); 2111 | out_html("\n"); 2112 | out_html("\n"); 2113 | out_html("\n

"); 2114 | out_html(wordlist[0]); 2115 | out_html("

\nSection: "); 2116 | if (words>4) 2117 | out_html(wordlist[4]); 2118 | else 2119 | out_html(section_name(wordlist[1])); 2120 | out_html(" ("); 2121 | out_html(wordlist[1]); 2122 | if (words>2) { 2123 | out_html(")
Updated: "); 2124 | scan_troff(wordlist[2], 1, NULL); 2125 | } else out_html(")"); 2126 | out_html("
Index\n"); 2127 | man_page_html(0,0); /* Return to Main Contents */ 2128 | *sl='\n'; 2129 | out_html("
\n"); 2130 | if (mandoc_command) out_html("
BSD mandoc
"); 2131 | } 2132 | c = sl+1; 2133 | } else 2134 | c = skip_till_newline(c); 2135 | curpos=0; 2136 | break; 2137 | case V('T','X'): 2138 | sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); 2139 | *sl=0; 2140 | out_html(change_to_font('I')); 2141 | if (words>1) wordlist[1][-1]=0; 2142 | c=lookup_abbrev(wordlist[0]); 2143 | curpos+=strlen(c); 2144 | out_html(c); 2145 | out_html(change_to_font('R')); 2146 | if (words>1) 2147 | out_html(wordlist[1]); 2148 | *sl='\n'; 2149 | c=sl+1; 2150 | break; 2151 | case V('r','m'): 2152 | /* .rm xx : Remove request, macro or string */ 2153 | case V('r','n'): 2154 | /* .rn xx yy : Rename request, macro or string xx to yy */ 2155 | { 2156 | STRDEF *de; 2157 | c=c+j; 2158 | i=V(c[0],c[1]); 2159 | c=c+2; 2160 | while (isspace(*c) && *c!='\n') c++; 2161 | j=V(c[0],c[1]); 2162 | while (*c && *c!='\n') c++; 2163 | c++; 2164 | de=strdef; 2165 | while (de && de->nr!=j) de=de->next; 2166 | if (de) { 2167 | if (de->st) free(de->st); 2168 | de->nr=0; 2169 | } 2170 | de=strdef; 2171 | while (de && de->nr!=i) de=de->next; 2172 | if (de) de->nr=j; 2173 | break; 2174 | } 2175 | case V('n','x'): 2176 | /* .nx filename : next file. */ 2177 | case V('i','n'): 2178 | /* .in +-N : Indent */ 2179 | c=skip_till_newline(c); 2180 | break; 2181 | case V('n','r'): 2182 | /* .nr R +-N M: define and set number register R by +-N; 2183 | ** auto-increment by M 2184 | */ 2185 | { 2186 | INTDEF *intd; 2187 | c=c+j; 2188 | i=V(c[0],c[1]); 2189 | c=c+2; 2190 | intd=intdef; 2191 | while (intd && intd->nr!=i) intd=intd->next; 2192 | if (!intd) { 2193 | intd = (INTDEF*) xmalloc(sizeof(INTDEF)); 2194 | intd->nr=i; 2195 | intd->val=0; 2196 | intd->incr=0; 2197 | intd->next=intdef; 2198 | intdef=intd; 2199 | } 2200 | while (*c == ' ' || *c == '\t') c++; 2201 | c=scan_expression(c,&intd->val); 2202 | if (*c!='\n') { 2203 | while (*c == ' ' || *c == '\t') c++; 2204 | c=scan_expression(c,&intd->incr); 2205 | } 2206 | c=skip_till_newline(c); 2207 | break; 2208 | } 2209 | case V('a','m'): 2210 | /* .am xx yy : append to a macro. */ 2211 | /* define or handle as .ig yy */ 2212 | mode=1; 2213 | case V('d','e'): 2214 | /* .de xx yy : define or redefine macro xx; end at .yy (..) */ 2215 | /* define or handle as .ig yy */ 2216 | { 2217 | STRDEF *de; 2218 | int olen=0; 2219 | c=c+j; 2220 | sl=fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); 2221 | i=V(c[0],c[1]);j=2; 2222 | if (words == 1) wordlist[1]=".."; else { 2223 | wordlist[1]--; 2224 | wordlist[1][0]='.'; 2225 | j=3; 2226 | } 2227 | c=sl+1; 2228 | sl=c; 2229 | while (*c && strncmp(c,wordlist[1],j)) c=skip_till_newline(c); 2230 | de=defdef; 2231 | while (de && de->nr!= i) de=de->next; 2232 | if (mode && de) olen=strlen(de->st); 2233 | j=olen+c-sl; 2234 | h= (char*) xmalloc((j*2+4)*sizeof(char)); 2235 | if (h) { 2236 | for (j=0; jst[j]; 2238 | if (!j || h[j-1]!='\n') 2239 | h[j++]='\n'; 2240 | while (sl!=c) { 2241 | if (sl[0] == '\\' && sl[1] == '\\') { 2242 | h[j++]='\\'; sl++; 2243 | } else 2244 | h[j++]=*sl; 2245 | sl++; 2246 | } 2247 | h[j]=0; 2248 | if (de) { 2249 | if (de->st) free(de->st); 2250 | de->st=h; 2251 | } else { 2252 | de = (STRDEF*) xmalloc(sizeof(STRDEF)); 2253 | de->nr=i; 2254 | de->next=defdef; 2255 | de->st=h; 2256 | defdef=de; 2257 | } 2258 | } 2259 | } 2260 | c=skip_till_newline(c); 2261 | break; 2262 | 2263 | /* ----- BSD mandoc stuff below ----- */ 2264 | case V('U','x'): /* BSD mandoc */ 2265 | c=c+j; 2266 | out_html("UNIX"); 2267 | c=skip_till_newline(c); 2268 | break; 2269 | case V('A','t'): /* BSD mandoc - called with arg V */ 2270 | c=c+j; 2271 | out_html("AT&T System"); 2272 | break; 2273 | case V('B','l'): /* BSD mandoc */ 2274 | { 2275 | char *nl, t=0 /* just for gcc */; 2276 | c=c+j; 2277 | nl = strchr(c,'\n'); 2278 | if (nl) { 2279 | t = *nl; 2280 | *nl = 0; 2281 | } 2282 | if (strstr(c, "-bullet")) /* HTML Unnumbered List */ 2283 | dl_newlevel_type(UL); 2284 | else if (strstr(c, "-enum")) /* HTML Ordered List */ 2285 | dl_newlevel_type(OL); 2286 | else /* HTML Descriptive List */ 2287 | dl_newlevel_type(DL); 2288 | if (nl) 2289 | *nl = t; 2290 | if (fillout) out_html("

\n"); else { 2291 | out_html(NEWLINE); 2292 | NEWLINE[0]='\n'; 2293 | } 2294 | curpos=0; 2295 | c=skip_till_newline(c); 2296 | break; 2297 | } 2298 | case V('E','l'): /* BSD mandoc */ 2299 | c=c+j; 2300 | dl_endlevel_type(); 2301 | if (fillout) out_html("

\n"); else { 2302 | out_html(NEWLINE); 2303 | NEWLINE[0]='\n'; 2304 | } 2305 | curpos=0; 2306 | c=skip_till_newline(c); 2307 | break; 2308 | case V('I','t'): /* BSD mandoc */ 2309 | c=c+j; 2310 | if (dl_type(DL)) { 2311 | out_html("

"); 2312 | out_html(change_to_font('B')); 2313 | if (*c == '\n') { 2314 | /* Don't allow embedded comms after a newline */ 2315 | c++; 2316 | c=scan_troff(c,1,NULL); 2317 | } else { 2318 | /* Do allow embedded comms on the same line. */ 2319 | c=scan_troff_mandoc(c,1,NULL); 2320 | } 2321 | out_html(change_to_font('R')); 2322 | out_html(NEWLINE); 2323 | if (inXo) 2324 | still_dd = 1; 2325 | else 2326 | out_html("
"); 2327 | } else if (dl_type(UL) || dl_type(OL)) { 2328 | out_html("
  • "); 2329 | c=scan_troff_mandoc(c,1,NULL); 2330 | out_html(NEWLINE); 2331 | } 2332 | if (fillout) curpos++; else curpos=0; 2333 | break; 2334 | case V('X','o'): /* BSD mandoc */ 2335 | c=c+j; 2336 | inXo = 1; 2337 | break; 2338 | case V('X','c'): /* BSD mandoc - Xc closes an Xo */ 2339 | c=c+j; 2340 | if (inXo) { 2341 | if (still_dd) 2342 | out_html("
    "); 2343 | inXo = 0; 2344 | } 2345 | break; 2346 | case V('S','m'): /* BSD mandoc - called with arg on/off */ 2347 | c=skip_till_newline(c); 2348 | break; 2349 | case V('B','k'): /* BSD mandoc */ 2350 | case V('E','k'): /* BSD mandoc */ 2351 | case V('D','d'): /* BSD mandoc */ 2352 | case V('O','s'): /* BSD mandoc */ 2353 | trans_char(c,'"','\a'); 2354 | c=c+j; 2355 | if (*c == '\n') c++; 2356 | c=scan_troff_mandoc(c, 1, NULL); 2357 | out_html(NEWLINE); 2358 | if (fillout) curpos++; else curpos=0; 2359 | break; 2360 | case V('B','t'): /* BSD mandoc */ 2361 | trans_char(c,'"','\a'); 2362 | c=c+j; 2363 | out_html(" is currently in beta test."); 2364 | if (fillout) curpos++; else curpos=0; 2365 | break; 2366 | case V('B','x'): /* BSD mandoc */ 2367 | trans_char(c,'"','\a'); 2368 | c=c+j; 2369 | if (*c == '\n') c++; 2370 | out_html("BSD "); 2371 | c=scan_troff_mandoc(c, 1, NULL); 2372 | if (fillout) curpos++; else curpos=0; 2373 | break; 2374 | case V('D','l'): /* BSD mandoc */ 2375 | c=c+j; 2376 | out_html(NEWLINE); 2377 | out_html("
    "); 2378 | out_html(change_to_font('L')); 2379 | if (*c == '\n') c++; 2380 | c=scan_troff_mandoc(c, 1, NULL); 2381 | out_html(change_to_font('R')); 2382 | out_html("
    "); 2383 | if (fillout) curpos++; else curpos=0; 2384 | break; 2385 | case V('B','d'): /* BSD mandoc */ 2386 | { /* Seems like a kind of example/literal mode */ 2387 | char *nl, t=0 /* just for gcc */; 2388 | c=c+j; 2389 | nl = strchr(c,'\n'); 2390 | if (nl) { 2391 | t = *nl; 2392 | *nl = 0; 2393 | } 2394 | out_html(NEWLINE); 2395 | mandoc_bd_options = 0; /* Remember options for terminating Bl */ 2396 | if (strstr(c, "-offset indent")) { 2397 | mandoc_bd_options |= BD_INDENT; 2398 | out_html("
    \n"); 2399 | } 2400 | if (strstr(c, "-literal") || strstr(c, "-unfilled")) { 2401 | if (fillout) { 2402 | mandoc_bd_options |= BD_LITERAL; 2403 | out_html(change_to_font(0)); 2404 | out_html(change_to_size('0')); 2405 | out_html("
    \n");
    2406 | 		  }
    2407 | 		  curpos=0;
    2408 | 		  fillout=0;
    2409 | 	     }
    2410 | 	     if (nl)
    2411 | 		  *nl = t;
    2412 | 	     c=skip_till_newline(c);
    2413 | 	     break;
    2414 | 	}
    2415 | 	case V('E','d'):	/* BSD mandoc */
    2416 | 	     if (mandoc_bd_options & BD_LITERAL) {
    2417 | 		  if (!fillout) {
    2418 | 		       out_html(change_to_font(0));
    2419 | 		       out_html(change_to_size('0'));
    2420 | 		       out_html("
    \n"); 2421 | } 2422 | } 2423 | if (mandoc_bd_options & BD_INDENT) 2424 | out_html("
    \n"); 2425 | curpos=0; 2426 | fillout=1; 2427 | c=skip_till_newline(c); 2428 | break; 2429 | case V('B','e'): /* BSD mandoc */ 2430 | c=c+j; 2431 | if (fillout) out_html("

    "); else { 2432 | out_html(NEWLINE); 2433 | NEWLINE[0]='\n'; 2434 | } 2435 | curpos=0; 2436 | c=skip_till_newline(c); 2437 | break; 2438 | case V('X','r'): /* BSD mandoc */ 2439 | { 2440 | /* Translate xyz 1 to xyz(1) 2441 | * Allow for multiple spaces. Allow the section to be missing. 2442 | */ 2443 | char buff[100]; 2444 | char *bufptr; 2445 | trans_char(c,'"','\a'); 2446 | bufptr = buff; 2447 | c = c+j; 2448 | if (*c == '\n') c++; /* Skip spaces */ 2449 | while (isspace(*c) && *c != '\n') c++; 2450 | while (isalnum(*c) && bufptr < buff + SIZE(buff)-4) { 2451 | /* Copy the xyz part */ 2452 | *bufptr++ = *c++; 2453 | } 2454 | while (isspace(*c) && *c != '\n') c++; /* Skip spaces */ 2455 | if (isdigit(*c)) { /* Convert the number if there is one */ 2456 | *bufptr++ = '('; 2457 | while (isalnum(*c) && bufptr < buff + SIZE(buff)-3) { 2458 | *bufptr++ = *c++; 2459 | } 2460 | *bufptr++ = ')'; 2461 | } 2462 | while (*c != '\n' && bufptr < buff + SIZE(buff)-2) { 2463 | /* Copy the remainder */ 2464 | if (!isspace(*c)) { 2465 | *bufptr++ = *c; 2466 | } 2467 | c++; 2468 | } 2469 | *bufptr++ = '\n'; 2470 | *bufptr = 0; 2471 | scan_troff_mandoc(buff, 1, NULL); 2472 | out_html(NEWLINE); 2473 | if (fillout) curpos++; else curpos=0; 2474 | } 2475 | break; 2476 | case V('F','l'): /* BSD mandoc */ 2477 | trans_char(c,'"','\a'); 2478 | c=c+j; 2479 | out_html("-"); 2480 | if (*c!='\n') { 2481 | out_html(change_to_font('B')); 2482 | c=scan_troff_mandoc(c, 1, NULL); 2483 | out_html(change_to_font('R')); 2484 | } 2485 | out_html(NEWLINE); 2486 | if (fillout) curpos++; else curpos=0; 2487 | break; 2488 | case V('P','a'): /* BSD mandoc */ 2489 | case V('P','f'): /* BSD mandoc */ 2490 | trans_char(c,'"','\a'); 2491 | c=c+j; 2492 | if (*c == '\n') c++; 2493 | c=scan_troff_mandoc(c, 1, NULL); 2494 | out_html(NEWLINE); 2495 | if (fillout) curpos++; else curpos=0; 2496 | break; 2497 | case V('P','p'): /* BSD mandoc */ 2498 | if (fillout) out_html("

    \n"); else { 2499 | out_html(NEWLINE); 2500 | NEWLINE[0]='\n'; 2501 | } 2502 | curpos=0; 2503 | c=skip_till_newline(c); 2504 | break; 2505 | case V('D','q'): /* BSD mandoc */ 2506 | trans_char(c,'"','\a'); 2507 | c=c+j; 2508 | if (*c == '\n') c++; 2509 | out_html("``"); 2510 | c=scan_troff_mandoc(c, 1, NULL); 2511 | out_html("''"); 2512 | out_html(NEWLINE); 2513 | if (fillout) curpos++; else curpos=0; 2514 | break; 2515 | case V('O','p'): /* BSD mandoc */ 2516 | trans_char(c,'"','\a'); 2517 | c=c+j; 2518 | if (*c == '\n') c++; 2519 | out_html(change_to_font('R')); 2520 | out_html("["); 2521 | c=scan_troff_mandoc(c, 1, NULL); 2522 | out_html(change_to_font('R')); 2523 | out_html("]"); 2524 | out_html(NEWLINE); 2525 | if (fillout) curpos++; else curpos=0; 2526 | break; 2527 | case V('O','o'): /* BSD mandoc */ 2528 | trans_char(c,'"','\a'); 2529 | c=c+j; 2530 | if (*c == '\n') c++; 2531 | out_html(change_to_font('R')); 2532 | out_html("["); 2533 | c=scan_troff_mandoc(c, 1, NULL); 2534 | if (fillout) curpos++; else curpos=0; 2535 | break; 2536 | case V('O','c'): /* BSD mandoc */ 2537 | trans_char(c,'"','\a'); 2538 | c=c+j; 2539 | c=scan_troff_mandoc(c, 1, NULL); 2540 | out_html(change_to_font('R')); 2541 | out_html("]"); 2542 | if (fillout) curpos++; else curpos=0; 2543 | break; 2544 | case V('P','q'): /* BSD mandoc */ 2545 | trans_char(c,'"','\a'); 2546 | c=c+j; 2547 | if (*c == '\n') c++; 2548 | out_html("("); 2549 | c=scan_troff_mandoc(c, 1, NULL); 2550 | out_html(")"); 2551 | out_html(NEWLINE); 2552 | if (fillout) curpos++; else curpos=0; 2553 | break; 2554 | case V('Q','l'): /* BSD mandoc */ 2555 | { /* Single quote first word in the line */ 2556 | char *sp; 2557 | trans_char(c,'"','\a'); 2558 | c=c+j; 2559 | if (*c == '\n') c++; 2560 | sp = c; 2561 | do { /* Find first whitespace after the 2562 | * first word that isn't a mandoc macro 2563 | */ 2564 | while (*sp && isspace(*sp)) sp++; 2565 | while (*sp && !isspace(*sp)) sp++; 2566 | } while (*sp && isupper(*(sp-2)) && islower(*(sp-1))); 2567 | 2568 | /* Use a newline to mark the end of text to 2569 | * be quoted 2570 | */ 2571 | if (*sp) *sp = '\n'; 2572 | out_html("`"); /* Quote the text */ 2573 | c=scan_troff_mandoc(c, 1, NULL); 2574 | out_html("'"); 2575 | out_html(NEWLINE); 2576 | if (fillout) curpos++; else curpos=0; 2577 | break; 2578 | } 2579 | case V('S','q'): /* BSD mandoc */ 2580 | trans_char(c,'"','\a'); 2581 | c=c+j; 2582 | if (*c == '\n') c++; 2583 | out_html("`"); 2584 | c=scan_troff_mandoc(c, 1, NULL); 2585 | out_html("'"); 2586 | out_html(NEWLINE); 2587 | if (fillout) curpos++; else curpos=0; 2588 | break; 2589 | case V('A','r'): /* BSD mandoc */ 2590 | /* parse one line in italics */ 2591 | out_html(change_to_font('I')); 2592 | trans_char(c,'"','\a'); 2593 | c=c+j; 2594 | if (*c == '\n') { /* An empty Ar means "file ..." */ 2595 | out_html("file ..."); 2596 | } else { 2597 | c=scan_troff_mandoc(c, 1, NULL); 2598 | } 2599 | out_html(change_to_font('R')); 2600 | out_html(NEWLINE); 2601 | if (fillout) curpos++; else curpos=0; 2602 | break; 2603 | case V('A','d'): /* BSD mandoc */ 2604 | case V('E','m'): /* BSD mandoc */ 2605 | case V('V','a'): /* BSD mandoc */ 2606 | /* parse one line in italics */ 2607 | out_html(change_to_font('I')); 2608 | trans_char(c,'"','\a'); 2609 | c=c+j; 2610 | if (*c == '\n') c++; 2611 | c=scan_troff_mandoc(c, 1, NULL); 2612 | out_html(change_to_font('R')); 2613 | out_html(NEWLINE); 2614 | if (fillout) curpos++; else curpos=0; 2615 | break; 2616 | case V('N','d'): /* BSD mandoc */ 2617 | trans_char(c,'"','\a'); 2618 | c=c+j; 2619 | if (*c == '\n') c++; 2620 | out_html(" - "); 2621 | c=scan_troff_mandoc(c, 1, NULL); 2622 | out_html(NEWLINE); 2623 | if (fillout) curpos++; else curpos=0; 2624 | break; 2625 | case V('N','m'): /* BSD mandoc */ 2626 | { 2627 | static char *mandoc_name = 0; 2628 | trans_char(c,'"','\a'); 2629 | c=c+j; 2630 | if (mandoc_synopsis) { 2631 | /* 2632 | * Break lines only in the Synopsis. 2633 | * The Synopsis section seems to be treated 2634 | * as a special case - Bummer! 2635 | */ 2636 | static int count = 0; /* Don't break on the first Nm */ 2637 | if (count) { 2638 | out_html("
    "); 2639 | } else { 2640 | char *end, t=0 /* just for gcc */; 2641 | end = strchr(c, '\n'); 2642 | if (end) { 2643 | t = *end; 2644 | *end = 0; 2645 | } 2646 | if (mandoc_name) 2647 | free(mandoc_name); 2648 | mandoc_name = xstrdup(c); 2649 | if (end) 2650 | *end = t; 2651 | } 2652 | count++; 2653 | } 2654 | out_html(change_to_font('B')); 2655 | while (*c == ' ' || *c == '\t') c++; 2656 | if (*c == '\n') { 2657 | /* 2658 | * If Nm has no argument, use one from an earlier 2659 | * Nm command that did have one. Hope there aren't 2660 | * too many commands that do this. 2661 | */ 2662 | if (mandoc_name) 2663 | out_html(mandoc_name); 2664 | } else { 2665 | c=scan_troff_mandoc(c, 1, NULL); 2666 | } 2667 | out_html(change_to_font('R')); 2668 | out_html(NEWLINE); 2669 | if (fillout) curpos++; else curpos=0; 2670 | break; 2671 | } 2672 | case V('C','d'): /* BSD mandoc */ 2673 | case V('C','m'): /* BSD mandoc */ 2674 | case V('I','c'): /* BSD mandoc */ 2675 | case V('M','s'): /* BSD mandoc */ 2676 | case V('O','r'): /* BSD mandoc */ 2677 | case V('S','y'): /* BSD mandoc */ 2678 | /* parse one line in bold */ 2679 | out_html(change_to_font('B')); 2680 | trans_char(c,'"','\a'); 2681 | c=c+j; 2682 | if (*c == '\n') c++; 2683 | c=scan_troff_mandoc(c, 1, NULL); 2684 | out_html(change_to_font('R')); 2685 | out_html(NEWLINE); 2686 | if (fillout) curpos++; else curpos=0; 2687 | break; 2688 | case V('D','v'): /* BSD mandoc */ 2689 | case V('E','v'): /* BSD mandoc */ 2690 | case V('F','r'): /* BSD mandoc */ 2691 | case V('L','i'): /* BSD mandoc */ 2692 | case V('N','o'): /* BSD mandoc */ 2693 | case V('N','s'): /* BSD mandoc */ 2694 | case V('T','n'): /* BSD mandoc */ 2695 | case V('n','N'): /* BSD mandoc */ 2696 | trans_char(c,'"','\a'); 2697 | c=c+j; 2698 | if (*c == '\n') c++; 2699 | out_html(change_to_font('B')); 2700 | c=scan_troff_mandoc(c, 1, NULL); 2701 | out_html(change_to_font('R')); 2702 | out_html(NEWLINE); 2703 | if (fillout) curpos++; else curpos=0; 2704 | break; 2705 | case V('%','A'): /* BSD mandoc biblio stuff */ 2706 | case V('%','D'): 2707 | case V('%','N'): 2708 | case V('%','O'): 2709 | case V('%','P'): 2710 | case V('%','Q'): 2711 | case V('%','V'): 2712 | c=c+j; 2713 | if (*c == '\n') c++; 2714 | c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ 2715 | if (fillout) curpos++; else curpos=0; 2716 | break; 2717 | case V('%','B'): 2718 | case V('%','J'): 2719 | case V('%','R'): 2720 | case V('%','T'): 2721 | c=c+j; 2722 | out_html(change_to_font('I')); 2723 | if (*c == '\n') c++; 2724 | c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ 2725 | out_html(change_to_font('R')); 2726 | if (fillout) curpos++; else curpos=0; 2727 | break; 2728 | /* ----- end of BSD mandoc stuff ----- */ 2729 | 2730 | default: 2731 | /* search macro database of self-defined macros */ 2732 | owndef = defdef; 2733 | while (owndef && owndef->nr!=i) owndef=owndef->next; 2734 | if (owndef) { 2735 | char **oldargument; 2736 | int deflen; 2737 | int onff; 2738 | sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); 2739 | c=sl+1; 2740 | *sl=0; 2741 | for (i=1; ist); 2754 | owndef->st[deflen+1]='a'; 2755 | for (i=0; (owndef->st[deflen+2+i] = owndef->st[i]); i++); 2756 | oldargument=argument; 2757 | argument=wordlist; 2758 | onff=newline_for_fun; 2759 | if (mandoc_command) 2760 | scan_troff_mandoc(owndef->st+deflen+2, 0, NULL); 2761 | else 2762 | scan_troff(owndef->st+deflen+2, 0, NULL); 2763 | newline_for_fun=onff; 2764 | argument=oldargument; 2765 | for (i=0; i"); 2858 | curpos=0; 2859 | still_dd=0; 2860 | } 2861 | switch (*h) { 2862 | case '&': 2863 | intbuff[ibp++]='&'; 2864 | intbuff[ibp++]='a'; 2865 | intbuff[ibp++]='m'; 2866 | intbuff[ibp++]='p'; 2867 | intbuff[ibp++]=';'; 2868 | curpos++; 2869 | break; 2870 | case '<': 2871 | intbuff[ibp++]='&'; 2872 | intbuff[ibp++]='l'; 2873 | intbuff[ibp++]='t'; 2874 | intbuff[ibp++]=';'; 2875 | curpos++; 2876 | break; 2877 | case '>': 2878 | intbuff[ibp++]='&'; 2879 | intbuff[ibp++]='g'; 2880 | intbuff[ibp++]='t'; 2881 | intbuff[ibp++]=';'; 2882 | curpos++; 2883 | break; 2884 | case '"': 2885 | intbuff[ibp++]='&'; 2886 | intbuff[ibp++]='q'; 2887 | intbuff[ibp++]='u'; 2888 | intbuff[ibp++]='o'; 2889 | intbuff[ibp++]='t'; 2890 | intbuff[ibp++]=';'; 2891 | curpos++; 2892 | break; 2893 | case '\n': 2894 | if (h[-1] == '\n' && fillout) { 2895 | intbuff[ibp++]='<'; 2896 | intbuff[ibp++]='P'; 2897 | intbuff[ibp++]='>'; 2898 | } 2899 | if (contained_tab && fillout) { 2900 | intbuff[ibp++]='<'; 2901 | intbuff[ibp++]='B'; 2902 | intbuff[ibp++]='R'; 2903 | intbuff[ibp++]='>'; 2904 | } 2905 | contained_tab=0; 2906 | curpos=0; 2907 | usenbsp=0; 2908 | intbuff[ibp++]='\n'; 2909 | break; 2910 | case '\t': 2911 | { 2912 | int curtab=0; 2913 | contained_tab=1; 2914 | FLUSHIBP; 2915 | /* like a typewriter, not like TeX */ 2916 | tabstops[SIZE(tabstops)-1] = curpos+1; 2917 | while (curtab < maxtstop && tabstops[curtab] <= curpos) 2918 | curtab++; 2919 | if (curtab < maxtstop) { 2920 | if (!fillout) { 2921 | while (curpos480) { FLUSHIBP; } 2924 | curpos++; 2925 | } 2926 | } else { 2927 | out_html(""); 2928 | while (curpos < tabstops[curtab]) { 2929 | out_html(" "); 2930 | curpos++; 2931 | } 2932 | out_html(""); 2933 | } 2934 | } 2935 | } 2936 | break; 2937 | default: 2938 | if (*h == ' ' && (h[-1] == '\n' || usenbsp)) { 2939 | FLUSHIBP; 2940 | if (!usenbsp && fillout) { 2941 | out_html("
    "); 2942 | curpos=0; 2943 | } 2944 | usenbsp=fillout; 2945 | if (usenbsp) out_html(" "); else intbuff[ibp++]=' '; 2946 | } else if (*h > 31 && *h < 127) { 2947 | intbuff[ibp++]=*h; 2948 | } else if (((unsigned char)(*h)) > 127) { 2949 | #ifdef NO_8BIT 2950 | intbuff[ibp++]='&'; 2951 | intbuff[ibp++]='#'; 2952 | intbuff[ibp++]='0'+((unsigned char)(*h))/100; 2953 | intbuff[ibp++]='0'+(((unsigned char)(*h))%100)/10; 2954 | intbuff[ibp++]='0'+((unsigned char)(*h))%10; 2955 | intbuff[ibp++]=';'; 2956 | #else 2957 | intbuff[ibp++]=*h; 2958 | #endif 2959 | } 2960 | curpos++; 2961 | break; 2962 | } 2963 | if (ibp>480) FLUSHIBP; 2964 | h++; 2965 | } 2966 | } 2967 | FLUSHIBP; 2968 | if (buffer) buffer[buffpos]=0; 2969 | if (san && *h) h++; 2970 | newline_for_fun=exnewline_for_fun; 2971 | if (result) { 2972 | *result = buffer; 2973 | buffer=exbuffer; 2974 | buffpos=exbuffpos; 2975 | buffmax=exbuffmax; 2976 | scaninbuff=exscaninbuff; 2977 | } 2978 | return h; 2979 | } 2980 | 2981 | static char *scan_troff_mandoc(char *c, int san, char **result) { 2982 | char *ret, *end = c; 2983 | int oldval = mandoc_line; 2984 | mandoc_line = 1; 2985 | while (*end && *end != '\n') { 2986 | end++; 2987 | } 2988 | 2989 | if (end > c + 2 2990 | && ispunct(*(end - 1)) 2991 | && isspace(*(end - 2)) && *(end - 2) != '\n') { 2992 | /* 2993 | * Don't format lonely punctuation. E.g. in "xyz ," format 2994 | * the xyz and then append the comma removing the space. 2995 | */ 2996 | *(end - 2) = '\n'; 2997 | ret = scan_troff(c, san, result); 2998 | *(end - 2) = *(end - 1); 2999 | *(end - 1) = ' '; 3000 | } else { 3001 | ret = scan_troff(c, san, result); 3002 | } 3003 | mandoc_line = oldval; 3004 | return ret; 3005 | } 3006 | 3007 | STRDEF *foundpages=NULL; 3008 | 3009 | static void 3010 | error_page(char *s, char *t, ...) { 3011 | va_list p; 3012 | 3013 | printf("%s\n" 3014 | "\n

    %s

    \n", s, s); 3015 | va_start(p, t); 3016 | vfprintf(stdout, t, p); 3017 | va_end(p); 3018 | printf("\n"); 3019 | exit(0); 3020 | } 3021 | 3022 | char * 3023 | xstrdup(const char *s) { 3024 | char *p = strdup(s); 3025 | if (p == NULL) 3026 | error_page("Out of memory", 3027 | "Sorry, out of memory, aborting...\n"); 3028 | return p; 3029 | } 3030 | 3031 | void * 3032 | xmalloc(size_t size) { 3033 | void *p = malloc(size); 3034 | if (p == NULL) 3035 | error_page("Out of memory", 3036 | "Sorry, out of memory, aborting...\n"); 3037 | return p; 3038 | } 3039 | 3040 | void * 3041 | xrealloc(void *ptr, size_t size) { 3042 | void *p = realloc(ptr,size); 3043 | if (p == NULL) 3044 | error_page("Out of memory", 3045 | "Sorry, out of memory, aborting...\n"); 3046 | return p; 3047 | } 3048 | 3049 | static void 3050 | usage(void) { 3051 | error_page("man2html: bad invocation", 3052 | "Call: man2html [-l|-h host.domain:port] [-p|-q] [filename]\n" 3053 | "or: man2html -r [filename]\n" 3054 | "or: man2html -c [filename]\n"); 3055 | } 3056 | 3057 | static void 3058 | goto_dir(char *path, char **dir, char **name) { 3059 | char *s, *t, *u; 3060 | 3061 | s = xstrdup(path); 3062 | t = strrchr(s, '/'); 3063 | if (t) { 3064 | *t = 0; 3065 | u = strrchr(s, '/'); 3066 | *t = '/'; 3067 | if (u) { 3068 | *u = 0; 3069 | if (chdir(s) == 0) { 3070 | if (dir) 3071 | *dir = s; 3072 | if (name) 3073 | *name = u+1; 3074 | } 3075 | #if 0 3076 | else /* complain or not - this need not be fatal */ 3077 | error_page("Error", "man2html: could not chdir to %s", s); 3078 | #endif 3079 | } 3080 | } 3081 | } 3082 | 3083 | /* 3084 | * Call: man2html [-l] [filename] 3085 | * 3086 | * The contents of FILENAME (or STDIN, in case FILENAME is "-" or absent) 3087 | * are converted from man-style nroff to html, and printed on STDOUT. 3088 | * 3089 | * Possible errors are reflected in the output. The return status is 0. 3090 | */ 3091 | int 3092 | main(int argc, char **argv) { 3093 | FILE *f; 3094 | struct stat stbuf; 3095 | int l, c; 3096 | char *buf, *filename, *fnam = NULL; 3097 | 3098 | #ifdef __CYGWIN__ 3099 | int opterr; 3100 | 3101 | extern int optind; 3102 | extern char *optarg; 3103 | #endif 3104 | 3105 | // printf("Content-type: text/html\n\n"); 3106 | 3107 | opterr = 0; /* no stderr error messages */ 3108 | while ((c = getopt (argc, argv, "D:E:hH:lL:M:pqrc?vVf")) != -1) { 3109 | switch(c) { 3110 | case 'D': 3111 | goto_dir(optarg, 0, 0); break; 3112 | case 'E': 3113 | error_page("Error", "%s", optarg); break; 3114 | case 'h': 3115 | set_cgibase("localhost"); break; 3116 | case 'H': 3117 | set_cgibase(optarg); break; 3118 | case 'l': 3119 | set_lynxcgibase("/home/httpd"); break; 3120 | case 'L': 3121 | set_lynxcgibase(optarg); break; 3122 | case 'M': 3123 | set_man2htmlpath(optarg); break; 3124 | case 'p': 3125 | set_separator('/'); break; 3126 | case 'q': 3127 | set_separator('?'); break; 3128 | case 'r': 3129 | set_relative_html_links(); break; 3130 | case 'c': 3131 | set_current_html_links(); break; 3132 | case 'v': 3133 | case 'V': 3134 | error_page("Version", "%s from man-%s", argv[0], version); 3135 | exit(0); 3136 | case '?': 3137 | default: 3138 | usage(); 3139 | case 'f': /* It is rumoured that some other 3140 | incarnation of man2html uses this flag; 3141 | ignore when given for compatibility. */ 3142 | /* case 'F': this will assign a format for man_page_html() */ 3143 | break; 3144 | } 3145 | } 3146 | 3147 | /* Find filename */ 3148 | if (argc == optind+1) 3149 | fnam = argv[optind]; 3150 | else if (argc != optind) 3151 | usage(); 3152 | 3153 | filename = fnam; 3154 | directory = 0; 3155 | 3156 | /* Open input file */ 3157 | if (!fnam || !strcmp(fnam, "-")) { 3158 | f = stdin; 3159 | fname = "(stdin)"; 3160 | } else { 3161 | /* do a chdir() first, to get .so expansion right */ 3162 | goto_dir(fnam, &directory, &fnam); 3163 | 3164 | f = fopen(fnam, "r"); 3165 | if (f == NULL) 3166 | error_page("File not found", "Could not open %s\n", filename); 3167 | fname = fnam; 3168 | } 3169 | 3170 | /* Read entire file into buf[1..l] */ 3171 | #define XTRA 5 3172 | /* buf has 1 extra byte at the start, and XTRA extra bytes at the end */ 3173 | if (f == stdin) { 3174 | int sz = 1024; 3175 | int ct = 1, tot = 0; 3176 | char *p = NULL; 3177 | 3178 | clearerr(stdin); 3179 | while (ct > 0) { 3180 | tot += ct; 3181 | if (feof(stdin)) 3182 | break; 3183 | sz = 2*sz+tot; 3184 | p = xrealloc(p, sz); 3185 | ct = fread(p+tot,1,sz-tot-XTRA,stdin); 3186 | } 3187 | 3188 | buf = p; 3189 | l = tot-1; 3190 | } else { 3191 | int ct; 3192 | 3193 | l = 0; 3194 | if (fstat(fileno(f), &stbuf) != -1) 3195 | l = stbuf.st_size; 3196 | buf = (char *) xmalloc((l+1+XTRA)*sizeof(char)); 3197 | ct = fread(buf+1,1,l,f); 3198 | if (ct < l) 3199 | l = ct; 3200 | fclose(f); 3201 | } 3202 | 3203 | buf[0] = '\n'; 3204 | buf[l+1] = '\n'; 3205 | buf[l+2] = buf[l+3] = 0; 3206 | 3207 | #ifdef MAKEINDEX 3208 | idxfile = fopen(INDEXFILE, "a"); 3209 | #endif 3210 | stdinit(); 3211 | 3212 | scan_troff(buf+1,0,NULL); 3213 | dl_down(); 3214 | out_html(change_to_font(0)); 3215 | out_html(change_to_size(0)); 3216 | if (!fillout) { 3217 | fillout=1; 3218 | out_html(""); 3219 | } 3220 | out_html(NEWLINE); 3221 | if (output_possible) { 3222 | /*   for mosaic users */ 3223 | printf("
    \n 

    Index

    \n
    \n"); 3224 | manidx[mip]=0; 3225 | printf("%s", manidx); 3226 | if (subs) printf("
    \n"); 3227 | printf("\n"); 3228 | print_sig(); 3229 | printf("\n\n"); 3230 | } else { 3231 | if (!filename) 3232 | filename = fname; 3233 | if (*filename == '/') 3234 | error_page("Invalid Manpage", 3235 | "The requested file %s is not a valid (unformatted) " 3236 | "man page.\nIf the file is a formatted manpage, " 3237 | "you could try to load the\n" 3238 | "plain file.\n", 3239 | filename, filename); 3240 | else 3241 | error_page("Invalid Manpage", 3242 | "The requested file %s is not a valid (unformatted) " 3243 | "man page.", filename); 3244 | } 3245 | if (idxfile) 3246 | fclose(idxfile); 3247 | if (buf) 3248 | free(buf); 3249 | return 0; 3250 | } 3251 | -------------------------------------------------------------------------------- /scripts/cgi-aux/man/man.aux: -------------------------------------------------------------------------------- 1 | Content-type: text/html 2 | 3 | 4 | 5 | Manual Pages - Main Contents 6 | 7 | 8 | 9 | 10 |

    Manual Pages - Main Contents

    11 |
    12 | 13 |

    Name and Section lookup

    14 | 15 | 16 | %lynx Start a query by typing an s. 17 | You can enter a program name, possibly preceded by the section, 18 | the directories to search (with -M) or a full name. 19 | For example: 20 |
      21 |
    • find 22 |
    • 1 find 23 |
    • -M /usr/man:/usr/X11R6/man:/usr/lib/perl5/man find 24 |
    • /local/gcc/man/man1/gperf.1 25 |
    26 | 27 |
    28 | 29 |

    Index of pages by name and description

    30 | Sections: 31 | 1. User Commands; 32 | 2. System Calls; 33 | 3. Library Functions; 34 | 4. Special Files; 35 | 5. File Formats; 36 | 6. Games; 37 | 7. Miscellany; 38 | 8. Administration and Privileged Commands; 39 | l. Postgresql Commands; 40 | n. Tcl Commands. 41 |

    42 |


    43 |

    Index of pages by name only

    44 | 1. User Commands; 45 | 2. System Calls; 46 | 3. Library Functions; 47 | 4. Special Files; 48 | 5. File Formats; 49 | 6. Games; 50 | 7. Miscellany; 51 | 8. Administration and Privileged Commands; 52 | l. Postgresql Commands; 53 | n. Tcl Commands; 54 | All Sections. 55 |

    56 |


    57 | 58 |

    Manual Pages full text search

    59 | 60 | 61 | Search the full text of the Manual Pages. 62 | 63 | 64 |

    65 |


    66 | 67 | The original man2html program and scripts are due to 68 | 69 | Richard Verhoeven and 70 | 71 | Michael Hamilton. 72 | This version is from man-1.6f maintained by 73 | Federico Lucifredi. 74 | 75 | 76 | -------------------------------------------------------------------------------- /scripts/cgi-aux/man/mansearch.aux: -------------------------------------------------------------------------------- 1 | Content-type: text/html 2 | 3 | 4 | 5 | Manual Pages - Text Search 6 | 7 | 8 | 9 | 10 |

    Manual Pages - Text Search

    11 | 12 | Return to Main Contents 13 |

    14 | 15 | 16 | %lynx Start a query by typing an s. 17 | 18 | Examples: 19 |

      20 |
    • pwd;directory - Find both in the same man page. 21 |
    • pwd,directory - Find either. 22 |
    • pwd directory - Find the exact phrase. 23 |
    • -F 1 pwd - Look in section 1 only. 24 |
    • -B glipmse - Find the best match (allow for misspelling). 25 |
    • -L 0:10 pwd - Only show the first 10 man pages matched. 26 |
    27 | 28 |
    29 |

    30 | The index uses the Glimpse 31 | (glimpse(1)) 32 | text indexing system. Many of the glimpse 33 | options, regular expressions, and wildcards are valid: 34 | see the help page for a summary. 35 |

    36 |


    37 | 38 |

    39 | Glimpse 40 | was developed by Udi Manber and Burra Gopal of the University of 41 | Arizona, and Sun Wu of the National Chung-Cheng University, Taiwan. 42 | You may contact the authors at 43 | glimpse@cs.arizona.edu 44 |

    45 | The Manual Page text search interface was created for Linux by 46 | 47 | Michael Hamilton. 48 | 49 | 50 | -------------------------------------------------------------------------------- /scripts/cgi-aux/man/mansearchhelp.aux: -------------------------------------------------------------------------------- 1 | Content-type: text/html 2 | 3 | 4 | 5 | Manual Pages - Search Help 6 | 7 | 8 | 9 | 10 |

    Manual Pages - Search Help

    11 | 12 | Perform another search 13 |
    14 | Return to Main Contents 15 |

    16 |


    17 |

    18 | The full text index uses the Glimpse text indexing system. 19 | The 20 | glimpse(1) 21 | manual page documents glimpse in full. This summary documents those 22 | features of glimpse that are valid when searching through the manual pages. 23 |

    24 |


    25 | 26 |

    Search Options

    27 | 28 | The following search options must be at the start of the search string. 29 | 30 |
    31 | 32 |
    - # 33 |
    34 | # is an integer between 1 and 8 35 | specifying the maximum number of errors 36 | permitted in finding the approximate matches (the default is zero). 37 | Generally, each insertion, deletion, or substitution counts as one error. 38 | Since the index stores only lower case characters, errors of 39 | substituting upper case with lower case may be missed. 40 | 41 |
    -B 42 |
    43 | Best match mode. (Warning: -B sometimes misses matches. It is safer 44 | to specify the number of errors explicitly.) 45 | When -B is specified and no exact matches are found, glimpse 46 | will continue to search until the closest matches (i.e., the ones 47 | with minimum number of errors) 48 | are found. 49 | In general, -B may be slower than -#, but not by very much. 50 | Since the index stores only lower case characters, errors of 51 | substituting upper case with lower case may be missed. 52 | 53 |
    -L x | x:y | x:y:z 54 |
    55 | A non-zero value of x limits the number of matches 56 | that will be shown. 57 | A non-zero value of y limits the number of man pages 58 | that will be shown. 59 | A non-zero valye of z will only show pages that have 60 | less that z matches. 61 | For example, -L 0:10 will output all matches for the first 10 files that 62 | contain a match. 63 | 64 |
    -F pattern 65 |
    66 | The -F option provides a pattern that restricts the search results to 67 | those filenames that match the pattern. 68 | or example, -F 8 effectively restricts matches to section 8. 69 | 70 |
    -w 71 |
    72 | Search for the pattern as a word - i.e., surrounded by non-alphanumeric 73 | characters. For example, 74 | -w -1 car will match cars, but not characters and not 75 | car10. 76 | The non-alphanumeric must 77 | surround the match; they cannot be counted as errors. 78 | This option does not work with regular expressions. 79 | 80 |
    -W 81 |
    82 | The default for Boolean AND queries is that they cover one record 83 | (the default for a record is one line) at a time. 84 | For example, glimpse 'good;bad' will output all lines containing 85 | both 'good' and 'bad'. 86 | The -W option changes the scope of Booleans to be the whole file. 87 | Within a file glimpse will output all matches to any of the patterns. 88 | So, glimpse -W 'good;bad' will output all lines containing 'good' 89 | or 'bad', but only in files that contain both patterns. 90 | 91 |
    -k 92 |
    93 | No symbol in the pattern is treated as a meta character. 94 | For example, -k a(b|c)*d will find 95 | the occurrences of a(b|c)*d whereas a(b|c)*d 96 | will find substrings that match the regular expression 'a(b|c)*d'. 97 | (The only exception is ^ at the beginning of the pattern and $ at the 98 | end of the pattern, which are still interpreted in the usual way. 99 | Use \^ or \$ if you need them verbatim.) 100 | 101 |
    102 | 103 |

    104 |


    105 | 106 |

    Patterns

    107 | 108 | Glimpse 109 | supports a large variety of patterns, including simple 110 | strings, strings with classes of characters, sets of strings, 111 | wild cards, and regular expressions (see LIMITATIONS). 112 | 113 |
    114 |
    Strings
    115 | Strings are any sequence of characters, including the special symbols 116 | `^' for beginning of line and `$' for end of line. 117 | The following special characters ( 118 | `$', 119 | 120 | `^', 121 | 122 | `*', 123 | 124 | `[', 125 | 126 | `^', 127 | 128 | `|', 129 | 130 | `(', 131 | 132 | `)', 133 | 134 | `!', 135 | 136 | and 137 | `\' 138 | 139 | ) 140 | as well as the following meta characters special to glimpse (and agrep): 141 | `;', 142 | 143 | `,', 144 | 145 | `#', 146 | 147 | `<', 148 | 149 | `>', 150 | 151 | `-', 152 | 153 | and 154 | `.', 155 | 156 | should be preceded by `\' if they are to be matched as regular 157 | characters. For example, \^abc\\ corresponds to the string ^abc\, 158 | whereas ^abc corresponds to the string abc at the beginning of a 159 | line. 160 |
    Classes of characters
    161 | a list of characters inside [] (in order) corresponds to any character 162 | from the list. For example, [a-ho-z] is any character between a and h 163 | or between o and z. The symbol `^' inside [] complements the list. 164 | For example, [^i-n] denote any character in the character set except 165 | character 'i' to 'n'. 166 | The symbol `^' thus has two meanings, but this is consistent with 167 | egrep. 168 | The symbol `.' (don't care) stands for any symbol (except for the 169 | newline symbol). 170 |
    Boolean operations
    171 | Glimpse 172 | 173 | supports an `AND' operation denoted by the symbol `;' 174 | an `OR' operation denoted by the symbol `,', 175 | or any combination. 176 | For example, 177 | glimpse 'pizza;cheeseburger' will output all lines containing 178 | both patterns. 179 | glimpse -F 'gnu;\.c$' 'define;DEFAULT' 180 | will output all lines containing both 'define' and 'DEFAULT' 181 | (anywhere in the line, not necessarily in order) in 182 | files whose name contains 'gnu' and ends with .c. 183 | glimpse '{political,computer};science' will match 'political science' 184 | or 'science of computers'. 185 |
    Wild cards
    186 | The symbol '#' is used to denote a sequence 187 | of any number (including 0) 188 | of arbitrary characters (see LIMITATIONS). 189 | The symbol # is equivalent to .* in egrep. 190 | In fact, .* will work too, because it is a valid regular expression 191 | (see below), but unless this is part of an actual regular expression, 192 | # will work faster. 193 | (Currently glimpse is experiencing some problems with #.) 194 |
    Combination of exact and approximate matching
    195 | Any pattern inside angle brackets <> must match the text exactly even 196 | if the match is with errors. For example, <mathemat>ics matches 197 | mathematical with one error (replacing the last s with an a), but 198 | mathe<matics> does not match mathematical no matter how many errors are 199 | allowed. 200 | (This option is buggy at the moment.) 201 |
    Regular expressions
    202 | Since the index is word based, a regular expression must match 203 | words that appear in the index for glimpse to find it. 204 | Glimpse first strips the regular expression from all non-alphabetic 205 | characters, and searches the index for all remaining words. 206 | It then applies the regular expression matching algorithm to the 207 | files found in the index. 208 | For example, glimpse 'abc.*xyz' will search the index 209 | for all files that contain both 'abc' and 'xyz', and then 210 | search directly for 'abc.*xyz' in those files. 211 | (If you use glimpse -w 'abc.*xyz', then 'abcxyz' will not be found, 212 | because glimpse 213 | will think that abc and xyz need to be matches to whole words.) 214 | The syntax of regular expressions in glimpse is in general the same as 215 | that for agrep. The union operation `|', Kleene closure `*', 216 | and parentheses () are all supported. 217 | Currently '+' is not supported. 218 | Regular expressions are currently limited to approximately 30 219 | characters (generally excluding meta characters). Some options 220 | (-d, -w, -t, -x, -D, -I, -S) do not 221 | currently work with regular expressions. 222 | The maximal number of errors for regular expressions that use '*' 223 | or '|' is 4. (See LIMITATIONS.) 224 | 225 |
    226 | 227 |
    228 | 229 |

    Limitations

    230 | 231 | The index of glimpse is word based. A pattern that contains more than 232 | one word cannot be found in the index. The way glimpse overcomes this 233 | weakness is by splitting any multi-word pattern into its set of words 234 | and looking for all of them in the index. 235 | For example, glimpse 'linear programming' will first consult the index 236 | to find all files containing both linear and programming, 237 | and then apply agrep to find the combined pattern. 238 | This is usually an effective solution, but it can be slow for 239 | cases where both words are very common, but their combination is not. 240 |

    241 | 242 | As was mentioned in the section on PATTERNS above, some characters 243 | serve as meta characters for glimpse and need to be 244 | preceded by '\' to search for them. The most common 245 | examples are the characters '.' (which stands for a wild card), 246 | and '*' (the Kleene closure). 247 | So, "glimpse ab.de" will match abcde, but "glimpse ab\.de" 248 | will not, and "glimpse ab*de" will not match ab*de, but 249 | "glimpse ab\*de" will. 250 | The meta character - is translated automatically to a hyphen 251 | unless it appears between [] (in which case it denotes a range of 252 | characters). 253 |

    254 | 255 | The index of glimpse stores all patterns in lower case. 256 | When glimpse searches the index it first converts 257 | all patterns to lower case, finds the appropriate files, 258 | and then searches the actual files using the original 259 | patterns. 260 | So, for example, glimpse ABCXYZ will first find all 261 | files containing abcxyz in any combination of lower and upper 262 | cases, and then searches these files directly, so only the 263 | right cases will be found. 264 | One problem with this approach is discovering misspellings 265 | that are caused by wrong cases. 266 | For example, glimpse -B abcXYZ will first search the 267 | index for the best match to abcxyz (because the pattern is 268 | converted to lower case); it will find that there are matches 269 | with no errors, and will go to those files to search them 270 | directly, this time with the original upper cases. 271 | If the closest match is, say AbcXYZ, glimpse may miss it, 272 | because it doesn't expect an error. 273 | Another problem is speed. If you search for "ATT", it will look 274 | at the index for "att". Unless you use -w to match the whole word, 275 | glimpse may have to search all files containing, for example, "Seattle" 276 | which has "att" in it. 277 |

    278 | 279 | There is no size limit for simple patterns and simple patterns 280 | within Boolean expressions. 281 | More complicated patterns, such as regular expressions, 282 | are currently limited to approximately 30 characters. 283 | Lines are limited to 1024 characters. 284 | Records are limited to 48K, and may be truncated if they are larger 285 | than that. 286 | The limit of record length can be 287 | changed by modifying the parameter Max_record in agrep.h. 288 |

    289 | 290 | Glimpseindex does not index words of size > 64. 291 |   292 | 293 |


    294 | 295 | 296 | -------------------------------------------------------------------------------- /scripts/cgi-bin/man/man2html: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # man2html cgi script - uses /usr/bin/man2html to format man pages 3 | # auxiliary text files in /home/httpd/cgi-aux/man 4 | # aeb@cwi.nl - 980109 5 | 6 | MAN2HTML="/usr/bin/man2html" 7 | MANX="/home/httpd/cgi-aux/man/man.aux" 8 | 9 | # Do we need lynxcgi URLs? For the moment our criterion is 10 | # 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. 11 | AGENT="${HTTP_USER_AGENT-unknown}" 12 | 13 | case "$AGENT" in 14 | Lynx*|lynx*) 15 | HH="${HTTP_HOST-nohh}" 16 | SED="s/%lynx //" 17 | ;; 18 | *) 19 | HH=nolynx 20 | SED="/%lynx/d" 21 | ;; 22 | esac 23 | 24 | SERVER="${SERVER_NAME-localhost}" 25 | case "$HH" in 26 | nohh) 27 | LL="-l" 28 | CG="lynxcgi:/home/httpd/cgi-bin/man" 29 | ;; 30 | *) 31 | LL="-H$SERVER" 32 | CG="http://$SERVER/cgi-bin/man" 33 | ;; 34 | esac 35 | 36 | # Find the required page - expect to be called with "man2html [sec] page". 37 | # There may a prefixed "-M manpath" option. 38 | if [ $# -ge 2 -a x"$1" = x-M ]; then 39 | MANPATH="$2" 40 | export MANPATH 41 | shift; shift 42 | MP=" using the given MANPATH" 43 | else 44 | MP="" 45 | fi 46 | 47 | # If no arguments given, show a start page. 48 | if [ $# = 0 ]; then 49 | if [ -r $MANX ]; then 50 | cat $MANX | sed "s#%cg#$CG#g; $SED" 51 | else 52 | "$MAN2HTML" -E "man2html: cannot open $MANX" 53 | fi 54 | exit 0 55 | fi 56 | 57 | if [ $# -gt 2 ]; then 58 | "$MAN2HTML" -E "man2html: bad invocation: too many arguments" 59 | exit 0 60 | fi 61 | 62 | # A single argument may be an explicitly give path name 63 | # Otherwise, ask man where to find it 64 | if [ $# = 1 ]; then 65 | case "$1" in 66 | /*) 67 | PAGE="$1" 68 | ;; 69 | *) 70 | PAGE=`man -w -c "$@" 2>/dev/null` 71 | ;; 72 | esac 73 | else 74 | PAGE=`man -w -c "$@" 2>/dev/null` 75 | fi 76 | 77 | if [ x"$PAGE" = x ]; then 78 | complaint="man2html: cannot find a page" 79 | if [ $# = 1 ]; then 80 | "$MAN2HTML" -E "$complaint for $1$MP" 81 | else 82 | "$MAN2HTML" -E "$complaint for $2 in section $1$MP" 83 | fi 84 | exit 0 85 | fi 86 | 87 | if [ -r "$PAGE" ] 88 | then 89 | case "$PAGE" in 90 | *.gz) 91 | zcat "$PAGE" | "$MAN2HTML" "$LL" -D "$PAGE" 92 | ;; 93 | *.bz2) 94 | bzcat "$PAGE" | "$MAN2HTML" "$LL" -D "$PAGE" 95 | ;; 96 | *) 97 | "$MAN2HTML" "$LL" "$PAGE" 98 | ;; 99 | esac 100 | elif [ -r "$PAGE".gz ] 101 | then 102 | zcat "$PAGE".gz | "$MAN2HTML" "$LL" -D "$PAGE" 103 | elif [ -r "$PAGE".bz2 ] 104 | then 105 | bzcat "$PAGE".bz2 | "$MAN2HTML" "$LL" -D "$PAGE" 106 | else 107 | "$MAN2HTML" -E "Strange... Cannot find (or read) $PAGE." 108 | fi 109 | exit 0 110 | -------------------------------------------------------------------------------- /scripts/cgi-bin/man/mansearch: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Interface to a glimpse search of the man pages. 4 | # Michael Hamilton 5 | # Small changes - aeb, 980109 6 | # 7 | 8 | # Do we need lynxcgi URLs? For the moment our criterion is 9 | # 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. 10 | AGENT="${HTTP_USER_AGENT-unknown}" 11 | 12 | case "$AGENT" in 13 | Lynx*|lynx*) 14 | HH="${HTTP_HOST-nohh}" 15 | SED="s/%lynx //" 16 | ;; 17 | *) 18 | HH=nolynx 19 | SED="/%lynx/d" 20 | ;; 21 | esac 22 | 23 | SERVER="${SERVER_NAME-localhost}" 24 | case "$HH" in 25 | nohh) 26 | CG="lynxcgi:/home/httpd/cgi-bin/man" 27 | ;; 28 | *) 29 | CG="http://$SERVER/cgi-bin/man" 30 | ;; 31 | esac 32 | QUOTE="'" 33 | export CG QUOTE SED 34 | 35 | exec awk ' 36 | function removeopts(string) { 37 | gsub(/^[ \t]/, "", string); # Remove leading spaces 38 | gsub(/[ \t]$/, "", string); # Remove trailing spaces 39 | gsub(/[ \t\\];/, ";", string); # Remove spaces before ; 40 | gsub(/[ \t];/, ",", string); # Remove spaces before , 41 | while (match(string, /^-[FLBwk1-8]/)) { 42 | if (match(string, /^-[FL]( |.)[^ \t]+[ \t]+/)) { # Option with arg 43 | options = options " " substr(string, RSTART, RLENGTH); 44 | string = substr(string, RSTART + RLENGTH); 45 | } 46 | else if (match(string, /^-[Bwk1-8][ \t]+/)) { # Option without arg 47 | options = options " " substr(string, RSTART, RLENGTH); 48 | string = substr(string, RSTART + RLENGTH); 49 | } 50 | else if (match(string, /^-[^ \t]/)) { # Remove it 51 | string = substr(string, RSTART + RLENGTH); 52 | } 53 | } 54 | return string; 55 | } 56 | 57 | BEGIN { 58 | 59 | searchdocument = "/home/httpd/cgi-aux/man/mansearch.aux"; 60 | quote = ENVIRON["QUOTE"]; 61 | cgipath = ENVIRON["CG"]; 62 | sedcmd = ENVIRON["SED"]; 63 | truncate_at = 11; # Single page display match limit. 64 | 65 | glimpse_cmd = "glimpse -z -H /var/man2html -y -W -i " 66 | 67 | for (i = 1; i < ARGC; i++) { 68 | string = string " " ARGV[i]; 69 | } 70 | # Have to be careful to single quote this 71 | # string later. 72 | gsub(/[^a-zA-Z0-9-_+ \t\/@%:;,$*|]/, " ", string); 73 | 74 | string = removeopts(string); 75 | 76 | gsub(/[^a-zA-Z0-9-_+ \t\/@%:,]/, " ", options); 77 | 78 | if (!string) { 79 | if (system("test -r " searchdocument ) != 0) { 80 | print "Content-type: text/html\n\n"; 81 | print ""; 82 | print "mansearch - file not found"; 83 | print "\n"; 84 | print "Sorry - cannot read " searchdocument "."; 85 | print ""; 86 | exit; 87 | } 88 | system("sed " quote "s#%cg#" cgipath "#g;" sedcmd quote " " searchdocument ); 89 | exit; 90 | } 91 | 92 | print "Content-type: text/html"; 93 | print ""; 94 | print ""; 95 | print ""; 96 | print "Manual Pages - Search Results: " string ""; 97 | print ""; 98 | print ""; 99 | 100 | print "

    Manual Pages - Search Results

    "; 101 | print "

    Target text: " options " " string "

    "; 102 | 103 | print ""; 104 | print "Perform another search"; 105 | print "
    "; 106 | print ""; 107 | print "Return to Main Contents"; 108 | print ""; 109 | 110 | print "
    "; 111 | 112 | print "
    "; 113 | # Unless you like being hacked, the single 114 | # forward quotes are most important. 115 | cmd = glimpse_cmd " " options " " quote string quote " 2>/dev/null" ; 116 | 117 | while ((cmd | getline matchline) > 0) { 118 | if (split(matchline, part, ": ") == 1) { 119 | continue; 120 | } 121 | else { 122 | fullname = part[1]; 123 | } 124 | 125 | if (fullname == "glimpse") { 126 | print "
    "fullname":"; 127 | } 128 | else if (fullname != last_fullname) { 129 | mcount++; 130 | tcount = 0; 131 | last_fullname = fullname ; 132 | last_text = ""; 133 | 134 | if (match(fullname, ".*/")) { 135 | dirname = substr(fullname, 1, RLENGTH); 136 | filename = substr(fullname, RLENGTH + 1); 137 | if (dirname != last_dirname) { 138 | last_dirname = dirname; 139 | print "
    "; 140 | print "

    Location: " dirname "

    "; 141 | print "
    "; 142 | } 143 | } 144 | else { 145 | filename = fullname; 146 | } 147 | 148 | if (match(filename, /\.[^.]+$/)) { 149 | ref = substr(filename, 1, RSTART - 1) "+" substr(filename, RSTART + 1); 150 | } 151 | else { 152 | ref = filename; 153 | } 154 | print "
    "; 155 | textname = filename; 156 | sub(/\.(gz)|Z|z$/, "", textname); 157 | sub(/\./, "(", textname); 158 | textname = textname ")"; 159 | print textname; 160 | print ""; 161 | } 162 | 163 | text = substr(matchline, length(fullname) + 2); 164 | tcount++; 165 | if (tcount < truncate_at) { 166 | sub(/^ *.[^ ]+ /, "", text); 167 | sub(/ +$/, "", text); 168 | gsub(/\\f./, "", text); 169 | gsub(/\\&/, "", text); 170 | gsub(/\\/, "", text); 171 | print "
    " text; 172 | } 173 | else if (tcount == truncate_at) { 174 | print "
    ...additional matches not shown."; 175 | } 176 | } 177 | 178 | print "
    "; 179 | if (mcount == 0) { 180 | print "No matches found."; 181 | } 182 | else if (mcount == 1) { 183 | print "
    \n

    1 match found." 184 | } 185 | else { 186 | print "


    \n

    " mcount " matches found." 187 | } 188 | print ""; 189 | print ""; 190 | exit; 191 | }' "$@" 192 | 193 | -------------------------------------------------------------------------------- /scripts/cgi-bin/man/mansearchhelp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | MAN2HTML=/usr/bin/man2html 3 | MANSH=/home/httpd/cgi-aux/man/mansearchhelp.aux 4 | 5 | # Do we need lynxcgi URLs? For the moment our criterion is 6 | # 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. 7 | AGENT="${HTTP_USER_AGENT-unknown}" 8 | case "$AGENT" in 9 | Lynx*|lynx*) 10 | HH="${HTTP_HOST-nohh}" 11 | ;; 12 | *) 13 | HH=nolynx 14 | ;; 15 | esac 16 | 17 | SERVER="${SERVER_NAME-localhost}" 18 | case "$HH" in 19 | nohh) 20 | CG="lynxcgi:/home/httpd/cgi-bin/man" 21 | ;; 22 | *) 23 | CG="http://$SERVER/cgi-bin/man" 24 | ;; 25 | esac 26 | 27 | if [ -r $MANSH ]; then 28 | sed s#%cg#$CG#g $MANSH 29 | else 30 | $MAN2HTML -E "man2html: cannot open $MANSH" 31 | fi 32 | exit 0 33 | -------------------------------------------------------------------------------- /scripts/cgi-bin/man/mansec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # 3 | # Generate an index into a manual section by using find. 4 | # Michael Hamilton 5 | # Small changes - aeb, 980109 6 | # 7 | BEGIN { 8 | 9 | OFS=""; 10 | 11 | if (ARGC != 3) { 12 | print "Content-type: text/html\n\n"; 13 | print ""; 14 | print "manwhatis - bad call"; 15 | print "\n"; 16 | print "manwhatis: wrong number of arguments"; 17 | print ""; 18 | exit; 19 | } 20 | cgipath = ARGV[1]; 21 | section = ARGV[2]; 22 | 23 | if (section !~ /^[1-8ln]$/ && section != "all") { 24 | print "Content-type: text/html\n\n"; 25 | print ""; 26 | print "Manual - Illegal section"; 27 | print ""; 28 | print "Illegal section number '" section "'." ; 29 | print "Must be one of 1,2,3,4,5,6,7,8,l,n or all"; 30 | print ""; 31 | exit; 32 | } 33 | 34 | "echo $PPID" | getline pid; 35 | 36 | if (cgipath ~ /lynxcgi/) { 37 | cache_suffix = "l"; 38 | } 39 | else { 40 | cache_suffix = "h"; 41 | } 42 | 43 | cache_dir = "/var/man2html"; 44 | cache_file = "manindex" cache_suffix "-" section ".html"; 45 | cache = cache_dir "/" cache_file; 46 | cache_tmp = cache "_" pid; 47 | buffer_tmp = cache "_items_" pid; 48 | 49 | # Find out the man path 50 | "man -w" | getline man_path 51 | man_path = man_path ":"; 52 | gsub(":", " ", man_path); 53 | # See if anything is out of date. 54 | # Check all man[1-8] dir dates vs cache date 55 | if (section == "all") { 56 | if (system("test -f " cache) == 0) { 57 | cmd = "find " man_path " -maxdepth 1 -name 'man[1-8]' -newer " cache; 58 | cmd | getline need_update; 59 | } 60 | else { 61 | need_update = 1; 62 | } 63 | } 64 | else { 65 | if (system("test -f " cache) == 0) { 66 | cmd = "find " man_path " -maxdepth 1 -name man" section " -newer " cache; 67 | cmd | getline need_update; 68 | } 69 | else { 70 | need_update = 1; 71 | } 72 | } 73 | 74 | if (need_update != "") { 75 | if (system("test -w " cache_dir "/.") != 0) { 76 | print "Content-type: text/html\n\n"; 77 | print ""; 78 | print "mansec - no cache"; 79 | print "\n"; 80 | print "Sorry - cannot create index."; 81 | print "No writable cache directory " cache_dir " exists."; 82 | print ""; 83 | exit; 84 | } 85 | 86 | sec_name[1] = "User Commands"; 87 | sec_name[2] = "System Calls"; 88 | sec_name[3] = "Library Functions"; 89 | sec_name[4] = "Special Files"; 90 | sec_name[5] = "File Formats"; 91 | sec_name[6] = "Games"; 92 | sec_name[7] = "Miscellany"; 93 | sec_name[8] = "Administration and Privileged Commands"; 94 | sec_name["all"] = "All available manual pages"; 95 | num_sections = 8; 96 | 97 | # Print heading 98 | print "Content-type: text/html\n\n" > cache_tmp; 99 | print "\n" > cache_tmp; 100 | print "Manual Pages - Names: " section ". " sec_name[section] ""> cache_tmp; 101 | print "\n" > cache_tmp; 102 | print "

    Manual Pages - Page Names

    " > cache_tmp; 103 | print "

    Section " section ": " sec_name[section] "

    " > cache_tmp; 104 | 105 | "hostname" | getline hostname; 106 | "date" | getline date; 107 | print hostname " (" date ")" > cache_tmp; 108 | 109 | if (section != "all") { 110 | sec_sub_dir = "/man" section; 111 | } 112 | else { 113 | sec_sub_dir = "/man*"; 114 | } 115 | gsub(" ", sec_sub_dir " ", man_path); 116 | 117 | print "

    Manual pages found under " man_path "." > cache_tmp; 118 | 119 | # Find any man[1-8]/filenames 120 | while ((("find " man_path " -follow -type f -printf '%f\n' | sort -f ") | getline manpage) > 0) { 121 | # Check for new letter of alphabet 122 | letter = tolower(substr(manpage,1,1)); 123 | if (letter != last_letter) { 124 | last_letter = letter; 125 | letter_index[++num_letters] = letter; 126 | # Start a new alphabetic heading 127 | print "

    ", toupper(letter), "

    " > buffer_tmp; 128 | # Print out alphabetic quick index and other links 129 | } 130 | # Split page.n into "page" and "n" and generate an entry 131 | sub(/[.]([zZ]|(gz))$/, "", manpage); 132 | match(manpage, /[.][^.]+$/); 133 | title = substr(manpage, 1, RSTART - 1); 134 | if (section != "all") { 135 | print "", title, "(", substr(manpage, RSTART + 1), ")" > buffer_tmp; 136 | } 137 | else { 138 | sec = substr(manpage, RSTART + 1) 139 | print "", title, "(", sec, ")" > buffer_tmp; 140 | } 141 | } 142 | 143 | close(buffer_tmp); 144 | 145 | print "

    " > cache_tmp; 146 | 147 | # Print out alphabetic quick index and other links 148 | for (i = 1; i <= num_letters; i++) { 149 | print "" toupper(letter_index[i]) "" > cache_tmp; 150 | } 151 | 152 | print "


    " > cache_tmp; 153 | print "Return to Main Contents" > cache_tmp; 154 | 155 | print "

    Other sections:" > cache_tmp; 156 | for (i=1; i<=num_sections; i++) { 157 | if (i != section) { # Dont print an entry for the section we are in 158 | print "" i ". " sec_name[i] " " > cache_tmp; 159 | } 160 | } 161 | print "


    " > cache_tmp; 162 | # Print out the accumulated index entries 163 | while ((getline < buffer_tmp) > 0) print > cache_tmp; 164 | print "


    " > cache_tmp; 165 | # Print out alphabetic quick index and other links 166 | for (i = 1; i <= num_letters; i++) { 167 | print "" toupper(letter_index[i]) "" > cache_tmp; 168 | } 169 | print "


    " > cache_tmp; 170 | print "

    Return to Main Contents" > cache_tmp; 171 | print "

    Other sections:" > cache_tmp; 172 | for (i=1; i<=num_sections; i++) { 173 | if (i != section) { # Dont print an entry for the section we are in 174 | print "" i ". " sec_name[i] " " > cache_tmp; 175 | } 176 | } 177 | print "\n" > cache_tmp; 178 | system("/bin/mv " cache_tmp " " cache); 179 | system("/bin/rm -f " buffer_tmp); 180 | } 181 | system("/bin/cat " cache); 182 | exit; 183 | } 184 | -------------------------------------------------------------------------------- /scripts/cgi-bin/man/manwhatis: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # 3 | # Generate a whatis index into the manual pages by using find to 4 | # locate all the whatis files. 5 | # Michael Hamilton 6 | # Small changes - aeb, 980109 7 | # 8 | BEGIN { 9 | 10 | OFS=""; 11 | 12 | if (ARGC != 3) { 13 | print "Content-type: text/html\n\n"; 14 | print ""; 15 | print "manwhatis - bad call"; 16 | print "\n"; 17 | print "manwhatis: wrong number of arguments"; 18 | print ""; 19 | exit; 20 | } 21 | cgipath = ARGV[1]; 22 | section = ARGV[2]; 23 | 24 | if (section !~ /^[1-8ln]$/) { 25 | print "Content-type: text/html\n\n"; 26 | print ""; 27 | print "Manual - Illegal section"; 28 | print "\n"; 29 | print "Illegal section number '" section "'." ; 30 | print "Must be one of 1,2,3,4,5,6,7,8,l,n"; 31 | print ""; 32 | exit; 33 | } 34 | 35 | if (cgipath ~ /lynxcgi/) { 36 | cache_suffix = "l"; 37 | } 38 | else { 39 | cache_suffix = "h"; 40 | } 41 | 42 | cache_dir = "/var/man2html"; 43 | cache_file = "whatis" cache_suffix "-" section ".html"; 44 | cache = cache_dir "/" cache_file; 45 | 46 | 47 | # Find out the man path 48 | "man -w" | getline man_path 49 | gsub(":", " ", man_path); 50 | # See if anything is out of date. 51 | if (system("test -f " cache) == 0) { 52 | cmd = "find " man_path " -maxdepth 1 -name whatis -newer " cache; 53 | cmd | getline need_update; 54 | } 55 | else { 56 | need_update = 1; 57 | } 58 | 59 | if (need_update != "") { 60 | 61 | if (system("test -w " cache_dir "/.") != 0) { 62 | print "Content-type: text/html\n\n"; 63 | print ""; 64 | print "manwhatis - no cache"; 65 | print "\n"; 66 | print "Sorry - cannot create index."; 67 | print "No writable cache directory " cache_dir " exists."; 68 | print ""; 69 | exit; 70 | } 71 | 72 | "echo $PPID" | getline pid; 73 | 74 | cache_tmp = cache "_" pid; 75 | sort_tmp = cache_dir "/manwhatis_tmp_" pid ; 76 | buffer_tmp = cache_dir "/manwhatis_tmp2_" pid; 77 | 78 | sec_name[1] = "User Commands"; 79 | sec_name[2] = "System Calls"; 80 | sec_name[3] = "Library Functions"; 81 | sec_name[4] = "Special Files"; 82 | sec_name[5] = "File Formats"; 83 | sec_name[6] = "Games"; 84 | sec_name[7] = "Miscellany"; 85 | sec_name[8] = "Administration and Privileged Commands"; 86 | num_sections = 8; 87 | # Print heading 88 | print "Content-type: text/html\n\n" > cache_tmp; 89 | print "\n" > cache_tmp; 90 | print "Manual Pages - Names and Descriptions: " section ". " sec_name[section] "" > cache_tmp; 91 | 92 | print "\n" > cache_tmp; 93 | print "

    Manual Pages - Names and Descriptions

    " > cache_tmp; 94 | print "

    Section " section ": " sec_name[section] "

    " > cache_tmp; 95 | "hostname" | getline hostname; 96 | "date" | getline date; 97 | print hostname " (" date ")" > cache_tmp; 98 | # Find out the man path 99 | "man -w" | getline; 100 | $1 = $1 ":"; 101 | gsub(":", " ", $1); 102 | 103 | find_cmd = "find " man_path " -maxdepth 1 -name whatis -printf '%p '"; 104 | find_cmd | getline whatis_files; 105 | close(find_cmd); 106 | 107 | if (whatis_files == "") { 108 | print "Content-type: text/html\n\n"; 109 | print ""; 110 | print "Manwhatis - Error updating index"; 111 | print "\n"; 112 | print "Unable to find whatis files - Sorry." 113 | print ""; 114 | exit; 115 | } 116 | # Try to parse valid entries - those that contain ([0-9]) 117 | # Note that egrep is sometimes in /bin, sometimes in /usr/bin 118 | extract_cmd = "egrep -h '\\(" section "[A-Za-z]*\\)' " whatis_files ; 119 | 120 | print "
    Manual pages referenced in " whatis_files "

    " > cache_tmp; 121 | 122 | # Note that sort sometimes lives in /bin and sometimes in /usr/bin 123 | sort_cmd = "sort -f >> " sort_tmp; 124 | 125 | while ( (extract_cmd | getline) > 0 ) { 126 | if (bracket_pos = index($0, "(")) { 127 | sec_full_num = substr($0, bracket_pos + 1, index($0, ")") - bracket_pos - 1); 128 | names = substr($0, 1, bracket_pos - 2); 129 | # Get rid of blanks and commas. 130 | n = split(names, name_list, " *, *"); 131 | description = substr($0, bracket_pos + length(sec_full_num) + 2); 132 | # Get rid of AT&T 133 | gsub("&", "\&", description); 134 | # Generate a entry for each name 135 | for (i = 1; i <= n; i++) { 136 | print name_list[i] " " sec_full_num " " name_list[1] " / " description | sort_cmd; 137 | } 138 | } 139 | } 140 | close(extract_cmd); 141 | close(sort_cmd); 142 | 143 | while ((getline < sort_tmp) > 0) { 144 | 145 | letter = tolower(substr($1,1,1)); 146 | if (letter != last_letter) { 147 | if (last_letter) { 148 | print "

    " > buffer_tmp; 149 | } 150 | last_letter = letter; 151 | letter_index[++num_letters] = letter; 152 | # Terminate list, start a new one 153 | 154 | print "

    ", toupper(letter), "

    \n
    " > buffer_tmp ; 155 | } 156 | # Generate a
    for the name 157 | if ($3 != last_file || $1 != last_name) { # Don't repeat the same entry link. 158 | print "
    ", $1, "(", $2, ")", "" > buffer_tmp; 159 | last_file = $3; 160 | last_name = $1; 161 | } 162 | print "
    ", substr($0, match($0, "/") + 1) > buffer_tmp; 163 | } 164 | # Finish off last list 165 | 166 | print "\n

    " > buffer_tmp; 167 | close(buffer_tmp); 168 | 169 | system("/bin/rm " sort_tmp); 170 | 171 | # Print out alphabetic quick index and other links 172 | for (i = 1; i <= num_letters; i++) { 173 | print "" toupper(letter_index[i]) "" > cache_tmp; 174 | } 175 | print "


    " > cache_tmp; 176 | print "Return to Main Contents" > cache_tmp; 177 | 178 | print "

    Other sections:" > cache_tmp; 179 | for (i=1; i<=num_sections; i++) { 180 | if (i != section) { # Dont print an entry for the section we are in 181 | print "" i ". " sec_name[i] " " > cache_tmp; 182 | } 183 | } 184 | print "


    " > cache_tmp; 185 | # Print out the accumulated contents entries 186 | while ((getline < buffer_tmp) > 0) print > cache_tmp; 187 | print "


    " > cache_tmp; 188 | 189 | for (i = 1; i <= num_letters; i++) { 190 | print "" toupper(letter_index[i]) "" > cache_tmp; 191 | } 192 | print "


    " > cache_tmp; 193 | print "

    Return to Main Contents" > cache_tmp; 194 | 195 | print "

    Other sections:" > cache_tmp; 196 | for (i=1; i<=num_sections; i++) { 197 | if (i != section) { # Dont print an entry for the section we are in 198 | print "" i ". " sec_name[i] " " > cache_tmp; 199 | } 200 | } 201 | print "" > cache_tmp; 202 | print "" > cache_tmp; 203 | system("/bin/mv " cache_tmp " " cache); 204 | system("/bin/rm " buffer_tmp); 205 | } 206 | system("/bin/cat " cache); 207 | exit; 208 | } 209 | -------------------------------------------------------------------------------- /strdefs.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | #ifndef NULL 4 | #define NULL ((void *) 0) 5 | #endif 6 | 7 | int nroff = 1; 8 | 9 | #define NROFF (-666) 10 | #define TROFF (-667) 11 | 12 | STRDEF *chardef, *strdef, *defdef; 13 | INTDEF *intdef; 14 | 15 | static INTDEF standardint[] = { 16 | { V('n',' '), NROFF, 0, NULL }, 17 | { V('t',' '), TROFF, 0, NULL }, 18 | { V('o',' '), 1, 0, NULL }, 19 | { V('e',' '), 0, 0, NULL }, 20 | { V('.','l'), 70, 0, NULL }, 21 | { V('.','$'), 0, 0, NULL }, 22 | { V('.','A'), NROFF, 0, NULL }, 23 | { V('.','T'), TROFF, 0, NULL }, 24 | { V('.','V'), 1, 0, NULL }, /* the me package tests for this */ 25 | { 0, 0, 0, NULL } }; 26 | 27 | static STRDEF standardstring[] = { 28 | { V('R',' '), 1, "®", NULL }, 29 | { V('l','q'), 2, "``", NULL }, 30 | { V('r','q'), 2, "''", NULL }, 31 | { 0, 0, NULL, NULL} 32 | }; 33 | 34 | 35 | static STRDEF standardchar[] = { 36 | { V('*','*'), 1, "*", NULL }, /* math star */ 37 | { V('*','A'), 1, "A", NULL }, 38 | { V('*','B'), 1, "B", NULL }, 39 | { V('*','C'), 2, "Xi", NULL }, 40 | { V('*','D'), 5, "Delta", NULL }, 41 | { V('*','E'), 1, "E", NULL }, 42 | { V('*','F'), 3, "Phi", NULL }, 43 | { V('*','G'), 5, "Gamma", NULL }, 44 | { V('*','H'), 5, "Theta", NULL }, 45 | { V('*','I'), 1, "I", NULL }, 46 | { V('*','K'), 1, "K", NULL }, 47 | { V('*','L'), 6, "Lambda", NULL }, 48 | { V('*','M'), 1, "M", NULL }, 49 | { V('*','N'), 1, "N", NULL }, 50 | { V('*','O'), 1, "O", NULL }, 51 | { V('*','P'), 2, "Pi", NULL }, 52 | { V('*','Q'), 3, "Psi", NULL }, 53 | { V('*','R'), 1, "P", NULL }, 54 | { V('*','S'), 5, "Sigma", NULL }, 55 | { V('*','T'), 1, "T", NULL }, 56 | { V('*','U'), 1, "Y", NULL }, 57 | { V('*','W'), 5, "Omega", NULL }, 58 | { V('*','X'), 1, "X", NULL }, 59 | { V('*','Y'), 1, "H", NULL }, 60 | { V('*','Z'), 1, "Z", NULL }, 61 | { V('*','a'), 5, "alpha", NULL }, 62 | { V('*','b'), 4, "beta", NULL }, 63 | { V('*','c'), 2, "xi", NULL }, 64 | { V('*','d'), 5, "delta", NULL }, 65 | { V('*','e'), 7, "epsilon", NULL }, 66 | { V('*','f'), 3, "phi", NULL }, 67 | { V('*','g'), 5, "gamma", NULL }, 68 | { V('*','h'), 5, "theta", NULL }, 69 | { V('*','i'), 4, "iota", NULL }, 70 | { V('*','k'), 5, "kappa", NULL }, 71 | { V('*','l'), 6, "lambda", NULL }, 72 | { V('*','m'), 1, "µ", NULL }, 73 | { V('*','n'), 2, "nu", NULL }, 74 | { V('*','o'), 1, "o", NULL }, 75 | { V('*','p'), 2, "pi", NULL }, 76 | { V('*','q'), 3, "psi", NULL }, 77 | { V('*','r'), 3, "rho", NULL }, 78 | { V('*','s'), 5, "sigma", NULL }, 79 | { V('*','t'), 3, "tau", NULL }, 80 | { V('*','u'), 7, "upsilon", NULL }, 81 | { V('*','w'), 5, "omega", NULL }, 82 | { V('*','x'), 3, "chi", NULL }, 83 | { V('*','y'), 3, "eta", NULL }, 84 | { V('*','z'), 4, "zeta", NULL }, 85 | { V('+','-'), 1, "±", NULL }, 86 | { V('1','2'), 1, "½", NULL }, 87 | { V('1','4'), 1, "¼", NULL }, 88 | { V('3','4'), 1, "¾", NULL }, 89 | { V('F','i'), 3, "ffi", NULL }, 90 | { V('F','l'), 3, "ffl", NULL }, 91 | { V('a','a'), 1, "´", NULL }, 92 | { V('a','p'), 1, "~", NULL }, 93 | { V('b','r'), 1, "|", NULL }, 94 | { V('b','u'), 1, "*", NULL }, /* bullet */ 95 | { V('b','v'), 1, "|", NULL }, 96 | { V('c','i'), 1, "o", NULL }, /* circle */ 97 | { V('c','o'), 1, "©", NULL }, 98 | { V('c','t'), 1, "¢", NULL }, 99 | { V('d','e'), 1, "°", NULL }, 100 | { V('d','g'), 1, "+", NULL }, /* dagger */ 101 | { V('d','i'), 1, "÷", NULL }, 102 | { V('e','m'), 3, "---", NULL }, /* em dash */ 103 | { V('e','n'), 1, "-", NULL }, /* en dash */ 104 | { V('e','q'), 1, "=", NULL }, 105 | { V('e','s'), 1, "Ø", NULL }, 106 | { V('f','f'), 2, "ff", NULL }, 107 | { V('f','i'), 2, "fi", NULL }, 108 | { V('f','l'), 2, "fl", NULL }, 109 | { V('f','m'), 1, "´", NULL }, 110 | { V('g','a'), 1, "`", NULL }, 111 | { V('h','y'), 1, "-", NULL }, 112 | { V('l','c'), 2, "|¯", NULL }, 113 | { V('i','f'), 8, "Infinity", NULL }, /* infinity sign */ 114 | { V('i','s'), 8, "Integral", NULL }, /* integral sign */ 115 | { V('l','f'), 2, "|_", NULL }, 116 | { V('l','k'), 1, "{", NULL }, 117 | { V('m','i'), 1, "-", NULL }, 118 | { V('m','u'), 1, "×", NULL }, 119 | { V('n','o'), 1, "¬", NULL }, 120 | { V('o','r'), 1, "|", NULL }, 121 | { V('p','d'), 1, "d", NULL }, /* partial derivative */ 122 | { V('p','l'), 1, "+", NULL }, 123 | { V('r','c'), 2, "¯|", NULL }, 124 | { V('r','f'), 2, "_|", NULL }, 125 | { V('r','g'), 1, "®", NULL }, 126 | { V('r','k'), 1, "}", NULL }, 127 | { V('r','n'), 1, "¯", NULL }, 128 | { V('r','u'), 1, "_", NULL }, 129 | { V('s','c'), 1, "§", NULL }, 130 | { V('s','l'), 1, "/", NULL }, 131 | { V('s','q'), 2, "[]", NULL }, 132 | { V('t','s'), 1, "s", NULL }, /* should be terminal sigma */ 133 | { V('u','l'), 1, "_", NULL }, 134 | { V('>','='), 1, ">", NULL }, 135 | { V('<','='), 1, "<", NULL }, 136 | { 0, 0, NULL, NULL } 137 | }; 138 | 139 | void stdinit(void) { 140 | STRDEF *stdf; 141 | int i; 142 | 143 | stdf = &standardchar[0]; 144 | i = 0; 145 | while (stdf->nr) { 146 | if (stdf->st) stdf->st = xstrdup(stdf->st); 147 | stdf->next = &standardchar[i]; 148 | stdf = stdf->next; 149 | i++; 150 | } 151 | chardef=&standardchar[0]; 152 | 153 | stdf=&standardstring[0]; 154 | i=0; 155 | while (stdf->nr) { 156 | /* waste a little memory, and make a copy, to avoid 157 | the segfault when we free non-malloced memory */ 158 | if (stdf->st) stdf->st = xstrdup(stdf->st); 159 | stdf->next = &standardstring[i]; 160 | stdf = stdf->next; 161 | i++; 162 | } 163 | strdef=&standardstring[0]; 164 | 165 | intdef=&standardint[0]; 166 | i=0; 167 | while (intdef->nr) { 168 | if (intdef->nr == NROFF) intdef->nr = nroff; else 169 | if (intdef->nr == TROFF) intdef->nr = !nroff; 170 | intdef->next = &standardint[i]; 171 | intdef = intdef->next; 172 | i++; 173 | } 174 | intdef = &standardint[0]; 175 | defdef = NULL; 176 | } 177 | --------------------------------------------------------------------------------