broome@ucbvax.ARPA (Jonathan C. Broome) (08/28/85)
[ cat this file onto the end of the previous file ] suffs -= 2; sec->dirs[d++] = dir; if (dirs == (DIR *) 0) dirs = dir; else dirlast->next = dir; dir->next = (DIR *) 0; dirlast = dir; dir->suff = (char **) malloc (sizeof (char **) * (suffs + 1)); for (s = 0; *argv; s++) dir->suff[s] = strsave (*argv++); dir->suff[s] = (char *) 0; } (void) fclose (fp); if (dirs || sections) /* save last type */ addtype ((char *) 0); (void) parse ("", &argv); /* free up argv memory */ } /* * Check to see if an entry for this directory already exists. * If so, return a pointer to it, else return (DIR *) 0. */ DIR * isdup (path) char *path; { register DIR *dir; for (dir = dirs; dir; dir = dir->next) if (eq (dir->man, path)) return (dir); return ((DIR *) 0); } !Funky!Stuff! if test 3908 -ne "`wc -c < 'config.c'`" then echo shar: error transmitting "'config.c'" '(should have been 3908 characters)' fi fi # end of overwriting check echo shar: extracting "'defs.h'" '(2025 characters)' if test -f 'defs.h' then echo shar: will not over-write existing file "'defs.h'" else cat << \!Funky!Stuff! > 'defs.h' /* * $Header: defs.h,v 1.3 85/08/27 15:16:31 broome Exp $ */ /* * $Log: defs.h,v $ * Revision 1.3 85/08/27 15:16:31 broome * Last cleanup before release. * * Revision 1.2 85/07/16 11:16:36 broome * Added global "debug" variable. * * Revision 1.1 85/07/05 18:19:11 broome * Initial revision */ #include <stdio.h> #define DIRS 11 /* one name can reference DIRS-1 directories */ #define TYPES 10 /* and at most TYPES cpu types */ struct section { char *name; /* name of section */ struct dir *dirs[DIRS]; /* array of pointers to directories */ struct section *next; /* next one in chain */ }; struct dir { char *man; /* full pathname of unformatted directory */ char *cat; /* full pathname containing formatted files */ char **suff; /* array of file suffixes */ struct dir *next; /* next one in list */ }; struct where { /* structure returned by find() */ char *name; /* name of file topic asked for */ char *section; /* section asked for (if any) */ char subsec; /* subsection char, if any */ int found; /* 1 if file found, 0 if not */ char *man; /* path to unformatted form */ char *cat; /* full path to formatted form */ }; struct type { char *name; /* cpu type name */ struct dir *dir; /* pointer to top of dir list */ struct section *sec; /* top of section list */ }; struct type types[TYPES]; /* all known cpu types */ struct section *sections; /* top of list of sections */ struct dir *dirs; /* top of list of directories */ int debug; typedef struct dir DIR; typedef struct section SEC; char *getword(); char *malloc(); char *strsave(); SEC *find_section(); struct where *find(); #define eq(a,b) (strcmp (a, b) == 0) !Funky!Stuff! if test 2025 -ne "`wc -c < 'defs.h'`" then echo shar: error transmitting "'defs.h'" '(should have been 2025 characters)' fi fi # end of overwriting check echo shar: extracting "'cat.c'" '(1822 characters)' if test -f 'cat.c' then echo shar: will not over-write existing file "'cat.c'" else cat << \!Funky!Stuff! > 'cat.c' #ifndef lint static char *RCSid = "$Header: cat.c,v 1.6 85/08/27 15:16:11 broome Exp $"; #endif /* * $Log: cat.c,v $ * Revision 1.6 85/08/27 15:16:11 broome * Last cleanup before release. * * Revision 1.5 85/07/06 16:55:41 broome * * Revision 1.4 85/07/03 17:34:11 broome * * Revision 1.3 85/07/03 15:41:37 broome * Safety check before major revisions... * * Revision 1.2 85/07/02 21:05:36 broome * * Revision 1.1 85/06/25 11:23:29 broome * Initial revision */ #include "defs.h" #include "response.h" #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <errno.h> cat (argc, argv) int argc; char *argv[]; { extern int errno; struct stat statb; struct where *wp; char line[256]; long date; FILE *fp; wp = find (--argc, ++argv); if (wp->found) { (void) stat (wp->man, &statb); /* stat the unformatted form */ date = statb.st_mtime; /* last modification date */ if (stat (wp->cat, &statb) < 0 || /* doesn't exist */ statb.st_size == 0 || /* zero length */ statb.st_mtime < date) /* out of date */ if (format (wp->man, wp->cat)) return; if ((fp = fopen (wp->cat, "r")) == NULL) /* should have it ! */ printf ("%d Cannot open %s: errno %d.\r\n", ERR_NOFILE, wp->cat, errno); else { printf ("%d Here comes the man page for %s! (%s)\r\n", OK_COMING, wp->name, wp->cat); while (fgets (line, 256, fp)) /* don't bother with \n => \r\n */ fputs (line, stdout); puts (".\r"); fclose (fp); } } else /* path not found */ notfound (wp); } !Funky!Stuff! if test 1822 -ne "`wc -c < 'cat.c'`" then echo shar: error transmitting "'cat.c'" '(should have been 1822 characters)' fi fi # end of overwriting check echo shar: extracting "'response.h'" '(2714 characters)' if test -f 'response.h' then echo shar: will not over-write existing file "'response.h'" else cat << \!Funky!Stuff! > 'response.h' /* * $Header: response.h,v 1.5 85/08/27 15:17:16 broome Exp $ */ /* * $Log: response.h,v $ * Revision 1.5 85/08/27 15:17:16 broome * Last cleanup before release. * * Revision 1.4 85/08/04 16:36:54 broome * Added new responses OK_TYPE and ERR_TYPE for "type" command. * * Revision 1.3 85/08/03 18:40:24 broome * Fixed several codes for consistency ... * * Revision 1.2 85/07/02 21:05:32 broome * * Revision 1.1 85/06/25 11:23:27 broome * Initial revision */ #define INFO_HELP 100 /* in front of help message */ #define INFO_TYPE 123 /* showing currently selected cpu type */ #define INFO_FMT 141 /* nroffing file now */ #define INFO_DONE 142 /* finished formatting */ #define OK_HELLO 210 /* opening banner */ #define OK_GOODBYE 211 /* closing banner */ #define OK_COMING 221 /* man page on its way */ #define OK_STAT 222 /* named page exists in formatted form */ #define OK_TYPE 223 /* reconfiguring for specified cpu type */ #define ERR_TIMEOUT 412 /* connection timed out after idle time */ #define ERR_NOSUBJ 405 /* specified section but no subject */ #define ERR_NOTSEC 421 /* no entry for subject in this section */ #define ERR_STAT 422 /* don't have file in *formatted* form */ #define ERR_TYPE 423 /* no config file for specified cpu type */ #define ERR_HLPFILE 424 /* cannot open help file */ #define ERR_PERM 425 /* cannot open file - permission denied */ #define ERR_OUTPUT 461 /* cannot create output file for formatting */ #define ERR_EXEC 462 /* exec failed in format routine */ #define ERR_CORE 463 /* nroff dumped core */ #define ERR_EXIT 465 /* nroff returned non-zero exit status */ #define ERR_FMT 465 /* unknown formatting error */ #define ERR_COMMAND 501 /* command not recognized or command not found */ #define ERR_SYNTAX 502 /* syntax error - argument count */ #define ERR_NOHELP 504 /* no help available for this command */ #define ERR_CNI 506 /* command not implemented yet */ #define ERR_HELLO 510 /* your host is denied access */ #define ERR_NOENT 521 /* no entry for subject */ #define ERR_NOFILE 522 /* cannot open the named file */ !Funky!Stuff! if test 2714 -ne "`wc -c < 'response.h'`" then echo shar: error transmitting "'response.h'" '(should have been 2714 characters)' fi fi # end of overwriting check echo shar: extracting "'main.c'" '(7761 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else cat << \!Funky!Stuff! > 'main.c' /* * Copyright (c) 1985 Jonathan C. Broome and The Regents of the * University of California. * * This software may be freely redistributed without licensing * provided that this copyright notice remains intact and no profit * is gained through any redistribution. * * Please report any bug fixes or modifications to the author at: * * broome@ucb-vax.berkeley.edu * or: * ...!ucbvax!broome * * The author and the Regents assume no liability for any damages * or loss of revenue caused directly or indirectly by the use of * this software. */ #ifndef lint static char *RCSid = "$Header: main.c,v 1.9 85/08/27 18:45:47 broome Exp $"; #endif /* * $Log: main.c,v $ * Revision 1.9 85/08/27 15:16:47 broome * Last cleanup before release. * * Revision 1.8 85/08/05 08:53:38 broome * Fixed missing argument to error printf ... * * Revision 1.7 85/08/04 16:33:06 broome * Added new command line options: * -f - to specify a configuration file besides the default. * -l - sets load cutoff so that we won't answer pings if load is higher. * -p - specify alternate port number to listen on. * * Revision 1.6 85/07/24 10:38:57 broome * * Revision 1.5 85/07/16 11:09:56 broome * Tuned the new "ping" stuff a bit. * * Revision 1.4 85/07/06 16:55:57 broome * Added new ping routines to help improve response times, * also makes it easier to cope with dead hosts. * * Revision 1.3 85/07/03 17:34:30 broome * [ RCS screwed up again! ] * * Revision 1.2 85/07/02 21:05:52 broome * * Revision 1.1 85/06/25 11:23:38 broome * Initial revision */ #include "response.h" #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/ioctl.h> #include <sys/wait.h> #include <signal.h> #include <errno.h> #include <stdio.h> #ifdef SERVICES #include <netdb.h> #endif SERVICES #ifndef STRICT /* hang up on unknown hosts ??? */ #define STRICT 0 #endif #ifndef TIMEOUT /* timeout interval on a connection */ #define TIMEOUT 2 #endif extern int errno; char hostname[32]; main (ac, av) int ac; char **av; { #ifdef SERVICES struct servent *sp, *getservbyname(); #endif char **argv; char *ctime(); char *config_file = CONFIG; long now; char line[128]; int argc, len, psock, ssock, new, mask, tty; int reaper(), hup(), timeout(); int port = 0; int secure = STRICT; /* hang up on unidentified hosts??? */ extern double cutoff; struct sockaddr_in sin; /* * usage: mand [ -s ] [ -f config_file ] [ -p service_port ] [ -l load_cutoff ] */ while (*++av) { if (**av != '-') usage (); switch (*++*av) { case 'f': if (*++av) /* next arg is configuration file */ config_file = *av; else usage (); break; case 'p': if (*++av) /* next arg is service port to use */ port = htons (atoi (*av)); else usage (); break; case 'l': if (*++av) /* next arg is load cutoff point */ cutoff = (double) atoi (*av); else usage (); break; case 's': secure = !secure; printf ("Secure = O%s\n", secure ? "N" : "FF"); break; default: usage (); } } if (port == 0) { #ifndef SERVICES fprintf (stderr, "Have to specify a service port!\n"); usage (); #else if ((sp = getservbyname ("man", "tcp")) == NULL) { fprintf (stderr, "mand: \"man/tcp\": unknown service.\n"); exit (1); } port = sp->s_port; #endif SERVICES } if ((ssock = socket (AF_INET, SOCK_STREAM, 0)) < 0) { perror ("socket"); exit (-1); } sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = port; if (bind (ssock, (char *)&sin, sizeof (sin)) < 0) { perror ("bind"); exit (-2); } (void) listen (ssock, 5); if ((psock = open_ping (port)) < 0) /* start up datagram socket */ exit (1); if (fork ()) /* fork off into background */ exit (0); signal (SIGCHLD, reaper); signal (SIGPIPE, SIG_IGN); signal (SIGHUP, hup); tty = open ("/dev/tty", 0, 0); /* disassociate from terminal */ if (tty != -1) { ioctl (tty, TIOCNOTTY, (struct sgttyb *)0); (void) close (tty); } else if (setpgrp (0, 0)) perror ("setpgrp"); (void) chdir ("/usr/man"); (void) umask (0); /* may not want this when root */ config (config_file); gethostname (hostname, 32); for ( ;; ) { mask = (1 << psock) | (1 << ssock); if (select (20, &mask, 0, 0, 0) <= 0) continue; if (mask & (1 << psock)) /* `ping' */ ping (); if (mask & (1 << ssock)) { len = sizeof (sin); if ((new = accept (ssock, &sin, &len)) < 0) { if (errno != EINTR) { perror ("accept"); exit (-1); } else continue; } if (fork ()) { /* parent */ close (new); } else { /* child */ close (ssock); close (psock); signal (SIGCHLD, SIG_IGN); signal (SIGALRM, timeout); alarm (TIMEOUT * 60); /* close conn after TIMEOUT mins */ if (new != 0) /* set up stdin, stdout, stderr */ dup2 (new, 0); if (new != 1) dup2 (new, 1); if (new != 2) dup2 (new, 2); if (identify (sin) && secure) { printf ("%d %s manual server: your host does not have man access\r\n", ERR_HELLO, hostname); exit (1); } time (&now); printf ("%d %s manual page server ready at %19.19s\r\n", OK_HELLO, hostname, ctime (&now)); (void) fflush (stdout); while (gets (line)) { /* read a line */ argc = parse (line, &argv); /* parse it */ if (argc == 0) /* blank line --- */ continue; /* just ignore it */ funcall (argc, argv); /* do the command */ } quit(); } } } } /* * Take care of all the dead children, avoiding zombie processes. */ reaper() { union wait status; while (wait3 (&status, WNOHANG, 0) > 0) ; } /* * Bye bye ... */ quit () { long now; time (&now); printf ("%d %s closing connection at %19.19s\r\n", OK_GOODBYE, hostname, ctime (&now)); exit (0); } /* * Exit nicely on SIGHUP. */ hup () { exit (0); } /* * Timed out after TIMEOUT minutes --- close down the connection. */ timeout () { printf ("%d %s manual server: connection timed out after %d minutes.\r\n", ERR_TIMEOUT, hostname, TIMEOUT); exit (1); } /* * Print a usage message and go away. */ usage () { fprintf (stderr, "Usage: mand [ -s ] [ -f config_file ] [ -p port ] [ -l load_cutoff ]\n"); exit (1); } !Funky!Stuff! if test 7761 -ne "`wc -c < 'main.c'`" then echo shar: error transmitting "'main.c'" '(should have been 7761 characters)' fi fi # end of overwriting check echo shar: extracting "'cmd.h'" '(2489 characters)' if test -f 'cmd.h' then echo shar: will not over-write existing file "'cmd.h'" else cat << \!Funky!Stuff! > 'cmd.h' /* * $Header: cmd.h,v 1.9 85/08/27 15:16:22 broome Exp $ */ /* * $Log: cmd.h,v $ * Revision 1.9 85/08/27 15:16:22 broome * Last cleanup before release. * * Revision 1.8 85/08/06 11:43:09 broome * Another new command - "ver" (version). Good for seeing if each site * is running the new stuff .... * * Revision 1.7 85/08/04 16:30:18 broome * Added new "type" command - allows a client to reconfigure mand to * use a configuration file with machine-specific pages. * * Revision 1.6 85/08/03 18:39:46 broome * Added new `stat' command - tests to see if the formatted version is * readily available. * * Revision 1.5 85/07/16 11:07:33 broome * Added new commands "path" and "list". * * Revision 1.4 85/07/06 16:55:35 broome * * Revision 1.3 85/07/03 17:34:02 broome * * Revision 1.2 85/07/02 21:05:29 broome * * Revision 1.1 85/06/25 11:23:26 broome * Initial revision */ /* * Have to declare all the functions before we can use them in the command table */ int apropos(), cat(), dbug(), dofind(), dosections(), dostat(), help(), list(), quit(), raw(), path(), show(), dotype(), version(), whatis(); struct cmd { char *name; /* command name */ int (*func)(); /* function to handle it */ int min; /* minimum number of args, including command name */ int max; /* maximum number of args */ char *usage; /* and usage msg string */ } cmdtab[] = { { "apropos",apropos, 2, 2, "apropos topic" }, { "cat", cat, 2, 3, "cat <section> topic" }, { "debug", dbug, 1, 1, "debug" }, { "find", dofind, 2, 3, "find <section> topic" }, { "help", help, 1, 2, "help <command>" }, { "list", list, 1, 1, "list" }, { "path", path, 1, 2, "path <section>" }, { "quit", quit, 1, 1, "quit" }, { "raw", raw, 2, 3, "raw <section> topic" }, { "show", show, 2, 99, "show file <file>" }, { "secs", dosections, 1, 1, "secs" }, { "stat", dostat, 2, 3, "stat <section> topic" }, { "type", dotype, 1, 2, "type <cpu_type>" }, { "ver", version, 1, 1, "ver" }, { "whatis", whatis, 2, 2, "whatis topic" } }; #define cmdtabsize (sizeof (cmdtab) / sizeof (struct cmd)) !Funky!Stuff! if test 2489 -ne "`wc -c < 'cmd.h'`" then echo shar: error transmitting "'cmd.h'" '(should have been 2489 characters)' fi fi # end of overwriting check echo shar: extracting "'cmd.c'" '(1273 characters)' if test -f 'cmd.c' then echo shar: will not over-write existing file "'cmd.c'" else cat << \!Funky!Stuff! > 'cmd.c' #ifndef lint static char *RCSid = "$Header: cmd.c,v 1.6 85/08/27 15:16:18 broome Exp $"; #endif /* * $Log: cmd.c,v $ * Revision 1.6 85/08/27 15:16:18 broome * Last cleanup before release. * * Revision 1.5 85/07/16 11:06:58 broome * Added new "path" and "list" commands, makes debugging easier. * * Revision 1.4 85/07/06 16:55:44 broome * * Revision 1.3 85/07/03 17:34:15 broome * * Revision 1.2 85/07/02 21:05:40 broome * * Revision 1.1 85/06/25 11:23:31 broome * Initial revision */ #include "response.h" #include "cmd.h" #include <stdio.h> /* * Do the actual function calls here. */ funcall (argc, argv) int argc; char **argv; { register struct cmd *cmd; for (cmd = cmdtab; cmd < cmdtab + cmdtabsize; cmd++) { if (streql (cmd->name, *argv) == 0) { /* names match */ if (argc >= cmd->min && argc <= cmd->max) /* right # args */ (*cmd->func)(argc, argv); else /* bad arg count */ printf ("%d Usage: %s\r\n", ERR_SYNTAX, cmd->usage); (void) fflush (stdout); return; } } printf ("%d Command not recognized.\r\n", ERR_COMMAND); (void) fflush (stdout); } !Funky!Stuff! if test 1273 -ne "`wc -c < 'cmd.c'`" then echo shar: error transmitting "'cmd.c'" '(should have been 1273 characters)' fi fi # end of overwriting check echo shar: extracting "'identify.c'" '(1677 characters)' if test -f 'identify.c' then echo shar: will not over-write existing file "'identify.c'" else cat << \!Funky!Stuff! > 'identify.c' /* * Copyright (c) 1985 Jonathan C. Broome and The Regents of the * University of California. * * This software may be freely redistributed without licensing * provided that this copyright notice remains intact and no profit * is gained through any redistribution. * * Please report any bug fixes or modifications to the author at: * * broome@ucb-vax.berkeley.edu * or: * ...!ucbvax!broome * * The author and the Regents assume no liability for any damages * or loss of revenue caused directly or indirectly by the use of * this software. */ #include "defs.h" #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #ifndef HOSTFILE #define HOSTFILE "/usr/lib/mand.hosts" #endif /* * Determine the calling host's cpu type if possible, then initialize it. * If the host is unknown, set to "generic". * Returns 1 if host is unknown - used if identity checking is strict. */ identify (sin) struct sockaddr_in sin; { char **argv = (char **) 0; char *addr; char *inet_ntoa(); char line[256]; int found = 0; FILE *fp; addr = inet_ntoa (sin.sin_addr.s_addr); if (fp = fopen (HOSTFILE, "r")) { while (getline (line, 256, fp)) { if (parse (line, &argv) == 0) continue; if (eq (argv[0], addr)) { found = 1; break; } } (void) fclose (fp); } if (switchtype (found ? argv[1] : "generic") && found) switchtype ("generic"); parse ("", &argv); /* free up memory */ return (!found); } !Funky!Stuff! if test 1677 -ne "`wc -c < 'identify.c'`" then echo shar: error transmitting "'identify.c'" '(should have been 1677 characters)' fi fi # end of overwriting check echo shar: extracting "'apropos.c'" '(1769 characters)' if test -f 'apropos.c' then echo shar: will not over-write existing file "'apropos.c'" else cat << \!Funky!Stuff! > 'apropos.c' #ifndef lint static char RCSid[] = "$Header: apropos.c,v 1.5 85/08/27 15:16:08 broome Exp $"; #endif /* * $Log: apropos.c,v $ * Revision 1.5 85/08/27 15:16:08 broome * Last cleanup before release. * * Revision 1.4 85/07/24 10:38:26 broome * Ready to ship out ... (?) * * Revision 1.3 85/07/04 20:26:25 broome * Fixed error messages to conform to the rfc. */ #include "response.h" #include <stdio.h> #define LIST "/usr/lib/whatis" /*ARGSUSED*/ apropos (argc, argv) int argc; char **argv; { register FILE *fp; char buf[512]; int found = 0; argv++; if ((fp = fopen (LIST, "r")) == NULL) { printf ("%d cannot open %s\r\n", ERR_NOFILE, LIST); return; } while (fgets (buf, 512, fp)) { if (substr (buf, *argv)) { if (found == 0) printf ("%d information on %s coming.\r\n", OK_COMING, *argv); printf ("%s", buf); (void) fflush (stdout); /* so it doesn't seem as slow to them */ found++; } } if (!found) printf ("%d %s: nothing appropriate.\n", ERR_NOENT, *argv); else puts (".\r"); } /* * Returns 1 if `sub' is contained in `str'. */ substr (buf, str) register char *buf, *str; { register char *i; i = str; while (*buf) { if (tolower (*buf) == *i) { /* first char matches */ while (*buf) { /* does rest match? */ if (tolower (*buf) != *i) break; buf++, i++; } if (!*i) /* ran out of substring */ return (1); i = str; /* reset i */ } buf++; } return (0); } !Funky!Stuff! if test 1769 -ne "`wc -c < 'apropos.c'`" then echo shar: error transmitting "'apropos.c'" '(should have been 1769 characters)' fi fi # end of overwriting check echo shar: extracting "'ver.c'" '(1106 characters)' if test -f 'ver.c' then echo shar: will not over-write existing file "'ver.c'" else cat << \!Funky!Stuff! > 'ver.c' /* * Copyright (c) 1985 Jonathan C. Broome and The Regents of the * University of California. * * This software may be freely redistributed without licensing * provided that this copyright notice remains intact and no profit * is gained through any redistribution. * * Please report any bug fixes or modifications to the author at: * * broome@ucb-vax.berkeley.edu * or: * ...!ucbvax!broome * * The author and the Regents assume no liability for any damages * or loss of revenue caused directly or indirectly by the use of * this software. */ #ifndef lint static char RCSid[] = "$Header: ver.c,v 1.2 85/08/27 18:45:53 broome Exp $"; #endif /* * $Log: ver.c,v $ * Revision 1.2 85/08/25 17:20:58 broome * * Revision 1.1 85/08/06 11:22:54 broome * Initial revision */ #include <stdio.h> /* * Show the date this version was last recompiled. * The "V ERSION" and "D ATE" stuff will be filled in * by the "newver.csh" script using sed. */ version () { printf ("101 Version VERSION, compiled DATE\r\n"); (void) fflush (stdout); } !Funky!Stuff! if test 1106 -ne "`wc -c < 'ver.c'`" then echo shar: error transmitting "'ver.c'" '(should have been 1106 characters)' fi fi # end of overwriting check echo shar: extracting "'help.c'" '(1708 characters)' if test -f 'help.c' then echo shar: will not over-write existing file "'help.c'" else cat << \!Funky!Stuff! > 'help.c' #ifndef lint static char *RCSid = "$Header: help.c,v 1.3 85/07/16 11:08:41 broome Exp $"; #endif /* * $Log: help.c,v $ * Revision 1.3 85/07/16 11:08:41 broome * Fixed to print error message when can't open help file. * * Revision 1.2 85/07/06 16:55:53 broome * * * Revision 1.1 85/06/25 11:23:35 broome * Initial revision */ #include <stdio.h> #include "response.h" #ifndef HELPFILE #define HELPFILE "/usr/lib/mand.hf" #endif static FILE *hp = (FILE *) NULL; /* help file pointer */ help (argc, argv) int argc; char *argv[]; { char buf[80]; int slen, found = 0; char *subj; char *i, *index(); if (argc == 1) /* no args, use "mand" */ subj = "mand"; else subj = argv[1]; slen = strlen (subj); if (hp == (FILE *) NULL) /* haven't opened help file yet */ if ((hp = fopen (HELPFILE, "r")) == (FILE *) NULL) { printf ("%d Cannot open help file (%s)\r\n", ERR_HLPFILE, HELPFILE); (void) fflush (stdout); return (ERR_HLPFILE); } fseek (hp, 0L, 0); /* go to top of file */ while (fgets (buf, 80, hp)) { if (strncmp (buf, subj, slen)) /* subject doesn't match */ continue; buf[strlen(buf)-1] = '\0'; /* zap the '\n' */