broome@ucbvax.ARPA (Jonathan C. Broome) (08/28/85)
[ this is the last part - cat them all together and feed to 'sh' ] if (i = index (buf, '\t')) /* tabs separate name from info */ printf ("%d-%s\r\n", INFO_HELP, ++i); found++; } if (found) printf ("%d End of HELP info for \"%s\"\r\n", INFO_HELP, subj); else printf ("%d HELP topic \"%s\" unknown\r\n", ERR_NOHELP, subj); fflush (stdout); return (found != 0); } !Funky!Stuff! if test 1708 -ne "`wc -c < 'help.c'`" then echo shar: error transmitting "'help.c'" '(should have been 1708 characters)' fi fi # end of overwriting check echo shar: extracting "'find.c'" '(3500 characters)' if test -f 'find.c' then echo shar: will not over-write existing file "'find.c'" else cat << \!Funky!Stuff! > 'find.c' #ifndef lint static char RCSid[] = "$Header: find.c,v 1.4 85/08/27 15:16:36 broome Exp $"; #endif /* * $Log: find.c,v $ * Revision 1.4 85/08/27 15:16:36 broome * Last cleanup before release. * * Revision 1.3 85/08/04 16:32:15 broome * Increased efficiency by checking for directory existence before stat'ing * each possible file name. * * Revision 1.2 85/07/06 16:56:18 broome * * Revision 1.1 85/07/05 18:19:13 broome * Initial revision */ #include <sys/file.h> #include "defs.h" /* * Take the name/section argument and try to * find the corresponding files. */ struct where * find (argc, argv) int argc; char *argv[]; { static struct where wp; SEC *sec; DIR *dir; int d; bzero ((char *)&wp, sizeof (wp)); if (argc == 2) { /* section specified */ wp.section = strsave (argv[0]); wp.name = strsave (argv[1]); if (strlen (*argv) == 2) /* subsection kludge */ wp.subsec = (*argv)[1]; if (sec = find_section (*argv++)) { for (d = 0; sec->dirs[d]; d++) /* check each dir pointed to */ if (checkpath (sec->dirs[d], *argv, &wp)) break; } } else { wp.name = strsave (*argv); /* * Default action is to check all known * directories and suffixes. */ for (dir = dirs; dir; dir = dir->next) if (checkpath (dir, *argv, &wp)) break; } return (&wp); } /* * Return a pointer to the section structure for the named section, * Null pointer if not found. */ SEC * find_section (name) char *name; { register SEC *sec; register int len = strlen (name); for (sec = sections; sec; sec = sec->next) { if (eq (name, sec->name)) return (sec); if (len == 2 && strlen (sec->name) == 1) /* kludge for `man 3x foo' */ if (*name == *sec->name) return (sec); } return ((SEC *) 0); } /* * Given a filename and DIR pointer, see if a file exists whose name * is the concatenation of the dir, name, and suffix. */ checkpath (dir, name, wp) DIR *dir; char *name; struct where *wp; { char *suff; int i; if (wp->subsec) { /* forced subsection, don't search list */ char suf[10]; sprintf (suf, ".%s", wp->section); return (docheck (dir, name, suf, wp)); } if (access (dir->man, 0) == -1) { /* test for dir existence */ if (debug) printf ("%s: No such directory.\n", dir->man); return (0); } for (i = 0; suff = dir->suff[i]; i++) /* test each possible suffix */ if (docheck (dir, name, suff, wp)) return (1); return (0); } /* * Common code to check on one file. */ static docheck (dir, name, suff, wp) DIR *dir; char *name; char *suff; struct where *wp; { char buf[256]; sprintf (buf, "%s/%s%s", dir->man, name, suff); /* full name of file */ if (debug) /* show file we are checking */ printf ("Checking %s\t", buf); if (access (buf, R_OK) == -1) { /* doesn't exist */ if (debug) printf ("not found.\n"); return (0); } if (debug) printf ("found.\n"); wp->man = strsave (buf); sprintf (buf, "%s/%s%s", dir->cat, name, suff); /* name of cat file */ wp->cat = strsave (buf); wp->found = 1; return (1); } !Funky!Stuff! if test 3500 -ne "`wc -c < 'find.c'`" then echo shar: error transmitting "'find.c'" '(should have been 3500 characters)' fi fi # end of overwriting check echo shar: extracting "'mand.cf'" '(3633 characters)' if test -f 'mand.cf' then echo shar: will not over-write existing file "'mand.cf'" else cat << \!Funky!Stuff! > 'mand.cf' # Anatomy of a directory entry: # # 1 /usr/man/man1 /usr/man/cat1 .1,.1m,.1c .1g .1p .1r .1v # # "1" -- Section name to be used by users (ie. "man 1 ls") # "/usr/man/man1" -- Directory to search for unformatted pages # "/usr/man/cat1" -- Directory to look/place formatted pages in # ".1,.1m,.1c" --- Suffixes to add to name, ie. "/usr/man/man1/ls.1" # # List all the sections by name, then the directories and suffixes # continuation lines must begin with a *tab* character, suffixes # may be separated by white space or commas, long lines may be continued # by ending with a backslash character. # # If you want multiple names to apply to one directory or set of directories, # you need to have multiple lines with (at least) the section name and the # man directory. The configuration routine will assign both section names # to each directory. # # Note that if you want to have several sections use the same man directory # with *different* suffixes (ie /usr/man/man1 w/ ".1 .1c" and ".1 .1f"), then # you need to use different *names* for the two directories --- like # "/usr/man//man1" for one of them will do. # #name man dir cat dir suffixes 1 /usr/man/man1 /usr/man/cat1 .1,.1m,.1c .1g .1p .1r .1v /usr/man/mann /usr/man/catn .n /usr/man/manl /usr/man/catl .l /usr/man/mano /usr/man/cato .o n /usr/man/mann /usr/man/catn .n new /usr/man/mann /usr/man/catn .n l /usr/man/manl /usr/man/catl .l local /usr/man/manl /usr/man/catl .l 6 /usr/man/man6 /usr/man/cat6 .6 8 /usr/man/man8 /usr/man/cat8 .8 .8v .8c 2 /usr/man/man2 /usr/man/cat2 .2 .2v 3 /usr/man/man3 /usr/man/cat3 .3 .3j .3x .3m .3s .3n .3v .3c .3f 4 /usr/man/man4 /usr/man/cat4 .4 .4p .4f .4v .4s .4n 5 /usr/man/man5 /usr/man/cat5 .5 7 /usr/man/man7 /usr/man/cat7 .7 p /usr/man/manp /usr/man/catp .p public /usr/man/manp /usr/man/catp .p o /usr/man/mano /usr/man/cato .o old /usr/man/mano /usr/man/cato .o # Switch type to "cad" - this will override all other sections # when cpu type is "cad" --> Note that Cad users have no access # to sections 2, 3, 5, old, or public (Can use this to save # users from themselves!) TYPE cad 1 /usr/man/man1 /usr/man/cat1 .1,.1m,.1c .1g .1p .1r .1v /usr/man/mann /usr/man/catn .n /usr/man/manl /usr/man/catl .l /usr/man/mano /usr/man/cato .o n /usr/man/mann /usr/man/catn .n new /usr/man/mann /usr/man/catn .n l /usr/man/manl /usr/man/catl .l local /usr/man/manl /usr/man/catl .l 6 /usr/man/man6 /usr/man/cat6 .6 8 /usr/man/man8 /usr/man/cat8 .8 .8v .8c c /a/guest/hprg/cad/man/man1 /a/guest/hprg/cad/man/cat1 .1 cad /a/guest/hprg/cad/man/man1 /a/guest/hprg/cad/man/cat1 .1 TYPE cs8 # these guys don't get to read too much! 1 /c/cs8/doc/man /c/cs8/doc/cat .1 .out /usr/man/man1 /usr/man/cat1 .1 .1 .1c .1p .1r .1v TYPE sun 1 /sun/man/man1 /sun/man/cat1 .1,.1m,.1c .1g .1p .1r .1v /usr/man/man1 /usr/man/cat1 .1,.1m,.1c .1g .1p .1r .1v /sun/man/mann /sun/man/catn .n /usr/man/mann /usr/man/catn .n /sun/man/manl /sun/man/catl .l /usr/man/manl /usr/man/catl .l /sun/man/mano /sun/man/cato .o n /sun/man/mann /sun/man/catn .n new /sun/man/mann /sun/man/catn .n l /sun/man/manl /sun/man/catl .l l /usr/man/manl /usr/man/catl .l local /sun/man/manl /sun/man/catl .l local /usr/man/manl /usr/man/catl .l 6 /sun/man/man6 /sun/man/cat6 .6 8 /sun/man/man8 /sun/man/cat8 .8 .8v .8c 2 /sun/man/man2 /sun/man/cat2 .2 .2v 3 /sun/man/man3 /sun/man/cat3 .3 .3j .3x .3m .3s .3n .3v .3c .3f 4 /sun/man/man4 /sun/man/cat4 .4 .4p .4f .4v .4s .4n 5 /sun/man/man5 /sun/man/cat5 .5 7 /sun/man/man7 /sun/man/cat7 .7 sun /sun/man/mans /sun/man/cats .s !Funky!Stuff! if test 3633 -ne "`wc -c < 'mand.cf'`" then echo shar: error transmitting "'mand.cf'" '(should have been 3633 characters)' fi fi # end of overwriting check echo shar: extracting "'parse.c'" '(2147 characters)' if test -f 'parse.c' then echo shar: will not over-write existing file "'parse.c'" else cat << \!Funky!Stuff! > 'parse.c' #ifndef lint static char *RCSid = "$Header: parse.c,v 1.3 85/08/04 16:35:30 broome Exp $"; #endif /* * $Log: parse.c,v $ * Revision 1.3 85/08/04 16:35:30 broome * Cleaned up a little, added comma as delimiter so that config file can * be more freely formatted. * * Revision 1.2 85/07/06 16:56:04 broome * * Revision 1.1 85/06/25 11:23:41 broome * Initial revision */ #define iswhite(c) (c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\0'||c==',') /* * Turn a line buffer into a pointer to a set * of strings, just like ``argv[]'', and return argc. */ parse (buf, array) char *buf; char ***array; { char **argv; char *s; char word[132]; int argc = 0; int i = 0, j; argv = *array; if (argv != (char **) 0) { /* have to free up space taken by old array */ do free (argv[i]); /* free up each element */ while (argv[i++] != (char *) 0); free (argv); /* and then free argv itslef */ } /* * Count and null-terminate each word. */ for (s = buf; *s; s++) if (!iswhite (*s) && iswhite(*(s+1))) /* the end of each word */ argc++; else if (iswhite (*s)) *s = '\0'; /* * Now malloc up space for the strings plus the null at the end. */ if ((argv = (char **) malloc ((argc+1) * sizeof(char *))) == (char **) 0) { perror ("parse: cannot malloc space for argv[]"); exit (1); } /* * And copy the contents in. */ i = 0; for (s = buf, j = 0; j < argc; s++) { if (!iswhite (*s) && iswhite(*(s+1))) { /* the end of each word */ word[i++] = *s; word[i] = '\0'; if ((argv[j] = (char *)malloc (i+1)) == (char *) 0) { perror ("parse: cannot malloc mem for word"); exit (1); } strcpy (argv[j++], word); i = 0; } else if (!iswhite (*s)) word[i++] = *s; } argv[j] = (char *) 0; /* and a null at the end of it all */ *array = argv; return (argc); } !Funky!Stuff! if test 2147 -ne "`wc -c < 'parse.c'`" then echo shar: error transmitting "'parse.c'" '(should have been 2147 characters)' fi fi # end of overwriting check echo shar: extracting "'mand.hf'" '(2838 characters)' if test -f 'mand.hf' then echo shar: will not over-write existing file "'mand.hf'" else cat << \!Funky!Stuff! > 'mand.hf' @(#) mand.hf Last revised 26/08/85. edit this file with tabstops set to 8. mand Commands available in ``mand'' are: mand mand APROPOS CAT DEBUG FIND HELP mand LIST PATH QUIT RAW SHOW mand SECS STAT TYPE VER WHATIS mand mand For help with a specific command, use "HELP topic". mand Send questions or bug reports to broome@ucb-vax.berkeley.edu mand This is an experimental version. apropos Usage: apropos topic apropos Searches through the permuted index for lines containing the apropos topic substring. Very verbose. cat Usage: cat <section> page cat This is the main command used - it searches for the named cat page and retrieves it, formatting it if needed. debug Usage: debug debug Enables tracing of search and configuration routines. debug Not especially interesting. find Usage: find <section> name find Searches for the named page, returns the location find of the source (unformatted) page or error if not found. fmt Usage: fmt <section> name fmt Takes the unformatted page and formats it, sending the fmt output directly to the connection socket. fmt NOT YET IMPLEMENTED .... help Usage: help <command> help Shows the help page for the named command list Usage: list list Lists all known directories and sections in the order list that they will be searched (ie. when the section is list left unspecified in a CAT command.) path Usage: path [section] path Lists the named section by name, showing each corresponding path directory and suffix list in the order searched. When given path no arguments, shows the information for all sections. quit Usage: quit quit Prints a goodbye message and closes down the connection. raw Usage: raw <section> page raw Sends the raw (unformatted) page if found, ERR otherwise. secs Usage: secs secs Returns a list of all currently valid section names, secs preceded by the number of sections to be sent. secs Can be used by a client to verify section names. secs (No pun intended!) show Usage: show page [ page [ page ] ... ] show Shows all the known files for topic `page' in show the order that they are selected. stat Usage: stat <section> page stat Returns OK status if a formatted copy of the named stat page is found (and is of non-zero length), ERR otherwise type Usage: type <cpu_type> type If given an argument, will cause ``mand'' to reconfigure type itself for ``cpu_type'', elsee will show the currently type selected cpu type. Used to allow mand to specially type cater to any of several machine types, such as Suns and type System V workstations with special man pages. ver Usage: ver ver Shows the date this daemon was last compiled and ver the current version number. whatis Usage: whatis topic whatis Searches for a line in the permuted manual index whatis corresponding to the named topic and returns it. !Funky!Stuff! if test 2838 -ne "`wc -c < 'mand.hf'`" then echo shar: error transmitting "'mand.hf'" '(should have been 2838 characters)' fi fi # end of overwriting check echo shar: extracting "'misc.c'" '(2712 characters)' if test -f 'misc.c' then echo shar: will not over-write existing file "'misc.c'" else cat << \!Funky!Stuff! > 'misc.c' #ifndef lint static char *RCSid = "$Header: misc.c,v 1.6 85/08/27 15:17:00 broome Exp $"; #endif /* * $Log: misc.c,v $ * Revision 1.6 85/08/27 15:17:00 broome * Last cleanup before release. * * Revision 1.5 85/08/04 16:56:04 broome * Added new "any" routine. * * Revision 1.4 85/07/06 16:56:01 broome * * Revision 1.3 85/07/03 17:34:34 broome * * Revision 1.2 85/07/02 21:05:56 broome * * Revision 1.1 85/06/25 11:23:39 broome * Initial revision */ #include <stdio.h> #include "response.h" #include "defs.h" /* * Search for and print the path name to the topic and * section requested. Duplicates the action used by * `cat()' and `raw()' without actually sending the file. */ dofind (argc, argv) int argc; char *argv[]; { struct where *wp; argv++, argc--; wp = find (argc, argv); if (wp->found) printf ("%d %s\r\n", OK_STAT, wp->man); else notfound (wp); } /* * Toggle debugging information. */ dbug () { debug = !debug; printf ("100 Debugging is now %s\n", debug ? "ON" : "OFF"); } /* * Show a list of all known directories. */ list () { DIR *dir; char *suff; int s; printf ("121-List of all known directories:\r\n"); for (dir = dirs; dir; dir = dir->next) { printf ("120-Man: %s\n120-Cat: %s\r\n120-\tSuffixes: ", dir->man, dir->cat); for (s = 0; suff = dir->suff[s]; s++) printf ("%s ", suff); puts ("\r"); } printf ("122 That's all.\r\n"); } /* * Report that the requested file was not found. */ notfound (wp) struct where *wp; { printf ("%d No entry for %s in ", ERR_NOENT, wp->name); if (wp->section) printf ("section %s of ", wp->section); printf ("the manual.\r\n"); } /* * Allocate enough memory for the given string, then copy it in. */ char * strsave (str) char *str; { char *s; char *malloc(); s = malloc (strlen (str) + 1); strcpy (s, str); return (s); } /* * Return 1 if ch is contained in str, else 0. */ any (ch, str) register char ch; register char *str; { while (*str) if (ch == *str++) return (1); return (0); } /* * Return the lower case version of a given character. * Can't use a macro when arg is of the form `*foo++'. */ tolower (c) register c; { if ('A' <= c && c <= 'Z') return (c - 'A' + 'a'); return (c); } /* * Case insensitive version of strcmp(), returns 0 if equal, 1 if not. */ streql (a, b) register char *a, *b; { while (tolower (*a) == tolower (*b)) { if (*a == '\0') return (0); a++; b++; } return (1); } !Funky!Stuff! if test 2712 -ne "`wc -c < 'misc.c'`" then echo shar: error transmitting "'misc.c'" '(should have been 2712 characters)' fi fi # end of overwriting check echo shar: extracting "'sections.c'" '(899 characters)' if test -f 'sections.c' then echo shar: will not over-write existing file "'sections.c'" else cat << \!Funky!Stuff! > 'sections.c' #ifndef lint static char RCSid[] = "$Header: sections.c,v 1.1 85/08/04 16:37:18 broome Exp $"; #endif /* * $Log: sections.c,v $ * Revision 1.1 85/08/04 16:37:18 broome * Initial revision * */ #include "defs.h" /* * Show the list of all valid sections that the user can ask for. * This can be used by a client program to download a list of *current* * sections, instead of compiling them in. For this reason, we count * the number of sections first, so that the client can allocate enough * memory to save all the sections... */ dosections () { SEC *sec; int num = 0; for (sec = sections; sec; sec = sec->next) /* count number of sections */ num++; printf ("121-%d sections follow:\r\n", num); for (sec = sections; sec; sec = sec->next) printf ("120-%s\r\n", sec->name); printf ("122 That's all.\r\n"); fflush (stdout); } !Funky!Stuff! if test 899 -ne "`wc -c < 'sections.c'`" then echo shar: error transmitting "'sections.c'" '(should have been 899 characters)' fi fi # end of overwriting check echo shar: extracting "'format.c'" '(2230 characters)' if test -f 'format.c' then echo shar: will not over-write existing file "'format.c'" else cat << \!Funky!Stuff! > 'format.c' #ifndef lint static char *RCSid = "$Header: format.c,v 1.6 85/08/27 15:16:41 broome Exp $"; #endif /* * $Log: format.c,v $ * Revision 1.6 85/08/27 15:16:41 broome * Last cleanup before release. * * Revision 1.5 85/08/06 11:43:56 broome * Added check for exit status, * remove core if it dumped ... * * Revision 1.4 85/07/06 16:55:50 broome * * Revision 1.3 85/07/03 17:34:18 broome * * Revision 1.2 85/07/02 21:05:43 broome * * Revision 1.1 85/06/25 11:23:33 broome * Initial revision */ #include <stdio.h> #include <sys/file.h> #include <sys/wait.h> #include "response.h" #define NROFF "/usr/bin/nroff" /* * Format the named file into catable form, placing the output into `dest'. */ format (src, dest) char *src, *dest; { union wait status; int pid, fd; extern int errno; /* tell them what's going on */ printf ("%d-formatting file %s ==> %s ....\r\n", INFO_FMT, src, dest); (void) fflush (stdout); if ((fd = creat (dest, 0644)) == -1) { /* can't create file */ printf ("%d Cannot create output file %s (%d)\r\n", ERR_OUTPUT, dest, errno); return (1); } switch (pid = fork()) { case -1: return (1); /* can't fork */ case 0: if (fd != 1) { /* child */ dup2 (fd, 1); close (fd); } execl (NROFF, "nroff", "-man", src, 0); perror ("exec"); exit (1); default: close (fd); /* parent */ while (wait (&status) != pid) ; if (status.w_coredump) { /* shouldn't core dump */ (void) unlink ("core"); /* clean up */ printf ("%d Format encountered core dump!\r\n", ERR_CORE); return (1); } if (status.w_retcode) { /* non-zero exit status */ printf ("%d Format returned non-zero exit code.\r\n", ERR_EXIT); return (2); } printf ("%d-done.\r\n", INFO_DONE); return (0); /* all was ok */ } } !Funky!Stuff! if test 2230 -ne "`wc -c < 'format.c'`" then echo shar: error transmitting "'format.c'" '(should have been 2230 characters)' fi fi # end of overwriting check echo shar: extracting "'ping.c'" '(2592 characters)' if test -f 'ping.c' then echo shar: will not over-write existing file "'ping.c'" else cat << \!Funky!Stuff! > 'ping.c' #ifndef lint static char RCSid[] = "$Header: ping.c,v 1.5 85/08/27 15:17:08 broome Exp $"; #endif /* * $Log: ping.c,v $ * Revision 1.5 85/08/27 15:17:08 broome * Last cleanup before release. * * Revision 1.4 85/08/04 16:36:11 broome * Added load cutoff, such that if 1 minute load is above this, we * won't respond to pings from clients. * * Revision 1.3 85/07/24 10:39:03 broome * * Revision 1.2 85/07/18 12:05:20 broome * * Revision 1.1 85/07/16 11:10:26 broome * Initial revision */ /* * Routines to handle `ping' calls on a dgram socket. */ #include <syslog.h> #include <nlist.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> struct nlist nl[] = { { "_avenrun" }, { 0 }, }; int sock; /* the datagram socket descriptor */ int kmem; /* and memory file descriptor */ double cutoff = -1.0; /* don't respond if 1min load is above this */ /* * Initialize everything ... */ open_ping (port) int port; { struct sockaddr_in sin; if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { syslog (LOG_ERR, "cannot open ping (datagram) socket: %m"); return (-1); } bzero ((char *)&sin, sizeof (sin)); sin.sin_port = port; /* should probably do a `getservice' */ sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; if (bind (sock, (char *)&sin, sizeof (sin)) < 0) { syslog (LOG_ERR, "cannot bind ping socket: %m"); return (-1); } if ((kmem = open ("/dev/kmem", 0, 0)) < 0) { syslog (LOG_ERR, "No kmem: %m"); return (-1); } nlist ("/vmunix", nl); if (nl[0].n_type == 0) { syslog (LOG_ERR, "No namelist: %m"); return (-1); } return (sock); } /* * Routine to actually handle `ping' packets sent to the datagram socket. * Finds the load average and sends it back to the sending socket. */ ping () { struct sockaddr_in from; double avenrun[3]; char buf[20]; /* grab the load average */ lseek (kmem, (long) nl[0].n_value, 0); read (kmem, avenrun, sizeof (avenrun)); if (cutoff != -1.0 && avenrun[0] > cutoff) /* load's too high */ return; /* don't want to see what they sent, just need their address */ if (recvfrom (sock, buf, 20, 0, &from, sizeof (from)) < 1) return; sprintf (buf,"%.2f %.2f %.2f\n", avenrun[0], avenrun[1], avenrun[2]); /* and send it on over */ if (sendto (sock, buf, strlen (buf), 0, &from, sizeof (from)) < 0) perror ("sendto"); } !Funky!Stuff! if test 2592 -ne "`wc -c < 'ping.c'`" then echo shar: error transmitting "'ping.c'" '(should have been 2592 characters)' fi fi # end of overwriting check echo shar: extracting "'showpath.c'" '(1162 characters)' if test -f 'showpath.c' then echo shar: will not over-write existing file "'showpath.c'" else cat << \!Funky!Stuff! > 'showpath.c' #ifndef lint static char RCSid[] = "$Header: showpath.c,v 1.2 85/07/16 11:12:04 broome Exp $"; #endif /* * $Log: showpath.c,v $ * Revision 1.2 85/07/16 11:12:04 broome * Revised output format, allows path for a given section to be shown. * * */ #include "defs.h" /* * Print out the entire search path used. */ path (argc, argv) int argc; char **argv; { SEC *sec; DIR *dir; char *suff; int d, s; if (argc == 2) printf ("121-search path for section %s:\r\n", *++argv); else printf ("121-All sections searched (in order):\r\n"); for (sec = sections; sec; sec = sec->next) { if (argc == 2 && strcmp (sec->name, *argv)) continue; printf ("120-Section: %s\n", sec->name); for (d = 0; dir = sec->dirs[d]; d++) { printf ("120-\tMan dir: %s\r\n120-\tCat dir: %s\r\n", dir->man, dir->cat); printf ("120-\t\tSuffixes: "); for (s = 0; suff = dir->suff[s]; s++) printf ("%s ", suff); puts ("\r"); } } printf ("122 That's all.\r\n"); (void) fflush (stdout); } !Funky!Stuff! if test 1162 -ne "`wc -c < 'showpath.c'`" then echo shar: error transmitting "'showpath.c'" '(should have been 1162 characters)' fi fi # end of overwriting check echo shar: extracting "'raw.c'" '(767 characters)' if test -f 'raw.c' then echo shar: will not over-write existing file "'raw.c'" else cat << \!Funky!Stuff! > 'raw.c' #ifndef lint static char RCSid[] = "$Header: raw.c,v 1.4 85/08/27 15:17:12 broome Exp $"; #endif /* * $Log: raw.c,v $ * Revision 1.4 85/08/27 15:17:12 broome * Last cleanup before release. * * Revision 1.3 85/07/06 16:56:07 broome * * Revision 1.2 85/07/04 20:35:55 broome * Got the rfc protocol right, added rcs keywords. */ #include "defs.h" #include "response.h" #include <stdio.h> /* * Find and send the raw (unformatted) man page. */ raw (argc, argv) int argc; char **argv; { struct where *wp; /* find the file */ wp = find (--argc, ++argv); if (wp->found) { printf ("%d Raw file %s on the way.\r\n", OK_COMING, wp->man); soelim (wp->man); puts (".\r"); } else notfound (wp); } !Funky!Stuff! if test 767 -ne "`wc -c < 'raw.c'`" then echo shar: error transmitting "'raw.c'" '(should have been 767 characters)' fi fi # end of overwriting check echo shar: extracting "'show.c'" '(1014 characters)' if test -f 'show.c' then echo shar: will not over-write existing file "'show.c'" else cat << \!Funky!Stuff! > 'show.c' #ifndef lint static char RCSid[] = "$Header: show.c,v 1.3 85/08/27 15:17:21 broome Exp $"; #endif /* * $Log: show.c,v $ * Revision 1.3 85/08/27 15:17:21 broome * Last cleanup before release. * * Revision 1.2 85/07/24 10:39:09 broome * * Revision 1.1 85/07/06 16:56:28 broome * Initial revision */ #include "defs.h" #include <sys/file.h> /* * Find all occurrences of pages for the given name. */ /*ARGSUSED*/ show (argc, argv) int argc; char *argv[]; { DIR *dir; int s; char buf[256]; while (*++argv) { printf ("101-Searching for %s.\r\n", *argv); for (dir = dirs; dir; dir = dir->next) for (s = 0; dir->suff[s]; s++) { sprintf (buf, "%s/%s%s", dir->man, *argv, dir->suff[s]); if (access (buf, R_OK) == 0) { printf ("100-%s\r\n", buf); (void) fflush (stdout); } } printf ("102 That's all for \"%s\"\r\n", *argv); } } !Funky!Stuff! if test 1014 -ne "`wc -c < 'show.c'`" then echo shar: error transmitting "'show.c'" '(should have been 1014 characters)' fi fi # end of overwriting check echo shar: extracting "'whatis.c'" '(2159 characters)' if test -f 'whatis.c' then echo shar: will not over-write existing file "'whatis.c'" else cat << \!Funky!Stuff! > 'whatis.c' #ifndef lint static char RCSid[] = "$Header: whatis.c,v 1.4 85/07/24 10:39:13 broome Exp $"; #endif /* * $Log: whatis.c,v $ * Revision 1.4 85/07/24 10:39:13 broome * * * Revision 1.3 85/07/06 16:56:13 broome * * Revision 1.2 85/07/03 17:34:41 broome */ #include "response.h" #include <stdio.h> #define LIST "/usr/lib/whatis" #define DELIMS " \t\n\r,\"\'-()" /* word delimiters */ int key; /*ARGSUSED*/ whatis (argc, argv) int argc; char **argv; { extern int debug; register FILE *fp; register char *b; char buf[512]; char *nextword(); char word[80]; int found = 0; argv++; if ((fp = fopen (LIST, "r")) == NULL) { printf ("%d cannot open %s\r\n", ERR_NOFILE, LIST); (void) fflush (stdout); return; } while (fgets (buf, 512, fp)) { key = 0; b = buf; while (b = nextword (b, word)) { if (debug) printf ("|%s|", word); if (strcmp (word, *argv) == 0) { /* word matches arg */ if (found == 0) printf ("%d information for \"%s\" on the way.\r\n", OK_COMING, *argv); printf ("%s", buf); found++; break; } if (key == 1) /* went through all the keywords */ break; } } if (!found) printf ("%d %s: not found.\n", ERR_NOENT, *argv); else puts (".\r"); (void) fflush (stdout); } /* * Get the next word from the line and put it into `word', return * the advanced line pointer (NULL if at end of the line). */ char *nextword (buf, word) char *buf, *word; { register char *i = word; if (!buf || !*buf) return ((char *) 0); while (*buf && any (*buf, DELIMS) == 0) /* get this word */ *i++ = *buf++; *i = '\0'; while (*buf && any (*buf, DELIMS)) { /* skip over to next word */ if (*buf == '(') /*)*/ /* at end of keyword list */ key = 1; buf++; } return (buf); } !Funky!Stuff! if test 2159 -ne "`wc -c < 'whatis.c'`" then echo shar: error transmitting "'whatis.c'" '(should have been 2159 characters)' fi fi # end of overwriting check echo shar: extracting "'so.c'" '(1003 characters)' if test -f 'so.c' then echo shar: will not over-write existing file "'so.c'" else cat << \!Funky!Stuff! > 'so.c' #ifndef lint static char RCSid[] = "$Header: so.c,v 1.3 85/08/27 15:17:24 broome Exp $"; #endif /* * $Log: so.c,v $ * Revision 1.3 85/08/27 15:17:24 broome * Last cleanup before release. * * Revision 1.2 85/07/06 16:56:09 broome * * Revision 1.1 85/07/03 13:07:22 broome * Initial revision */ #include <stdio.h> /* * A nice simple form of "soelim" to replace `.so' * directives with the named file inline. */ soelim (name) char *name; { FILE *fp; char line[1024]; char so[512]; if ((fp = fopen (name, "r")) == NULL) { sprintf (line, "/usr/man/%s", name); /* kludge for old files */ if ((fp = fopen (line, "r")) == NULL) { perror (name); return; } } while (fgets (line, 1024, fp)) { if (strncmp (line, ".so", 3) == 0) { /* include directive */ sscanf (line, ".so%s", so); soelim (so); } else fputs (line, stdout); } fclose (fp); } !Funky!Stuff! if test 1003 -ne "`wc -c < 'so.c'`" then echo shar: error transmitting "'so.c'" '(should have been 1003 characters)' fi fi # end of overwriting check echo shar: extracting "'stat.c'" '(1001 characters)' if test -f 'stat.c' then echo shar: will not over-write existing file "'stat.c'" else cat << \!Funky!Stuff! > 'stat.c' #ifndef lint static char *RCSid = "$Header: stat.c,v 1.2 85/08/27 15:17:30 broome Exp $"; #endif /* * $Log: stat.c,v $ * Revision 1.2 85/08/27 15:17:30 broome * Last cleanup before release. * * Revision 1.1 85/08/03 18:36:20 broome * Initial revision */ #include "defs.h" #include "response.h" #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> dostat (argc, argv) int argc; char *argv[]; { struct stat statb; struct where *wp; long date; argc--, argv++; wp = find (argc, argv); if (wp->found) { stat (wp->man, &statb); /* stat the unformatted form */ date = statb.st_mtime; if (stat (wp->cat, &statb) < 0 || statb.st_size == 0 || statb.st_mtime < date) /* have to create/update it */ printf ("%d-No formatted file found for %s.\r\n", ERR_STAT, wp->name); else printf ("%d-Have formatted page for %s.\r\n", OK_STAT, wp->name); } else notfound (wp); } !Funky!Stuff! if test 1001 -ne "`wc -c < 'stat.c'`" then echo shar: error transmitting "'stat.c'" '(should have been 1001 characters)' fi fi # end of overwriting check echo shar: extracting "'type.c'" '(1752 characters)' if test -f 'type.c' then echo shar: will not over-write existing file "'type.c'" else cat << \!Funky!Stuff! > 'type.c' #include "defs.h" #include "response.h" static int t_index = 0; /* index of current type */ static int n_types = 0; /* number of types known */ /* * Switch to an alternate type. Returns 0 if ok, 1 on error. */ switchtype (name) char *name; { int i; for (i = 0; i < n_types; i++) if (eq (name, types[i].name)) { t_index = i; /* save the index */ dirs = types[i].dir; /* and set the pointers */ sections = types[i].sec; return (0); } return (1); } /* * Interface to the "switchtype" command. If no args, * prints current cpu type. */ dotype (argc, argv) int argc; char *argv[]; { if (argc == 1) { printf ("%d cpu type is \"%s\"\r\n", INFO_TYPE, types[t_index].name); } else { if (switchtype (argv[1])) printf ("%d unknown cpu type \"%s\"\r\n", ERR_TYPE, argv[1]); else printf ("%d new cpu type is \"%s\"\r\n", OK_TYPE, argv[1]); } fflush (stdout); } /* * Add another cpu type to the list. Used in config(), * but uses static data here. Note that "name" is the * name of the _next_ type, not this one just ending. */ addtype (name) char *name; { static char *this_type = (char *) 0; static int this_index = 0; n_types++; types[this_index].dir = dirs; /* save pointer to list */ dirs = (DIR *) 0; /* and set it to zero for next list */ types[this_index].sec = sections; sections = (SEC *) 0; types[this_index].name = this_type ? this_type : "generic"; /* save name */ this_index++; this_type = name ? strsave (name) : (char *) 0; /* this is next name */ } !Funky!Stuff! if test 1752 -ne "`wc -c < 'type.c'`" then echo shar: error transmitting "'type.c'" '(should have been 1752 characters)' fi fi # end of overwriting check echo shar: extracting "'mand.8'" '(2928 characters)' if test -f 'mand.8' then echo shar: will not over-write existing file "'mand.8'" else cat << \!Funky!Stuff! > 'mand.8' .TH MAND 8 "August 3 1985" .UC 4 .ad .SH NAME mand \- manual page server daemon .SH SYNOPSIS \fB/etc/mand\fP [ -p port ] [ -f config_file ] [ -l load ] [ -s ] .SH DESCRIPTION \fIMand\fP is a manual page server normally invoked at boot time from the \fI/etc/rc\fP or \fI/etc/rc.local\fP file. It is used in conjunction with \fIrman\fP to allow network access to manual pages from remote machines, typically workstations or other machines short on disk space. .SH OPTIONS The \fI\-p\fP option can be used to run \fImand\fP on a port other than the one defined in \fI/etc/services\fP, typically used to offer a secondary set of pages to alternate machine types. .PP The \fI\-f\fP option can be used to cause \fImand\fP to read a different configuration file. .PP The \fI\-l\fP option can be used to specify a load cutoff limit, such that if the load is exceeded \fImand\fP will not respond to `pings' from clients, though it will still accept stream connections. .PP The \fI\-s\fP ("secure") switch is used to toggle the identity checking routine. If the secure flag is set, the server will deny access to any client not identified in the host file. (The default setting for this flag is system dependent.) .SH CONFIGURATION .PP The configuration file specifies the directories and suffixes that \fImand\fP will search when looking for a set of pages, indicating the section name (ie. "cad"), the directory containing the unformatted manual pages, the directory for formatted pages, and a list of file suffixes to search. \fIMand\fP uses this information to construct filenames by concatenating the directory, the topic name, and the extension; it will try each extension in the order listed. Multiple directories can be given for each section by indenting all but the first line with a space or tab character. .PP Alternate machine \fItypes\fP are accomodated in the configuration file by preceding the list of sections for that type with a line of the form .nf .br .sp type \fImachine_type\fP .sp .br When a client connects, \fImand\fP will check the host file for a line indicating the client's type and will reconfigure itself to use the list of sections and directories specified for that type. If a client wishes to override the assigned type, it may issue a command of the form "type \fItype\fP" upon opening a connection. .SH PROTOCOL \fIMand\fP and \fIrman\fP use a protocol similar to that of most internet servers (e.g. the smtp server \fIsendmail\fP), with English commands and three-digit response codes. .SH FUTURE ADDITIONS \fIMand\fP should use some type of multi-keyed hashing scheme to speed up searching. .SH FILES .nf .ta \w'/usr/lib/mand.hosts 'u /etc/services list of service port numbers /usr/lib/mand.cf configuration file /usr/lib/mand.hf help file /usr/lib/mand.hosts host name/type file .fi .SH "SEE ALSO" rman(1), sendmail(8) .SH AUTHOR Jonathan C. Broome (broome@ucb-vax.berkeley.edu) !Funky!Stuff! if test 2928 -ne "`wc -c < 'mand.8'`" then echo shar: error transmitting "'mand.8'" '(should have been 2928 characters)' fi fi # end of overwriting check echo shar: extracting "'getline.c'" '(986 characters)' if test -f 'getline.c' then echo shar: will not over-write existing file "'getline.c'" else cat << \!Funky!Stuff! > 'getline.c' #ifndef lint static char RCSid[] = "$Header: getline.c,v 1.1 85/08/04 13:59:54 broome Exp $"; #endif /* * $Log: getline.c,v $ * Revision 1.1 85/08/04 13:59:54 broome * Initial revision * */ #include <stdio.h> /* * Read at most _maxlen_ characters into the buffer pointed to by line. * Strips newlines, allows escaped newlines, turns tabs to spaces, and * eats comments beginning with a `#' sign. */ getline (line, maxlen, fp) char *line; int maxlen; FILE *fp; { register int ch, len = maxlen, comment = 0; while (len && (ch = getc (fp)) != EOF) { if (ch == '\n') break; if (ch == '#') comment = 1; if (comment) continue; if (ch == '\\') if ((ch = getc (fp)) == '\n') continue; if (ch == '\t') ch = ' '; *line++ = ch; len--; } if (ch == EOF) /* at EOF */ return (0); *line = '\0'; return (1); } !Funky!Stuff! if test 986 -ne "`wc -c < 'getline.c'`" then echo shar: error transmitting "'getline.c'" '(should have been 986 characters)' fi fi # end of overwriting check echo shar: extracting "'.version'" '(3 characters)' if test -f '.version' then echo shar: will not over-write existing file "'.version'" else cat << \!Funky!Stuff! > '.version' 12 !Funky!Stuff! if test 3 -ne "`wc -c < '.version'`" then echo shar: error transmitting "'.version'" '(should have been 3 characters)' fi fi # end of overwriting check echo shar: extracting "'newver.csh'" '(231 characters)' if test -f 'newver.csh' then echo shar: will not over-write existing file "'newver.csh'" else cat << \!Funky!Stuff! > 'newver.csh' #! /bin/csh -f set date = `date` if (-e .version) then set version = ` awk '{ print $1 + 1 }' .version ` else set version = 1 endif echo $version >! .version sed -e "s;DATE;$date;;" -e "s;VERSION;$version;;" ver.c >! version.c !Funky!Stuff! if test 231 -ne "`wc -c < 'newver.csh'`" then echo shar: error transmitting "'newver.csh'" '(should have been 231 characters)' fi chmod +x 'newver.csh' fi # end of overwriting check echo shar: extracting "'mand.hosts'" '(721 characters)' if test -f 'mand.hosts' then echo shar: will not over-write existing file "'mand.hosts'" else cat << \!Funky!Stuff! > 'mand.hosts' # Recognized host addresses and their machine type. # # For those of you wondering why on earth we use # addresses in this file rather than names, the # gethostbyaddr() call takes forever!!! 128.32.149.3 generic # ucbseymour 128.32.149.5 generic # ucbbuddy 128.32.137.1 generic # ucbcory 128.32.149.4 generic # ucbholden 128.32.137.2 pdp # ucbholden-il 128.32.4 generic # ucbarpa arpa 128.32.5 cad # ucbcad cad 128.32.6 generic # ucbernie ernie 128.32.9 generic # ucbesvax esvax 128.32.10 generic # ucbvax vax 128.32.12 generic # ucbcalder calder 128.32.24 ucf # ucbmiro miro 128.32.132.1 cad # ucbic ic 128.32.132.2 cad # ucbicw icw 128.32.132.3 cad # ucbcad-ec cad-ec 128.32.132.4 cad # ucbsim sim !Funky!Stuff! if test 721 -ne "`wc -c < 'mand.hosts'`" then echo shar: error transmitting "'mand.hosts'" '(should have been 721 characters)' fi fi # end of overwriting check echo shar: done with directory "'daemon'" cd .. # End of shell archive exit 0