
/***************************************************************************
*
*        Programm:   Man
*        Modul:      man.c
*        Funktion:   unix man clone
*
*        Datum:            09.09.90
*        letzte Änderung:  12.09.90
*
***************************************************************************/

/*
 *       unix man(1) clone
 *       john aycock, 1990
 *
 *       V1.1  ARP version by Götz Müller
 */

#include <ctype.h>
#include <string.h>

#define DFLT_PAGER      "more"
#define DFLT_MANDIR     "man:"
#define DFLT_MANIDX     "man:.manidx"
#define MAXIDXLINE      512
#define MAXALIASES      8
#define MAXBUFFER       254
#define LINELENGTH      77L
#define VERSION         "1.1"

typedef char bool;

struct line {
   char *aliases[MAXALIASES];
   char *desc, *fname;
};

extern void exit(int);

bool endoffile = FALSE;

/***************************************************************************
*
*     wildcard
*
*     Fkt:     vergleicht String mit Muster
*
*
*     Input:   s :   Zeiger auf String
*              wc :  Zeiger auf Muster
*
*     Output:  TRUE  String wird von Muster überdeckt
*
***************************************************************************/

bool
wildcard(char *s, char *wc)

{
   char buffer[MAXBUFFER+1];

   PreParse(wc,buffer);
   return((bool)PatternMatch(buffer,s));
}

/***************************************************************************
*
*     getline
*
*     Fkt:     liest eine Zeile in die Zeilenstruktur ein
*
*
*     Input:   fh :  Zeiger auf FileHandle
*
*     Output:  Zeiger auf Zeilenstruktur
*
***************************************************************************/

struct line *
getline(BPTR fh)

{
   short i;
   char *p;
   long read_len;
   static char buffer[MAXIDXLINE];
   static struct line l;

   while (1) {
      if (!(read_len = Read(fh,buffer, MAXIDXLINE-1))) {
         endoffile = TRUE;
         return(NULL);
      }
      buffer[read_len] = '\0';
      if (!(p = strchr(buffer,(int)'\n')))
         return(NULL);
      *(p+1) = '\0';
      Seek(fh,-(buffer + read_len - p - 1L),OFFSET_CURRENT);
      if (*(buffer + strlen(buffer) - 1) != '\n')
         return(NULL);
      for (p = buffer; *p != '\n' && isspace((int)*p); p++)
         ;
      if (*p != '\n' && *p != '#')
         break;
   }
   for (i = 0; i < MAXALIASES; i++)
      l.aliases[i] = NULL;
   l.desc = l.fname = NULL;
   for (i = 0; i < MAXALIASES; i++) {
      l.aliases[i] = p;
      while (*p != '\n' && *p != '|' && *p != ':')
         p++;
      if (*p == '\n')
         return(NULL);
      else
         if (*p == ':') {
            *p++ = '\0';
            break;
         }
      *p++ = '\0';
   }
   l.desc = p;
   while (*p != '\n' && *p != ':')
      p++;
   if (*p == '\n')
      return(NULL);
   *p++ = '\0';  l.fname = p;
   while (*p++ != '\n')
      ;
   *p = '\0';
   return(&l);
}

/***************************************************************************
*
*     printit
*
*     Fkt:     gibt den Inhalt der Zeilenstruktur aus
*
*
*     Input:   l :   Zeilenstruktur
*
*     Output:  ---
*
***************************************************************************/

void
printit(struct line *l)

{
   short i;
   int desc_len;
   long len = 0L;
   char fmt_str[24];

   for (i = 0; i < MAXALIASES && l->aliases[i]; i++)
      len += Printf("%s%lc",l->aliases[i],
                           (i<MAXALIASES-1&&l->aliases[i+1])?'000,':'000:');
   if (LINELENGTH - len > (desc_len = strlen(l->desc)))
      SPrintf(fmt_str,"%%%ld.%lds\n",LINELENGTH-len,LINELENGTH-len);
   else
      if (LINELENGTH > desc_len)
         SPrintf(fmt_str,"\n%%%lds\n",LINELENGTH);
      else
         strcpy(fmt_str,"\n%%s\n");
   Printf(fmt_str,l->desc);
}

/***************************************************************************
*
*     main
*
*     Fkt:     Hauptfunktion
*
*
*     Input:   argc :   Anzahl der Argumente
*              argv :   Zeiger auf Argument-Array
*
*     Output:  ---
*
***************************************************************************/

void
main(int argc, char *argv[])

{
   short i;
   char buffer[MAXBUFFER+1],*progname,*name;
   bool found = FALSE,keyword = FALSE;
   long run_error;
   struct line *line;
   BPTR mindex,stderr;

   if (!(progname = strrchr(argv[0], '/')))
      if (!(progname = strrchr(argv[0], ':')))
         progname = argv[0];
      else
         progname++;
   else
      progname++;
   if (!(stderr = Open("*",MODE_OLDFILE)))
      exit(20);
   if (argc < 2) {
      FPrintf(stderr, "usage: %s <name>\n", progname);
      FPrintf(stderr, "       %s -k <keyword>\n", progname);
      FPrintf(stderr, "       %s -v\n", progname);
      Close(stderr);
      exit(0);
   }
   if (!Strcmp(argv[1], "-v")) {
      FPrintf(stderr,"%s: unix man(1) clone version %s . john aycock . 1990\n"
                     "ARP version by Götz Müller\n",progname,VERSION);
      Close(stderr);
      exit(0);
   }
   if (!Strcmp(argv[1], "-k")) {
      if (argc != 3) {
         FPrintf(stderr,"%s: syntax error (\"%s\" for help)\n",
                                                         progname,progname);
         Close(stderr);
         exit(1);
      }
      keyword = TRUE;  name = argv[2];
      strcpy(buffer, "*");
      strcat(buffer, name);
      strcat(buffer, "*");
   } else {
      if (argc != 2) {
         FPrintf(stderr,"%s: syntax error (\"%s\" for help)\n",
                                                         progname, progname);
         Close(stderr);
         exit (1);
      }
      name = argv[1];
   }
   if (!(mindex = Open(DFLT_MANIDX,MODE_OLDFILE))) {
      FPrintf(stderr, "%s: unable to open %s\n", progname, DFLT_MANIDX);
      Close(stderr);
      exit (1);
   }
   do {
      if (!(line = getline(mindex))) {
         if (endoffile)
            break;
         FPrintf(stderr, "%s: error reading %s\n", progname, DFLT_MANIDX);
         Close(stderr);
         Close(mindex);
         exit(1);
      }
      if (!keyword) {
         for (i = 0; i < MAXALIASES && line->aliases[i]; i++) {
            if (!Strcmp(line->aliases[i], name)) {
               found = TRUE;
               *buffer = '\0';
               if ((*line->fname == '@') || !strpbrk(line->fname, ":/"))
                  strcat(buffer, DFLT_MANDIR);
               if (*line->fname == '@')
                  line->fname++;
               strcat(buffer, line->fname);
               if (run_error = SyncRun(DFLT_PAGER,buffer,NULL,NULL)) {
                  if (run_error < 0)
                     FPrintf(stderr, "%s: error loading/running %s\n",
                                                      progname, DFLT_PAGER);
                  else
                     FPrintf(stderr, "%s: error invoking %s on manual page\n",
                                                      progname, DFLT_PAGER);
                  Close(stderr);
                  Close(mindex);
                  exit(1);
               }
               break;
            }
         }
         if (found)
            break;
      } else {
         /* keyword */
         for (i = 0; i < MAXALIASES && line->aliases[i]; i++) {
            if (wildcard(line->aliases[i], name)) {
               found = TRUE;
               printit(line);
               i = -1;
               break;
            }
         }
         if (i < 0)
            continue;
         if (wildcard(line->desc, buffer)) {
            found = TRUE;
            printit(line);
         }
      }
   } while (!endoffile);
   if (!found)
      FPrintf(stderr, "%s: nothing appropriate\n", progname);
   Close(stderr);
   Close(mindex);
   exit(0);
}

