/************************************************************************ * Description: Re-format man pages into html documents. * Author: M.J. Leslie * Date: 22-Dec-94 * Syntax: * mjl_man command [section] * Testing: Tested on: * man stat * man seekdir * * Bugs: Have a look at 'man seekdir' in the 'See Also' section * there is a hyphanated word. This is not handled correctly. * Do you fancy fixing it Vinny? * * History: * Ver Date Comments * --- ---- -------- * 2.1 12-Mar-96 Background and buttons at the botton added. * 2.0 16-Apr-95 Major rewrite because I keep finding bugs! * * 1.5 26-Mar-95 Bug with < and > characters fixed. * 1.4 12-Feb-95 Bug in build_xref fixed. * 1.3 14-Jan-95 Entries in the 'See Also' section are now * links to other pages. * 1.2 31-Dec-94 man section now provided on the command line. * 1.1 31-Dec-94 Now specifies man section 2 - System calls * 1.0 22-Dec-94 Initial release. * ************************************************************************/ #include #include #include /* strncmp */ #define AUTHOR "M.J. Leslie" #define VERSION "2.0" #define MAX_LINE 200 #define BACKSPACE 8 /* ASCII value of backspace */ #define FALSE 0 #define TRUE 1 /************************************************************************/ void parm_error(char *); /* Execute if no parms provided.*/ void man_html(char, char *, char *); /* Read the man page. */ void links(char *); /* Look for 'See Also' links */ void build_links(const char *line); /* Build links. */ void build_href(char *word); void headings(char *); void uppercase(char *record); /* convert a line to uppercase */ void highlight(char *record); /* Remove highlighting */ void lt_gt(char *record); /* Conv < and > to HTML. */ void clear(char *record); /* Conv < and > to HTML. */ /************************************************************************/ main(int argc, char *argv[]) { char section=' '; /* Assume no section will be * supplied */ if ( argc < 2 ) /* Check we have a parm */ { parm_error(argv[0]); exit(0); } if (argc > 2 ) /* Man section has been supplied. */ { section = *argv[2]; } man_html(section, argv[1], argv[0]); /* Read the man page and convert it * into HTML. */ } /************************************************************************/ void parm_error(char * prog_name) { puts("Content-type: text/html"); puts(""); /* BLANK LINE IS REQUIRED */ printf("

%s failure

\n", prog_name); printf("%s requires ONE parameter\n", prog_name); } /************************************************************************/ void man_html(char section, char *man_page, char *prog_name) { FILE *fp1; char record[MAX_LINE]; /* line from the man page */ char man[80]="/usr/bin/man * "; /* Location of the man command. */ /************************************************** * * Linux - /usr/bin/man * SunOS 4.1.3 - /usr/ucb/man * Solaris - /usr/bin/man * **************************************************/ /* Create a path of libraries for * 'man' to search. */ putenv("MANPATH=/usr/local/man:/usr/man/preformat:/usr/man"); /* Start building the HTML document */ puts("Content-type: text/html"); puts(""); /* BLANK LINE IS REQUIRED */ /* Build some more HTML */ printf("%s\n", man_page); puts(""); puts("
"); puts("
");

                    /* build the man command    */
   man[13] = section;
   strcat(man, " ");
   strcat(man, man_page);

                    /* Issue the man command and reformat
                     * the O/P          */
   fp1 = popen (man ,"r");

                    /* Read a record        */
   while (fgets(record, sizeof(record),fp1) != NULL)
      {

      highlight(record);        /* Remove highlighting.     */

      lt_gt(record);            /* convert < and > to HTML  */

                    /* Look for section headings
                     * and wrap them in HTML    */
      headings(record);

      links(record);            /* Try to build links to other
                     * man pages.           */

      clear(record);
      }

   pclose(fp1);

                    /* Put the tail onto the document */
   puts("
"); puts("

"); puts("


"); puts("

"); puts("

"); puts(""); puts(""); puts(""); puts(""); puts("
"); puts("Top"); puts(""); puts("Master Index"); puts(""); puts("Keywords"); puts(""); puts("Functions"); puts("
"); puts("
"); puts("

"); puts("


"); printf("\nThis manual page was brought to you "); printf("by %s V-%s\n", prog_name, VERSION); } /************************************************************************/ void highlight(char *record) { char op_record[MAX_LINE]; int counter=0, counter1=0; /* REMOVE THE HIGHLIGHTING * AND UNDERSCORES * If the next char is a BACKSPACE, * throw way the current char and * the backspace. */ do { if ( record[counter+1] != BACKSPACE) { op_record[counter1++] = record[counter]; } else { counter++; } } while ( counter++ < strlen(record) ); strcpy (record, op_record); } /************************************************************************/ void lt_gt(char *record) { char op_record[MAX_LINE]; int counter=0, counter1=0; /* Convert < and > into HTML */ do { switch (record[counter]) { case '<': op_record[counter1++] = '&'; op_record[counter1++] = 'l'; op_record[counter1++] = 't'; op_record[counter1++] = ';'; break; case '>': op_record[counter1++] = '&'; op_record[counter1++] = 'g'; op_record[counter1++] = 't'; op_record[counter1++] = ';'; break; default: op_record[counter1++] = record[counter]; break; } } while ( counter++ < strlen(record) ); strcpy(record, op_record); } /************************************************************************/ void headings(char *record) { char op_record[MAX_LINE]; /* If the first character is * NOT blank, its probably * a heading, so wrap it in HTML*/ if ( isalnum(record[0])) { strcpy(op_record, "

"); strcat(op_record, record ); strcat(op_record, "

"); strcpy(record, op_record); } } /************************************************************************/ void links(char *ip_record) { char record[MAX_LINE]; int pos; static int see_also=FALSE; strcpy(record, ip_record); if ( see_also && record[0] == 0x0a) { see_also=FALSE; puts("
");
      }
                    /* Have we passed 'See Also'?   */

   if (see_also) 
      {                 /* Y. Build links.      */
      build_links(record); 
      }
   else                 /* N. Is 'See Also' on this 
                     * line.            */
      {
      uppercase(record);        /* Convert it to UPPERCASE. */
                    /* Does it contain 'SEE ALSO'?  */
      if (strstr(record,"SEE ALSO"))
         {
                    /* Yes.             */
         puts("
"); puts("
"); printf("%s", ip_record); puts("

"); see_also=TRUE; } else { printf("%s", ip_record); } } } /************************************************************************/ void uppercase(char *record) { int step=strlen(record); while(step) { record[step]=toupper(record[step]); step--; } } /************************************************************************/ void build_links(const char *line) { char *word; char work_line[MAX_LINE]=" "; int counter1=0; int counter2=0; /* Test to see if we have a line which * references other functions. */ /* Does it have (2) or (3) * in it? */ if ( !((strstr(line, "(2)") != NULL) || (strstr(line, "(3)") != NULL)) ) return; /* Yes. Carry on. */ strcpy(work_line, line); /* Usually a reference is directly followed by the * man section in brackets 'getuid(2)' but some have * a space 'getuid (2)'. Attempt to remove the space. */ do { if (!(line[counter1] == ' ' && line[counter1+1] == '(')) { work_line[counter2++] = line[counter1]; } } while(counter1++ < strlen(line)); /* Extract first string */ word=strtok(work_line, "\n\t, "); build_href(word); /* Build href */ /* Extract remaining * strings */ while ( (word=strtok(NULL, "\n\t, ")) != NULL) { build_href(word); /* Build href */ } } /************************************************************************/ void build_href(char *word) { char *pos; /* Check out the word. Make sure it * has (n) at the end. This is because * some references are hyphanated. */ if (word[strlen(word)-1] != ')') { return; printf("%s ", word); } /* word will look like - getuid(2) */ /* Change the ( to + */ pos = strchr(word, '('); *pos = '+'; /* Change the ) to > */ pos = strchr(word, ')'); *pos = '>'; /* Word now looks like - getuid+2> */ /* The URL */ printf (" to 'a' */ pos = strchr(word, '>'); *pos = 'a'; /* Word is now - getuid, \n", word); } /************************************************************************/ void clear(char *record) { int counter1=0; for (counter1=0;counter1