📄 man2html.c
字号:
/*** This program was written by Richard Verhoeven (NL:5482ZX35)** at the Eindhoven University of Technology. Email: rcb5@win.tue.nl**** Permission is granted to distribute, modify and use this program as long** as this comment is not removed or changed.*//*** If you want to use this program for your WWW server, adjust the line** which defines the CGIBASE or compile it with the -DCGIBASE='"..."' option.**** You have to adjust the built-in manpath to your local system. Note that** every directory should start and end with the '/' and that the first** directory should be "/" to allow a full path as an argument.**** The program first check if PATH_INFO contains some information.** If it does (t.i. man2html/some/thing is used), the program will look** for a manpage called PATH_INFO in the manpath.**** Otherwise the manpath is searched for the specified command line argument,** where the following options can be used:**** name name of manpage (csh, printf, xv, troff)** section the section (1 2 3 4 5 6 7 8 9 n l 1v ...)** -M path an extra directory to look for manpages (replaces "/")**** If man2html finds multiple manpages that satisfy the options, an index** is displayed and the user can make a choice. If only one page is** found, that page will be displayed.**** man2html will add links to the converted manpages. The function add_links** is used for that. At the moment it will add links as follows, where ** indicates what should match to start with:** ^^^** Recognition Item Link** ----------------------------------------------------------** name(*) Manpage ../man?/name.*** ^** name@hostname Email address mailto:name@hostname** ^** method://string URL method://string** ^^^** www.host.name WWW server http://www.host.name** ^^^^** ftp.host.name FTP server ftp://ftp.host.name** ^^^^** <file.h> Include file file:/usr/include/file.h** ^^^**** Since man2html does not check if manpages, hosts or email addresses exist,** some links might not work. For manpages, some extra checks are performed** to make sure not every () pair creates a link. Also out of date pages** might point to incorrect places.**** The program will not allow users to get system specific files, such as** /etc/passwd. It will check that "man" is part of the specified file and** that "/../" isn't. Even if someone manages to get such file, man2html will** handle it like a manpage and will usually not produce any output (or crash).**** If you find any bugs when normal manpages are converted, please report** them to me (rcb5@win.tue.nl) after you have checked that man(1) can handle** the manpage correct.**** Known bugs and missing features:**** * Equations are not converted at all.** * Tables are converted but some features are not possible in html.** * The tabbing environment is converted by counting characters and adding** spaces. This might go wrong (outside <PRE>)** * Some pages look beter if man2html works in troff mode, especially pages** with tables. You can deside at compile time which made you want to use.**** -DNROFF=0 troff mode** -DNROFF=1 nroff mode (default)**** if you install both modes, you should compile with the correct CGIBASE.** * Some manpages rely on the fact that troff/nroff is used to convert** them and use features which are not descripted in the man manpages.** (definitions, calculations, conditionals, requests). I can't guarantee** that all these features work on all manpages. (I didn't have the** time to look through all the available manpages.)*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/stat.h>#include <dirent.h>#include <ctype.h>#include <sys/types.h>#include <time.h>#include <sys/time.h>#ifndef CGIBASE#define CGIBASE "http://wsinwp01.win.tue.nl:1234/cgi-bin/man2html"#endif#ifndef NROFF#define NROFF 1#endifchar *signature = "<HR>\n""This document was created by\n""<A HREF=\""CGIBASE"\">man2html</A>,\n""using the manual pages.<BR>\n""Time: %s\n";/* timeformat for signature */#define TIMEFORMAT "%T GMT, %B %d, %Y"char *manpath[] = { "/", "/usr/X11/man/", "/usr/man/", "/usr/local/man/", "/usr/exp/man/", "/usr/openwin/man/", "/usr/tex/man/", "/usr/www/man/", "/usr/lang/man/", "/usr/gnu/man/", "/usr/motif/man/", "/usr/titools/man/", "/usr/sunpc/man/", "/usr/ncd/man/", "/usr/newsprint/man/", NULL };char *sections = "123456789nl";void usage(void){ printf("Content-type: text/html\n\n" "<HTML><HEAD>\n" "<TITLE>Manual Pages</TITLE>\n" "</HEAD><BODY>\n" "<H1>Manual Pages</H1>\n" "This is a HyperText interface to the UNIX manpages.\n" "You can enter a program name, the section, an extra\n" "directory (using -M) or a full name. For example\n" "<UL><LI><TT>elm</TT>\n" "<LI><TT>elm 1</TT>\n" "<LI><TT>-M /usr/local/man elm</TT>\n" "<LI><TT>/local/gcc/man/man1/gperf.1</TT>\n" "</UL>\n" "<ISINDEX>\n" "<P>\n" "This man2html converter was written by \n" "<A HREF=\"http://wsinwp01.win.tue.nl:1234/index.html\">" "Richard Verhoeven</A>\n" "</BODY></HTML>\n"); exit(0);}/* below this you should not change anything unless you know a lot** about this program or about troff.*/typedef struct STRDEF STRDEF;struct STRDEF { int nr,slen; char *st; STRDEF *next;};typedef struct INTDEF INTDEF;struct INTDEF { int nr; int val; int incr; INTDEF *next;};static char NEWLINE[2]="\n";static char idxlabel[6] = "ixAAA";#define INDEXFILE "/tmp/manindex.list"char *fname;FILE *idxfile;STRDEF *chardef, *strdef, *defdef;INTDEF *intdef;#define V(A,B) ((A)*256+(B))INTDEF standardint[] = { { V('n',' '), NROFF,0, NULL }, { V('t',' '), 1-NROFF,0, NULL }, { V('o',' '), 1,0, NULL }, { V('e',' '), 0,0, NULL }, { V('.','l'), 70,0,NULL }, { V('.','$'), 0,0, NULL }, { V('.','A'), NROFF,0, NULL }, { V('.','T'), 1-NROFF,0, NULL }, { V('.','V'), 1,0, NULL }, /* the me package tests for this */ { 0, 0, 0, NULL } };STRDEF standardstring[] = { { V('R',' '), 1, "®", NULL }, { V('l','q'), 2, "``", NULL }, { V('r','q'), 2, "''", NULL }, { 0, 0, NULL, NULL}};STRDEF standardchar[] = { { V('*','*'), 1, "*", NULL }, { V('*','A'), 1, "A", NULL }, { V('*','B'), 1, "B", NULL }, { V('*','C'), 2, "Xi", NULL }, { V('*','D'), 5, "Delta", NULL }, { V('*','E'), 1, "E", NULL }, { V('*','F'), 3, "Phi", NULL }, { V('*','G'), 5, "Gamma", NULL }, { V('*','H'), 5, "Theta", NULL }, { V('*','I'), 1, "I", NULL }, { V('*','K'), 1, "K", NULL }, { V('*','L'), 6, "Lambda", NULL }, { V('*','M'), 1, "M", NULL }, { V('*','N'), 1, "N", NULL }, { V('*','O'), 1, "O", NULL }, { V('*','P'), 2, "Pi", NULL }, { V('*','Q'), 3, "Psi", NULL }, { V('*','R'), 1, "P", NULL }, { V('*','S'), 5, "Sigma", NULL }, { V('*','T'), 1, "T", NULL }, { V('*','U'), 1, "Y", NULL }, { V('*','W'), 5, "Omega", NULL }, { V('*','X'), 1, "X", NULL }, { V('*','Y'), 1, "H", NULL }, { V('*','Z'), 1, "Z", NULL }, { V('*','a'), 5, "alpha", NULL }, { V('*','b'), 4, "beta", NULL }, { V('*','c'), 2, "xi", NULL }, { V('*','d'), 5, "delta", NULL }, { V('*','e'), 7, "epsilon", NULL }, { V('*','f'), 3, "phi", NULL }, { V('*','g'), 5, "gamma", NULL }, { V('*','h'), 5, "theta", NULL }, { V('*','i'), 4, "iota", NULL }, { V('*','k'), 5, "kappa", NULL }, { V('*','l'), 6, "lambda", NULL }, { V('*','m'), 1, "µ", NULL }, { V('*','n'), 2, "nu", NULL }, { V('*','o'), 1, "o", NULL }, { V('*','p'), 2, "pi", NULL }, { V('*','q'), 3, "psi", NULL }, { V('*','r'), 3, "rho", NULL }, { V('*','s'), 5, "sigma", NULL }, { V('*','t'), 3, "tau", NULL }, { V('*','u'), 7, "upsilon", NULL }, { V('*','w'), 5, "omega", NULL }, { V('*','x'), 3, "chi", NULL }, { V('*','y'), 3, "eta", NULL }, { V('*','z'), 4, "zeta", NULL }, { V('t','s'), 5, "sigma", NULL }, { V('+','-'), 1, "±", NULL }, { V('1','2'), 1, "½", NULL }, { V('1','4'), 1, "¼", NULL }, { V('3','4'), 1, "¾", NULL }, { V('F','i'), 3, "ffi", NULL }, { V('F','l'), 3, "ffl", NULL }, { V('a','a'), 1, "´", NULL }, { V('a','p'), 1, "~", NULL }, { V('b','r'), 1, "|", NULL }, { V('b','u'), 1, "*", NULL }, { V('b','v'), 1, "|", NULL }, { V('c','i'), 1, "o", NULL }, { V('c','o'), 1, "©", NULL }, { V('c','t'), 1, "¢", NULL }, { V('d','e'), 1, "°", NULL }, { V('d','g'), 1, "+", NULL }, { V('d','i'), 1, "÷", NULL }, { V('e','m'), 1, "-", NULL }, { V('e','m'), 3, "---", NULL }, { V('e','q'), 1, "=", NULL }, { V('e','s'), 1, "Ø", NULL }, { V('f','f'), 2, "ff", NULL }, { V('f','i'), 2, "fi", NULL }, { V('f','l'), 2, "fl", NULL }, { V('f','m'), 1, "´", NULL }, { V('g','a'), 1, "`", NULL }, { V('h','y'), 1, "-", NULL }, { V('l','c'), 2, "|¯", NULL }, { V('l','f'), 2, "|_", NULL }, { V('l','k'), 1, "<FONT SIZE=+2>{</FONT>", NULL }, { V('m','i'), 1, "-", NULL }, { V('m','u'), 1, "×", NULL }, { V('n','o'), 1, "¬", NULL }, { V('o','r'), 1, "|", NULL }, { V('p','l'), 1, "+", NULL }, { V('r','c'), 2, "¯|", NULL }, { V('r','f'), 2, "_|", NULL }, { V('r','g'), 1, "®", NULL }, { V('r','k'), 1, "<FONT SIZE=+2>}</FONT>", NULL }, { V('r','n'), 1, "¯", NULL }, { V('r','u'), 1, "_", NULL }, { V('s','c'), 1, "§", NULL }, { V('s','l'), 1, "/", NULL }, { V('s','q'), 2, "[]", NULL }, { V('u','l'), 1, "_", NULL }, { 0, 0, NULL, NULL }};/* default: print code */char eqndelimopen=0, eqndelimclose=0;char escapesym='\\', nobreaksym='\'', controlsym='.', fieldsym=0, padsym=0;char *buffer=NULL;int buffpos=0, buffmax=0;int scaninbuff=0;int itemdepth=0;int dl_set[20]= { 0 };int still_dd=0;int tabstops[20] = { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 };int maxtstop=12;int curpos=0;extern char *scan_troff(char *c, int san, char **result);static char **argument=NULL;static char charb[3];void print_sig(void){ char datbuf[500]; struct tm *timetm; time_t clock; datbuf[0]='\0';#ifdef TIMEFORMAT clock=time(NULL); timetm=gmtime(&clock); strftime(datbuf,500,TIMEFORMAT, timetm);#endif printf(signature, datbuf);}char *expand_char(int nr){ STRDEF *h; h=chardef; if (!nr) return NULL; while (h) if (h->nr==nr) { curpos+=h->slen; return h->st; } else h=h->next; charb[0]=nr/256; charb[1]=nr%256; charb[2]='\0'; curpos+=2; return charb;}char *expand_string(int nr){ STRDEF *h=strdef; if (!nr) return NULL; while (h) if (h->nr==nr) { curpos+=h->slen; return h->st; } else h=h->next; return NULL;}char outbuffer[1024];int obp=0;int no_newline_output=0;int newline_for_fun=0;int output_possible=0;int out_length=0;void add_links(char *c){ /* ** Add the links to the output. ** At the moment the following are recognized: ** ** name(*) -> ../man?/name.* ** method://string -> method://string ** www.host.name -> http://www.host.name ** ftp.host.name -> ftp://ftp.host.name ** name@host -> mailto:name@host ** <name.h> -> file:/usr/include/name.h (guess) ** ** Other possible links to add in the future: ** ** /dir/dir/file -> file:/dir/dir/file */ int i,j,nr; char *f, *g,*h; char *idtest[6]; /* url, mailto, www, ftp, manpage */ out_length+=strlen(c); /* search for (section) */ nr=0; idtest[0]=strstr(c+1,"://"); idtest[1]=strchr(c+1,'@'); idtest[2]=strstr(c,"www."); idtest[3]=strstr(c,"ftp."); idtest[4]=strchr(c+1,'('); idtest[5]=strstr(c+1,".h>"); for (i=0; i<6; i++) nr += (idtest[i]!=NULL); while (nr) { j=-1; for (i=0; i<6; i++) if (idtest[i] && (j<0 || idtest[i]<idtest[j])) j=i; switch (j) { case 5: /* <name.h> */ f=idtest[5]; h=f+2; g=f; while (g>c && g[-1]!=';') g--; if (g!=c) { char t; t=*g; *g='\0'; printf("%s",c); *g=t;*h='\0'; printf("<A HREF=\"file:/usr/include/%s\">%s</A>>", g,g); c=f+6; } else { f[5]='\0'; printf("%s",c); f[5]=';'; c=f+5; } break; case 4: /* manpage */ f=idtest[j]; /* check section */ g=strchr(f,')'); if (g && f-g<6 && (isalnum(f[-1]) || f[-1]=='>') && ((isdigit(f[1]) && f[1]!='0' && (f[2]==')' || (isalpha(f[2]) && f[3]==')') || f[2]=='X')) || (f[2]==')' && (f[1]=='n' || f[1]=='l')))) { /* this might be a link */ h=f-1; /* skip html makeup */ while (h>c && *h=='>') { while (h!=c && *h!='<') h--; if (h!=c) h--; } if (isalnum(*h)) { char t,sec,subsec, *e; e=h+1; sec=f[1]; subsec=f[2]; if ((subsec=='X' && f[3]!=')')|| subsec==')') subsec='\0'; while (h>c && (isalnum(h[-1]) || h[-1]=='_' || h[-1]=='-' || h[-1]=='.')) h--; t=*h; *h='\0'; printf("%s", c); *h=t; t=*e; *e='\0';#if LIRC_RELATIVE_PATH if (subsec) printf("<A HREF=\"../man%c/%s.%c%c\">%s</A>", sec, h, sec, tolower(subsec), h); else printf("<A HREF=\"../man%c/%s.%c\">%s</A>", sec, h, sec, h);#elif LIRC_ABSOLUTE_PATH if (subsec) printf("<A HREF=\"file:///usr/man/man%c/%s.%c%c\">%s</A>", sec, h, sec, tolower(subsec), h); else printf("<A HREF=\"file:///usr/man/man%c/%s.%c\">%s</A>", sec, h, sec, h);#else /* links to man pages make no sense for us */ printf("%s",h);#endif *e=t; c=e; } } *f='\0'; printf("%s", c); *f='('; idtest[4]=f-1; c=f; break; /* manpage */ case 3: /* ftp */ case 2: /* www */ g=f=idtest[j]; while (*g && (isalnum(*g) || *g=='_' || *g=='-' || *g=='+' || *g=='.')) g++; if (g[-1]=='.') g--; if (g-f>4) { char t; t=*f; *f='\0'; printf("%s",c); *f=t; t=*g;*g='\0'; printf("<A HREF=\"%s://%s\">%s</A>", (j==3?"ftp":"http"), f,f); *g=t; c=g; } else { f[3]='\0'; printf("%s",c); c=f+3; f[3]='.'; } break; case 1: /* mailto */ g=f=idtest[1]; while (g>c && (isalnum(g[-1]) || g[-1]=='_' || g[-1]=='-' || g[-1]=='+' || g[-1]=='.' || g[-1]=='%')) g--; h=f+1; while (*h && (isalnum(*h) || *h=='_' || *h=='-' || *h=='+' || *h=='.')) h++; if (*h=='.') h--; if (h-f>4 && f-g>1) { char t; t=*g; *g='\0'; printf("%s",c); *g=t;t=*h;*h='\0'; printf("<A HREF=\"mailto:%s\">%s</A>",g,g); *h=t; c=h; } else { *f='\0'; printf("%s",c); *f='@'; idtest[1]=c; c=f; } break; case 0: /* url */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -