Subject: Try out this MAN.C (man page viewer) via your web browser
From: [email-masked] (Joseph Banta)

12 Jun 1998 00:10:32 -0700
Message-ID: <01BD9527.B8C344F0.cygnus.gnu-win32@HERBY>
Mime-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
To: "[email-masked]'" <[email-masked]>

Compile the code below, and with the command 'man <program>', you
can view man pages with your web browser, 'less' or 'notepad'.  (depending
on how you set the MANHANDLER environment variable)  Read the header
below for more info, or hack into the code yourself.

-----cut here -----

/*
**  Title: man.c
**
**  Author: Joseph Banta, Perceptics Corp., Knoxville, TN, June 1998
**          [email-masked]
**
**  Usage: man [-m|--manonly|-i|--infoonly] <names...>
**
**  Prerequisites:
**   cygwinb19.dll
**   bash, tkinfo, wish, sed
**   groff (if you want to view man pages via less or notepad;
**          otherwise, set the environment variable MANHANDLER
**          to the complete path of your web browser
**          [i.e., 'c:\Progra~1\MSIE\iexplore.exe'])
**
**  Purpose:
**   This is a 'man' emulator written for win32, cygnus style.
**   It was originally based on 'man2html' by [email-masked],
**   but its functionality is extended a bit.  What it does is
**   search through the directories in the environment variables
**   INFOPATH and MANPATH for info and man pages, respectively,
**   and if an info page is found, 'tkinfo' is called, otherwise
**   the application named in the environment variable MANHANDLER
**   (by default, 'less') is called to view the man page.  If the
**   MANHANDLER application contains the string 'iexplore' or
**   'netscape', then this program converts the man page to html
**   format for the browser.  If the MANHANDLER application name
**   contains the string 'more' or 'less', the man page is piped
**   through groff to be viewed appropriately.  Otherwise (i.e.,
**   if MANHANDLER is defined as 'notepad'), the page is piped
**   through groff into plain text format.
*/

#include <stdio.h>
#include <ctype.h>
#include <dirent.h>
#include <unistd.h>

extern char* getenv(char*);
extern char* strdup(char*);
extern char* strchr(char*, char);

int in_tt = 0;
int next_line_dd = 0;
int need_undl = 0;
int got_regular_line = 0;
int need_re = 0;
int fill_mode = 1;
int current_BI = 0;
int skip_nl = 0;

typedef struct StringList {
  char *string;
  struct StringList *next;
} StringList, *StringList_ptr;

char   *get_token(char *, char *);
void   clean(char *);
void   un_bi(FILE *);
int    process_line_til_regular(FILE *, FILE *);
void   bol(FILE *);
void   eol(FILE *);
void   twoggle(char *, char *, char *, FILE *);
int    process_line(FILE *, FILE *);
int    nullString(char*);
void   htmlTarget(char *, char *, char *, char *);
void   formatedTextTarget(char *, char *, char *);
void   textTarget(char *, char *, char *, char *, char *);
void   checkForCalls(char*[]);
void   usage(char*);
StringList_ptr initializedStringList_ptr(char *);

int main( int argc, char **argv )
{
  DIR *dir, *subDir;
  StringList_ptr manRequest=NULL, thisRequest;
  struct dirent *entry, *subEntry;

  char line[1000], thisPath[1000], target[1000],
       *util, *util1, **manDir, **infoDir,
       *systemDrive,
       *baseDir,
       *manHandler,
       *manPath,
       *infoPath,
       *tempDir;
  int i, j, k, numPaths, numInfos, mode=0;

  if (argc == 1)
    usage(argv[0]);

  if(nullString(systemDrive = getenv("SYSTEMDRIVE")))
    systemDrive = strdup("C:\\");

  if(nullString(baseDir = getenv("PERCEPTICS")))
    if(nullString(baseDir = getenv("CYGROOT")))
      baseDir = strdup("/usr/local");
  for(i=0; baseDir[i]!='\0'; i++)
    if(baseDir[i] == '\\')
      baseDir[i] = '/';

  if(nullString(manPath = getenv("MANPATH"))) {
    sprintf(line, "%s/man", baseDir);
    manPath = strdup(line); }

  if(nullString(infoPath = getenv("INFOPATH"))) {
    sprintf(line, "%s/info", baseDir);
    infoPath = strdup(line); }

  if(nullString(tempDir = getenv("TEMPDIR"))) {
    sprintf(line, "%s/temp", systemDrive);
    tempDir = strdup(line); }

  if(nullString(manHandler = getenv("MANHANDLER")))
    manHandler = strdup("less");

  /*  Separate out the components of manPath into manDir[]  */
  for(numPaths=1, util=manPath; util=strchr(util, ':'); numPaths++, util++){
    if(util == NULL)
      break; }
  manDir = (char**) malloc(numPaths * sizeof(char*));
  for(i=0, util=manPath; i<numPaths; i++, util=util1+1) {
    util1 = strchr(util, ':');
    if(util1 == NULL)
      util1 = util + strlen(util);
    manDir[i] = (char*) malloc(util1 - util + 1);
    for(j=0; j<util1-util; j++)
      manDir[i][j] = util[j];
    manDir[i][j] = '\0'; }

  /*  Separate out the components of infoPath into infoDir[]  */
  for(numInfos=1, util=infoPath; util=strchr(util, ':'); numInfos++, util++){
    if(util == NULL)
      break; }
  infoDir = (char**) malloc(numInfos * sizeof(char*));
  for(i=0, util=infoPath; i<numInfos; i++, util=util1+1) {
    util1 = strchr(util, ':');
    if(util1 == NULL)
      util1 = util + strlen(util);
    infoDir[i] = (char*) malloc(util1 - util + 1);
    for(j=0; j<util1-util; j++)
      infoDir[i][j] = util[j];
    infoDir[i][j] = '\0'; }

  /* Parse the command line */
  for(i=1; i<argc; i++) {
    if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
      usage(argv[0]);
    else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--manonly"))
      mode = 1; /* Show only 'man' pages */
    else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--infoonly"))
      mode = 2; /* Show only 'info' pages */
    else
      thisRequest = ((manRequest == NULL) ? manRequest : thisRequest->next)
                  = initializedStringList_ptr(argv[i]); }

  /* Iterate through each requested name... */
  for(thisRequest=manRequest; thisRequest!=NULL; thisRequest=thisRequest->next){
    target[0]='\0';

    /* First, look for 'info' pages, unless the user has specified only  **
    ** to search 'man' pages with the option '-m'.                       */
    if(mode != 1) {
      sprintf(thisPath, "%s.info", thisRequest->string);
      for(j=0; j<numInfos; j++) {

        /* Look in each directory in infoPath to see if we can find   **
        ** a file that matches 'name.info' where name is the argument */
        if((dir = opendir(infoDir[j])) == NULL)
          continue;
        while((entry = readdir(dir)) != NULL) {
          if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
            continue;
          if(!strcmp(entry->d_name, thisPath)) {
            sprintf(target, "%s", infoDir[j]);
            break; } } }

      /* If an info page was found, display the page, then go on to the  **
      ** next request.                                                   */
      if(target[0] != '\0') {
        sprintf(line, "tkinfo -dir %s %s &", target, thisRequest->string);
        system(line);
        continue; } }

    /* Look for 'man' pages, unless the user has specified only to       **
    ** search 'info' pages with the option '-i'.                         */
    if(mode != 2) {
      for(j=0; j<numPaths; j++) {

        /* Look in each directory in manPath to see if we can find **
        ** a file that matches 'name.*' where name is the argument **
        ** and * could be anything                                 */
        if((dir = opendir(manDir[j])) == NULL)
          continue;
        while((entry = readdir(dir)) != NULL) {
          if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
            continue;
          sprintf(thisPath, "%s/%s", manDir[j], entry->d_name);
          if((subDir = opendir(thisPath)) == NULL)
            continue;
          while((subEntry = readdir(subDir)) != NULL) {
            if(!strcmp(subEntry->d_name, ".") || !strcmp(subEntry->d_name, ".."))
              continue;
            if(!strncmp(subEntry->d_name, thisRequest->string, (k=strlen(thisRequest->string))) &&
               (subEntry->d_name[k] == '.')) {
              sprintf(target, "%s/%s", thisPath, subEntry->d_name);
              break; } }
          if(target[0] != '\0')
            break; } } }

    if(target[0] == '\0') {
      fprintf(stderr, "No manual entry found for '%s'\n", thisRequest->string);
      continue; }

    /*  If the manHandler app name contains the string 'netscape'  **
    **  or 'iexplore', format the man page as HTML                 */
    if(strstr(manHandler, "netscape") || strstr(manHandler, "iexplore"))
      htmlTarget(thisRequest->string, target, tempDir, manHandler);

    /*  If the manHandler app name contains the string 'more'      **
    **  or 'less', try to format the man page with groff           */
    else if(strstr(manHandler, "more") || strstr(manHandler, "less"))
      formatedTextTarget(target, manHandler, baseDir);

    /*  Otherwise, try to remove all the formatting with groff     */
    else
      textTarget(target, manHandler, baseDir, tempDir, thisRequest->string); }

  return 0;
}

char *
get_token(char *inp, char *buf)
{
  char *obuf = buf;
  int quoted = 0;
  /* skip whitespace */
  while (*inp && isspace(*inp))
    inp++;
  if (*inp == 0)
    return 0;

  while (*inp)
  {
    switch (*inp)
    {
    case '"':
      quoted = 1-quoted;
      break;
    case '\\':
      *buf++ = *inp;
      *buf++ = *++inp;
      break;
    default:
      if (isspace(*inp) && !quoted)
      {
        *buf = 0;
        return inp;
      }
      *buf++ = *inp;
      break;
    }
    inp++;
  }
  *buf = 0;
  return inp;
}

void
clean(char *cp)
{
  char foo[1000];
  char *rp = foo;
  char *ocp = cp;
  if (strncmp(cp, ".if t ", 6) == 0)
    cp += 6;
  while (*cp)
  {
    switch (*cp)
    {
    case '\\':
      cp++;
      switch (*cp)
      {
      case 'E':
      case 'F':
      case 'g':
      case 'b':
      case 'r':
      case 'B':
        *rp++ = '\\';
        *rp++ = *cp++;
        break;
      case '/':
      case '-':
      case '\\':
      case '+':
      case '.':
      case 10:
      case 0:
      case ' ':
      case '=':
      case '\'':
      case '`':
      case '[':
      case ']':
      case ':':
      case '}':
      case '{':
        *rp++ = *cp++;
        break;
      case '|':
      case '^':
      case '"':
      case 'd':
      case 'u':
      case 'n':
      case '&':
      case 'w':
      case '%':
      case 'v':
      case 'k':
        cp++;
        break;
      case 't':
        *rp++ = ' ';
        cp++;
        break;
      case '0':
        *rp++ = ' ';
        cp++;
        break;
      case 'c':
        if (cp[1] == '\n')
        {
          skip_nl = 1;
          cp++;
        }
        cp++;
        break;
      case 'e':
        *rp++ = '\\';
        cp++;
        break;
      case 's':
        cp++;
        cp++;
        while (isdigit(*cp))
          cp++;
        break;
      case 'f':
        if (current_BI)
        {
          *rp++ = '<';
          *rp++ = '/';
          *rp++ = current_BI;
          *rp++ = '>';
          current_BI = 0;
        }
        if (in_tt)
        {
          strcpy(rp, "</tt>");
          rp += 5;
          in_tt = 0;
        }
        switch (*++cp)
        {
        case '(':
          if (cp[1] == 'C' && cp[2] == 'W')
          {
            strcpy(rp, "<tt>");
            rp += 4;
            in_tt = 1;
            cp += 2;
          }
          else
            fprintf(stderr, "unknown font %.3s\n", cp);
          break;
        case 'B':
          current_BI = 'b';
          *rp++ = '<';
          *rp++ = 'b';
          *rp++ = '>';
          break;
        case 'R':
        case 'P':
          break;
        case 'I':
          current_BI = 'i';
          *rp++ = '<';
          *rp++ = 'i';
          *rp++ = '>';
          break;
        }
        cp++;
        break;
      case '*':
        cp++;
        if (cp[0] == '(')
        {
          cp++;
          if (cp[0] == 'l' && cp[1] == 'q')
            *rp++ = '`';
          else if (cp[0] == 'r' && cp[1] == 'q')
            *rp++ = '\'';
          else
          {
            sprintf(rp, "[%.2s]", cp);
            rp += 4;
          }
          cp += 2;
        }
        else if (cp[0] == 'r')
        {
          cp++;
          strcpy(rp, "RCS");
          rp += 3;
        }
        else
        {
          sprintf(rp, "[%c]", *cp);
          rp += 3;
        }
        break;
      case '(':
        if (cp[1] == 'c' && cp[2] == 'o')
          *rp++ = 0xa9;
        else if (cp[1] == 'b' && cp[2] == 'v')
          *rp++ = '|';
        else if (cp[1] == 'e' && cp[2] == 'm')
          *rp++ = ' ';
        else if (cp[1] == '+' && cp[2] == '-')
          *rp++ = 0xb1;
        else if (cp[1] == 't' && cp[2] == 'i')
          *rp++ = '~';
        else if (cp[1] == 't' && cp[2] == 's')
          *rp++ = '"';
        else if (cp[1] == 'p' && cp[2] == 'l')
          *rp++ = '+';
        else if (cp[1] == 'm' && cp[2] == 'i')
          *rp++ = '-';
        else if (cp[1] == 'f' && cp[2] == 'm')
          *rp++ = '\'';
        else if (cp[1] == 'm' && cp[2] == 'u')
          *rp++ = 'x';
        else if (cp[1] == 'b' && cp[2] == 'u')
        {
          strcpy(rp, "<li>");
          rp += 4;
        }
        else if (cp[1] == '>' && cp[2] == '=')
        {
          *rp++ = '>';
          *rp++ = '=';
        }
        else if (cp[1] == '*' && cp[2] == '*')
        {
          *rp++ = '*';
          *rp++ = '*';
        }
        else
          fprintf(stderr, "unknown meta-character (%c%c\n", cp[1], cp[2]);
        cp += 3;
        break;
      default:
        fprintf(stderr, "unknown escape \\%c (%d)\n", *cp, *cp);
        break;
      }
      break;
    case '&':
      *rp++ = '&';
      *rp++ = 'a';
      *rp++ = 'm';
      *rp++ = 'p';
      *rp++ = ';';
      cp++;
      break;
    case '<':
      *rp++ = '&';
      *rp++ = 'l';
      *rp++ = 't';
      *rp++ = ';';
      cp++;
      break;
    case '>':
      *rp++ = '&';
      *rp++ = 'g';
      *rp++ = 't';
      *rp++ = ';';
      cp++;
      break;
    default:
      *rp++ = *cp++;
      break;
    }
  }
  *rp = 0;
  strcpy(ocp, foo);
}

void un_bi(FILE *outFile)
{
  if (current_BI)
  {
    fprintf(outFile, "</%c>", current_BI);
    current_BI = 0;
  }
}

int
process_line_til_regular(FILE *inFile, FILE *outFile)
{
  got_regular_line = 0;
  while (!got_regular_line)
    process_line(inFile, outFile);
}

void
bol(FILE *outFile)
{
  got_regular_line = 1;
  if (next_line_dd)
    fprintf(outFile, "<dd>");
  next_line_dd = 0;
}

void
eol(FILE *outFile)
{
  if (!fill_mode)
    fprintf(outFile, "<br>\n");
}

void
twoggle(char *a, char *b, char *l, FILE *outFile)
{
  int first = 1;
  char *c;
  char buf[1000];
  bol(outFile);
  while ((l = get_token(l, buf)))
  {
    clean(buf);
    c = first ? a : b;
    if (c)
      fprintf(outFile, "<%s>%s</%s>", c, buf, c);
    else
      fprintf(outFile, "%s", buf);
    if (a && b && strcmp(a, b) == 0) {
      fputc(' ', outFile); }
    first = 1-first;
  }
  un_bi(outFile);
  if (!skip_nl)
    fprintf(outFile, "\n");
  eol(outFile);
  got_regular_line = 1;
}

int
process_line(FILE *inFile, FILE *outFile)
{
  char buf[1000], cmd[10], b1[1000];
  char token[1000];
  if (fgets(buf, 999, inFile) == 0)
    return 0;

  skip_nl = 0;
  if (buf[0] != '.')
  {
    if (strncmp(buf, "'\\\"", 3) == 0)
      return 1;
    clean(buf);
    bol(outFile);
    fprintf(outFile, "\n%s\n", buf);
    if (buf[0] == 0 || buf[0] == '\n')
      fprintf(outFile, "<p>\n");
    eol(outFile);
    return 1;
  }

  if (sscanf(buf, "%s %[^\n]", cmd, buf) == 1)
    buf[0] = 0;
  if (strcmp(cmd, "..") == 0)
  {
  }
  else if (strcmp(cmd, ".B") == 0)
  {
    if (buf[0])
    {
      twoggle("b", "b", buf, outFile);
    }
    else
    {
      fprintf(outFile, "<b>\n");
      process_line_til_regular(inFile, outFile);
      fprintf(outFile, "</b>\n");
    }
  }
  else if (strcmp(cmd, ".I") == 0)
  {
    if (buf[0])
    {
      twoggle("i", "i", buf, outFile);
    }
    else
    {
      fprintf(outFile, "<i>\n");
      process_line_til_regular(inFile, outFile);
      fprintf(outFile, "</i>\n");
    }
  }
  else if (strcmp(cmd, ".BI") == 0)
  {
    twoggle("b", "i", buf, outFile);
  }
  else if (strcmp(cmd, ".IB") == 0)
  {
    twoggle("i", "b", buf, outFile);
  }
  else if (strcmp(cmd, ".BR") == 0)
  {
    twoggle("b", 0, buf, outFile);
  }
  else if (strcmp(cmd, ".RB") == 0)
  {
    twoggle(0, "b", buf, outFile);
  }
  else if (strcmp(cmd, ".IR") == 0)
  {
    twoggle("i", 0, buf, outFile);
  }
  else if (strcmp(cmd, ".RI") == 0)
  {
    twoggle(0, "i", buf, outFile);
  }
  else if (strcmp(cmd, ".nf") == 0)
  {
    if (fill_mode)
      fprintf(outFile, "<pre>\n");
    fill_mode = 0;
  }
  else if (strcmp(cmd, ".fi") == 0)
  {
    if (!fill_mode)
      fprintf(outFile, "</pre>\n");
    fill_mode = 1;
  }
  else if (strcmp(cmd, ".br") == 0
           || strcmp(cmd, ".Sp") == 0
           || strcmp(cmd, ".ti") == 0)
  {
    if (need_undl)
    {
      need_undl = 0;
      fprintf(outFile, "</dl>\n");
    }
    fprintf(outFile, "<br>\n");
  }
  else if (strcmp(cmd, ".LP") == 0
           || strcmp(cmd, ".PP") == 0
           || strcmp(cmd, ".sp") == 0
           || strcmp(cmd, ".P") == 0)
  {
    if (need_undl)
    {
      need_undl = 0;
      fprintf(outFile, "</dl>\n");
    }
    fprintf(outFile, "\n<p>\n");
  }
  else if (strcmp(cmd, ".RS") == 0)
  {
    fprintf(outFile, "<ul>\n");
    need_re ++;
  }
  else if (strcmp(cmd, ".RE") == 0)
  {
    if (need_re)
    {
      fprintf(outFile, "</ul>\n");
      need_re --;
    }
  }
  else if (strcmp(cmd, ".SH") == 0
           || strcmp(cmd, ".SS") == 0)
  {
    char *cp = buf;
    int got_token = 0;
    while (need_re)
    {
      fprintf(outFile, "</ul>\n");
      need_re--;
    }
    if (need_undl)
    {
      fprintf(outFile, "</dl>\n");
      need_undl = 0;
    }
    fprintf(outFile, "\n</ul><H2>\n");
    while (cp = get_token(cp, token))
    {
      got_token = 1;
      clean(token);
      fprintf(outFile, "%s ", token);
    }
    if (!got_token)
    {
      if (fgets(buf, 999, inFile) == 0)
        return 0;
      fprintf(outFile, "%s\n", buf);
    }
    fprintf(outFile, "</H2><ul>\n\n");
    un_bi(outFile);
    got_regular_line = 1;
    if (!fill_mode)
      fprintf(outFile, "</pre>\n");
    fill_mode = 1;
  }
  else if (strcmp(cmd, ".SM") == 0)
  {
    if (buf[0])
    {
      bol(outFile);
      clean(buf);
      fprintf(outFile, "<code>%s</code>\n", buf);
      eol(outFile);
    }
    else
    {
      fprintf(outFile, "<code>\n");
      process_line_til_regular(inFile, outFile);
      fprintf(outFile, "</code>\n");
    }
  }
  else if (strcmp(cmd, ".TH") == 0)
  {
    int all_upper = 1, i;
    get_token(buf, buf);
    for (i=0; buf[i]; i++)
      if (islower(buf[i]))
        all_upper = 0;
    if (all_upper)
      for (i=0; buf[i]; i++)
        if (isupper(buf[i]))
          buf[i] = tolower(buf[i]);
    fprintf(outFile, "<!--#exec cmd=\"header %s\" -->\n", buf);
    fprintf(outFile, "<ul>\n");
  }
  else if (strcmp(cmd, ".TP") == 0
           || strcmp(cmd, ".Tp") == 0)
  {
    if (!need_undl)
    {
      fprintf(outFile, "<p><dl compact>\n");
      need_undl = 1;
    }
    fprintf(outFile, "<dt>\n");
    next_line_dd = 0;
    process_line_til_regular(inFile, outFile);
    next_line_dd = 1;
  }
  else if (strcmp(cmd, ".IP") == 0)
  {
    if (!need_undl)
    {
      fprintf(outFile, "<p><dl compact>\n");
      need_undl = 1;
    }
    get_token(buf, buf);
    clean(buf);
    fprintf(outFile, "<dt>%s\n", buf);
    next_line_dd = 1;
  }
  else if (strcmp(cmd, ".TQ") == 0)
  {
    fprintf(outFile, "<dt>\n");
    next_line_dd = 0;
    process_line_til_regular(inFile, outFile);
    next_line_dd = 1;
  }
  else if (strcmp(cmd, ".FN") == 0)
  {
    bol(outFile);
    get_token(buf, buf);
    fprintf(outFile, "<code>%s</code>\n", buf);
    got_regular_line = 1;
    eol(outFile);
  }
  /* Tcl macros */
  else if (strcmp(cmd, ".AP") == 0)
  {
    char *cp = buf;
    cp = get_token(cp, token);
    fprintf(outFile, "<p>%s\n", token);
    cp = get_token(cp, token);
    fprintf(outFile, " <b>%s</b>\n", token);
    cp = get_token(cp, token);
    fprintf(outFile, " (<i>%s</i>) -\n", token);
  }
  else if (strcmp(cmd, ".DS") == 0)
  {
    fprintf(outFile, "<pre>\n");
  }
  else if (strcmp(cmd, ".DE") == 0)
  {
    fprintf(outFile, "</pre>\n");
  }
  /* end of Tcl macros */
  else if (strcmp(cmd, ".\"") == 0)
  {
  }
  else if (strcmp(cmd, ".de") == 0)
  {
    do {
      if (fgets(buf, 999, inFile) == 0)
        return 0;
    } while (buf[0] != '.' || buf[1] != '.');
  }

  return 1;
}

int nullString(char *name) {
  if(name == NULL)
    return 1;
  else if(name[0] == '\0')
    return 1;
  return 0; }

void htmlTarget(char *name, char *target, char *tempDir, char *manHandler) {
  FILE *inFile, *outFile;
  char htmlFile[1000], shellVersion[1000], command[1000];
  int i, j, k;

  if((inFile = fopen(target, "rb")) == NULL) {
    fprintf(stderr, "Error: can't open '%s' for reading.\n", target);
    return; }

  sprintf(htmlFile, "%s\\%s.html", tempDir, name);
  if((outFile = fopen(htmlFile, "wb")) == NULL) {
    fprintf(stderr, "Error: can't write to temporary html file.\n");
    return; }

  while (process_line(inFile, outFile)) { }
  fprintf(outFile, "</ul>\n<!--#exec cmd=\"trailer\" -->\n");

  fclose(outFile);
  fclose(inFile);

  /*  find all the back-slashes in 'htmlFile' and replace each with 2 */
  for(j=k=0; htmlFile[j]!='\0'; j++, k++) {
    if(htmlFile[j] == '\\')
      shellVersion[k++] = '\\';
    shellVersion[k] = htmlFile[j]; }
  shellVersion[k] = '\0';
  sprintf(command, "%s %s; rm %s &", manHandler, shellVersion, shellVersion);
  system(command);
}

void   formatedTextTarget(char *target, char *manHandler, char *baseDir) {
  char command[1000],
       *calls[] = { "groff", manHandler, NULL };

  checkForCalls(calls);
  sprintf(command, "groff -man -Tascii -M%s/share/groff/tmac -F%s/share/groff/font %s | %s", baseDir, baseDir, target, manHandler);
  system(command);
}

void   textTarget(char *target, char *manHandler, char *baseDir,
                  char *tempDir, char *name) {
  char command[1000],
       *calls[] = { "groff", "sed", manHandler, NULL };

  checkForCalls(calls);
  sprintf(command, "groff -man -Tascii -M%s/share/groff/tmac -F%s/share/groff/font %s | sed -e 's/_//g' | sed -e 's/.//g' > \"%s/%s.man\"; %s \"%s/%s.man\"; sleep 2; rm \"%s/%s.man\" &",
          baseDir, baseDir, target, tempDir, name,
          manHandler, tempDir, name, tempDir, name);
  system(command);
}

void checkForCalls(char *calls[]) {
  int i;

  /* If anybody can figure out how to check to see that a string **
  ** actually calls a command, put the code here.                */
/*
  for(i=0; calls[i]!=NULL; i++)
*/
}

StringList_ptr initializedStringList_ptr(char *string){
  StringList_ptr list_ptr = (StringList_ptr) malloc (sizeof(StringList));

  list_ptr->string = (char*) malloc ((strlen(string)+1)*sizeof(char));

  strcpy(list_ptr->string, string);
  list_ptr->next = NULL;

  return list_ptr;
}

void   usage(char *commandName) {
  printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
         "\n  Usage:  ", commandName, " [-m|--manonly|-i|--infoonly] <names...>\n\n",
         "  Prerequisites:\n",
         "   cygwinb19.dll\n",
         "   bash, sed\n",
         "   groff (if you want to view man pages via less or notepad;\n",
         "          otherwise, set the environment variable MANHANDLER\n",
         "          to the complete path of your web browser\n",
         "          [i.e., 'c:\\Progra~1\\MSIE\\iexplore.exe'])\n\n",
         "  Purpose:\n",
         "   This is a 'man' emulator written for win32, cygnus style.\n",
         "   It was originally based on 'man2html' by [email-masked],\n",
         "   but its functionality is extended a bit.  What it does is\n",
         "   search through the directories in the environment variables\n",
         "   INFOPATH and MANPATH for info and man pages, respectively,\n",
         "   and if an info page is found, 'tkinfo' is called, otherwise\n",
         "   the application named in the environment variable MANHANDLER\n",
         "   (by default, 'less') is called to view the man page.  If the\n",
         "   MANHANDLER application contains the string 'iexplore' or\n",
         "   'netscape', then this program converts the man page to html\n",
         "   format for the browser.  If the MANHANDLER application name\n",
         "   contains the string 'more' or 'less', the man page is piped\n",
         "   through groff to be viewed appropriately.  Otherwise (i.e.,\n",
         "   if MANHANDLER is defined as 'notepad'), the page is piped\n",
         "   through groff into plain text format.\n\n",
         "  Author: Joseph Banta, Perceptics Corp., Knoxville, TN, June 1998\n",
         "          [email-masked]\n\n");
  exit(0);
}

-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".