home *** CD-ROM | disk | FTP | other *** search
- From: genrad!decvax!ukma!ukecc!edward
- Subject: A compiled 'man' program for System V
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 70
- Submitted by: cbosgd!ukma!ukecc!edward (Edward C. Bennett)
-
- In System V (at least on our 3B20) the man(1) command is a shell
- script and, because it calls nroff *every time*, it is painfully slow to
- use. Even the catman(1) command, which uses preformatted and packed versions
- of the man pages, takes a noticeably long time to get your data on-screen.
- Furthermore, catman(1) has no easy way to keep the /usr/catman files up-
- to-date. Such is the inspiration for this new version of man(1).
- This version of man(1) eliminates all these problems. It is compiled
- rather than interpreted to increase speed.
- [This program compiles on BSD4.2 after changing <string.h> to <strings.h>
- and converting calls to strchr() to index() - moderator ]
- It uses the /usr/catman files
- to avoid repetative nroff'ing. And checks to see if the formatted version
- postdates the raw version and if not, a new formatted version is created.
- This automates the problem of maintaining a current manual.
- Additionally, the program allows you to select the order that the
- sections are searched. This way you can put little-used sections like 5
- and 8 at the end of the line. The program also looks at the environment
- variable PAGER for a preferred paging program, finding none it uses a
- preselected default. An option is provided to look for man pages applicable
- to a given keyword.
-
- #! /bin/sh
- : This is a shell archive, meaning:
- : 1. Remove everything above the '#! /bin/sh' line.
- : 2. Save the resulting text in a file.
- : 3. Execute the file with /bin/sh '(not csh)' to create the files:
- : 'README'
- : 'Makefile'
- : 'man.1'
- : 'man.c'
- : 'mkxref.c'
- : 'updateall.c'
- : This archive created: 'Mon Dec 23 16:31:07 1985'
- : By: 'Edward C. Bennett'
- export PATH; PATH=/bin:$PATH
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat >'README' <<\SHAR_EOF
- To set this system up:
-
- Check the makefile to be sure all paths are OK.
-
- Su to 'root' and do "make convert"
-
- Compile the updateall command. This should be run at an off
- hour as it takes quite awhile.
- SHAR_EOF
- fi
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat >'Makefile' <<\SHAR_EOF
- # makefile of System V man program
- #
- # AUTHOR
- # Edward C. Bennett, edward@ukecc.UUCP
- #
- # Copyright 1985 by Edward C. Bennett
- #
- # Permission is given to alter this code as needed to adapt it to forign
- # systems provided that this header is included and that the original
- # author's name is preserved.
-
- USRBIN=/usr/bin
- MANOWN=bin
-
- man: man.c
- cc -O man.c -o man
-
- xref: mkxref
- mkxref > /usr/man/xref
-
- mkxref: mkxref.c
- cc -O mkxref.c -o mkxref
-
- updateall: updateall.c
- cc -O updateall.c -o updateall
-
- install: man
- /etc/install -f ${USRBIN} man
- chown ${MANOWN} ${USRBIN}/man
- chmod 4755 ${USRBIN}/man
-
- convert: man mkxref
- mv ${USRBIN}/man ${USRBIN}/oman
- mv /usr/man/u_man/man1/man.1 /usr/man/u_man/man1/oman.1
- /etc/install -f ${USRBIN} man
- chown ${MANOWN} ${USRBIN}/man
- chmod 4755 ${USRBIN}/man
- mkxref > /usr/man/xref
- chown ${MANOWN} /usr/bin/xref
-
- clean:
- rm -f man mkxref updateall
-
- shar:
- shar README Makefile man.1 man.c mkxref.c updateall.c > man.shar
- SHAR_EOF
- fi
- if test -f 'man.1'
- then
- echo shar: will not over-write existing file "'man.1'"
- else
- cat >'man.1' <<\SHAR_EOF
- .TH MAN 1 "23 December 1985"
- .SH NAME
- man \- print manual pages
- .SH SYNOPSIS
- .B man
- [
- .B section
- ]
- title
- .PP
- .B man \-k keyword
- .SH DESCRIPTION
- .I Man
- finds and prints pages from the on-line manual.
- To speed things up,
- .I man
- keeps preformatted and packed versions of the manual pages
- in the /usr/catman directory.
- The date of the formatted version is checked against the date
- of the raw version and if the raw version is newer,
- a new formatted version is created with
- .IR nroff (1)
- and
- .IR pack (1).
- .PP
- The environmental variable PAGER is checked for a preferred
- paging program.
- If none is specified,
- .IR pg (1)
- is used.
- .PP
- If
- .I man
- is used with the \-k option,
- a list of all subject lines is searched for the given keyword.
- This is useful if you don't know the name of a command,
- but you know what it does.
- .SH FILES
- .TP 38
- /usr/man/[apu]_man/man[1-8]/*
- unformatted pages
- .TP 38
- /usr/catman/[apu]_man/man[1-8]/*.z
- formatted, packed pages
- .TP 38
- /usr/man/xref
- collection of title lines
- .SH AUTHOR
- Edward C. Bennett
- .SH DIAGNOSTICS
- Hopefully self-explanatory.
- .SH BUGS
- .I Man
- only prints the first manual entry with the given title that it finds.
- To keep things simple,
- .IR nroff (1)
- uses no fancy options.
- The \-k option should search for multiple keywords.
- SHAR_EOF
- fi
- if test -f 'man.c'
- then
- echo shar: will not over-write existing file "'man.c'"
- else
- cat >'man.c' <<\SHAR_EOF
- /*
- * man - view the on-line manual
- *
- * man [ section ] title
- *
- * man -k keyword
- *
- * This manual program is designed primarily for a speed increase
- * in viewing the manual. Rather than run nroff every time a man page is
- * requested, pre-formatted packed versions of the pages are kept in the
- * /usr/catman directory and pcat is used to read them. This agrees with
- * System V's catman program. This program stats both the unformatted and
- * formatted versions of the requested page and, if the formatted page is
- * up-to-date, it is printed, otherwise a new packed page is created with
- * nroff and pack. This automates the task of keeping up-to-date man pages
- * on-line. The environmental variable PAGER is checked for a preferred
- * pager, if none is specified /usr/bin/pg is used. To keep things simple,
- * nroff uses no fancy options.
- * With the -k option, the /usr/man/xref database is searched for the
- * given keyword.
- *
- * AUTHOR
- * Edward C. Bennett, edward@ukecc.UUCP
- *
- * Copyright 1985 by Edward C. Bennett
- *
- * Permission is given to alter this code as needed to adapt it to forign
- * systems provided that this header is included and that the original
- * author's name is preserved.
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
- #include <string.h>
-
- #define DEFPAGER "/usr/bin/pg"
- #define GREP "/bin/grep"
- #define XREF "/usr/man/xref"
-
- /*
- * These are the directories under /usr/man that are to be searched for the
- * requested man page. The order in the array is the order of the search
- * so to minimize searching effort the more frequently used sections should
- * go at the top.
- */
- char *mandirs[] = {
- "u_man/man1",
- "p_man/man2",
- "p_man/man3",
- "u_man/man6",
- "p_man/man4",
- "p_man/man5",
- "a_man/man1",
- "a_man/man7",
- "a_man/man8",
- };
- #define NUMDIRS sizeof(mandirs)/sizeof(char *)
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *manpage, *pager, *section, *title, *Findpage(), *getenv();
- char cmd[BUFSIZ], catbuf[BUFSIZ], catbufz[BUFSIZ];
- int status;
- void exit();
- struct stat manstat, catstat;
-
- if (!strcmp(argv[1], "-k")) {
- execl(GREP, GREP, argv[2], XREF, 0);
- }
-
- switch (argc) {
- case 2:
- title = argv[1];
- section = NULL;
- break;
-
- case 3:
- title = argv[2];
- section = argv[1];
- break;
-
- default:
- fprintf(stderr, "Usage: %s [ section ] title\n", argv[0]);
- exit(1);
- }
-
- if ((pager = getenv("PAGER")) == NULL)
- pager = DEFPAGER;
-
- chdir("/usr/man");
-
- if ((manpage = Findpage(title, section)) == NULL) {
- if (section)
- printf("No entry for %s in section %s of the manual\n", title, section);
- else
- printf("No manual entry for %s\n", title);
- exit(1);
- }
-
- strcpy(catbuf, "/usr/catman/");
- strcat(catbuf, manpage);
- strcpy(catbufz, catbuf);
- strcat(catbufz, ".z");
-
- stat(manpage, &manstat);
- if (stat(catbufz, &catstat) == -1)
- catstat.st_mtime = -1;
-
- if (catstat.st_mtime < manstat.st_mtime) {
- unlink(catbufz);
- printf("Reformatting page, wait...");
- fflush(stdout);
- if (fork() == 0) {
- sprintf(cmd, "nroff -man %s > %s", manpage, catbuf);
- execl("/bin/sh", "sh", "-c", cmd, 0);
- }
- wait(&status);
- printf("\nCompressing output, wait...");
- fflush(stdout);
- if (fork() == 0) {
- sprintf(cmd, "pack -f %s", catbuf);
- execl("/bin/sh", "sh", "-c", cmd, 0);
- }
- wait(&status);
- }
-
- /*
- * Do this in case the user does something like 'man curses > file'
- */
- if (isatty(1))
- sprintf(cmd, "pcat %s | %s", catbuf, pager);
- else
- sprintf(cmd, "pcat %s", catbuf);
-
- execl("/bin/sh", "sh", "-c", cmd, 0);
- }
-
- /*
- * Findpage - determine the pathname of the requested page
- *
- * path = Findpage(title, sect);
- * path is a pointer to the requested path
- * title is a pointer to the title of the requested page
- * sect is a pointer to the section to search, NULL if all sections
- *
- * Findpage() returns a pointer to a buffer containing the path name
- * of the unformatted version of the request man page in the form
- * [apu]_man/man[1-8]/title.[1-8]. The user can specify a section to search.
- * This is needed for cases like write(1) and write(2). If 'section' is given
- * as NULL, all sections are searched. If no match for title.sect can be found,
- * NULL is returned.
- */
- char *
- Findpage(title, sect)
- char *title, *sect;
- {
- int fd, i, len, tlen;
- long lseek();
- static char manbuf[BUFSIZ];
- struct direct manent;
-
- tlen = strlen(title);
- for (i = 0; i < NUMDIRS; i++) {
- if (sect && *sect != *(mandirs[i] + 9))
- continue;
-
- if ((fd = open(mandirs[i], O_RDONLY)) == -1)
- continue;
-
- /*
- * Skip "." and ".."
- */
- lseek(fd, 2*sizeof(manent), 0);
- while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
- if (manent.d_ino == 0)
- continue;
-
- len = (int)(strchr(manent.d_name, '.') - manent.d_name);
- if (!strncmp(manent.d_name, title, (len > tlen ? len : tlen))) {
- if (sect && strcmp(sect, manent.d_name+len+1))
- continue;
-
- sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
- return(manbuf);
- }
- }
- }
- return(NULL);
- }
- SHAR_EOF
- fi
- if test -f 'mkxref.c'
- then
- echo shar: will not over-write existing file "'mkxref.c'"
- else
- cat >'mkxref.c' <<\SHAR_EOF
-
- /*
- * mkxref - a program to list the titles from man pages
- *
- * All files in /usr/man/?_man/man? are searched for their title lines.
- * A title line is the first line following the ".SH NAME" line. Nroff
- * escapes are removed and the lines are written to the standard output.
- * If no title line is found in a file, the file's name is printed on
- * the standard error output.
- *
- * AUTHOR
- * Edward C. Bennett, edward@ukecc.UUCP
- *
- * Copyright 1985 by Edward C. Bennett
- *
- * Permission is given to alter this code as needed to adapt it to forign
- * systems provided that this header is included and that the original
- * author's name is preserved.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/dir.h>
- #include <fcntl.h>
- #include <string.h>
-
- char *mandirs[] = {
- "u_man/man1",
- "p_man/man2",
- "p_man/man3",
- "u_man/man6",
- "p_man/man4",
- "p_man/man5",
- "a_man/man1",
- "a_man/man7",
- "a_man/man8",
- };
- #define NUMDIRS sizeof(mandirs)/sizeof(char *)
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char manbuf[BUFSIZ];
- int fd, i, len;
- long lseek();
- struct direct manent;
-
- chdir("/usr/man");
-
- for (i = 0; i < NUMDIRS; i++) {
- if ((fd = open(mandirs[i], O_RDONLY)) == -1)
- continue;
-
- /*
- * Skip "." and ".."
- */
- lseek(fd, 2*sizeof(manent), 0);
- while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
- if (manent.d_ino == 0)
- continue;
-
- sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
- Findname(manbuf);
- }
- }
- }
-
- Findname(manfile)
- char *manfile;
- {
- char *p, line[BUFSIZ], section[4];
- int i, flag = 0;
- FILE *fp;
-
- strcpy(section, strchr(manfile, '.')+1);
- if ((fp = fopen(manfile, "r")) == NULL)
- return;
-
- while (fgets(line, BUFSIZ, fp) != NULL) {
- if (!strncmp(line, ".SH NAME", 8)) {
- flag++;
- if ((p = fgets(line, BUFSIZ, fp)) != NULL) {
- i = 0;
- while (*p) {
- /*
- * Remove escapes
- */
- if (*p == '\\') {
- if (*++p == 's') {
- if (*++p == '-' || *p == '+') {
- p++;
- i--;
- }
- p++;
- i -= 2;
- }
- else if (*p == '*') {
- p += 2;
- i -= 3;
- }
- else if (*p == '&') {
- p++;
- i -= 2;
- }
- else if (*p == '-') {
- printf("(%s) ", section, ")");
- for (i += (int)(p - line) + strlen(section); i < 25; i++)
- putchar(' ');
- putchar(*p++);
- }
- else
- putchar(*p++);
- }
- else
- putchar(*p++);
- }
- }
- break;
- }
- }
- if (!flag)
- fprintf(stderr, "%s\n", manfile);
- fclose(fp);
-
- return;
- }
- SHAR_EOF
- fi
- if test -f 'updateall.c'
- then
- echo shar: will not over-write existing file "'updateall.c'"
- else
- cat >'updateall.c' <<\SHAR_EOF
- /*
- * updateall - update the /usr/catman files
- *
- * All of the unformatted manual pages are checked against the copies
- * in the /usr/catman directory. If the unformatted copy is newer, a
- * new formatted and packed copy is placed in /usr/catman.
- *
- * AUTHOR
- * Edward C. Bennett, edward@ukecc.UUCP
- *
- * Copyright 1985 by Edward C. Bennett
- *
- * Permission is given to alter this code as needed to adapt it to forign
- * systems provided that this header is included and that the original
- * author's name is preserved.
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/dir.h>
- #include <string.h>
-
- char *mandirs[] = {
- "u_man/man1",
- "p_man/man2",
- "p_man/man3",
- "u_man/man6",
- "p_man/man4",
- "p_man/man5",
- "a_man/man1",
- "a_man/man7",
- "a_man/man8",
- };
- #define NUMDIRS sizeof(mandirs)/sizeof(char *)
-
- main()
- {
- char manbuf[BUFSIZ], cmd[BUFSIZ], catbuf[BUFSIZ], catbufz[BUFSIZ];
- int status;
- void exit();
- struct stat manstat, catstat;
- int fd, i;
- long lseek();
- struct direct manent;
-
- chdir("/usr/man");
-
- for (i = 0; i < NUMDIRS; i++) {
-
- if ((fd = open(mandirs[i], O_RDONLY)) == -1)
- continue;
-
- lseek(fd, 2*sizeof(manent), 0);
- while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
- if (manent.d_ino == 0)
- continue;
-
- sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
-
- strcpy(catbuf, "/usr/catman/");
- strcat(catbuf, manbuf);
- strcpy(catbufz, catbuf);
- strcat(catbufz, ".z");
-
- stat(manbuf, &manstat);
- if (stat(catbufz, &catstat) == -1)
- catstat.st_mtime = -1;
-
- if (catstat.st_mtime < manstat.st_mtime) {
- unlink(catbufz);
- if (fork() == 0) {
- sprintf(cmd, "nroff -man %s > %s", manbuf, catbuf);
- execl("/bin/sh", "sh", "-c", cmd, 0);
- }
- wait(&status);
- if (fork() == 0) {
- sprintf(cmd, "pack -f %s", catbuf);
- execl("/bin/sh", "sh", "-c", cmd, 0);
- }
- wait(&status);
- }
- }
- }
- }
- SHAR_EOF
- fi
- : End of shell archive
- exit 0
-
- Edward C. Bennett
-
- UUCP: ihnp4!cbosgd!ukma!ukecc!edward
-
- /* A charter member of the Scooter bunch */
-
- "Goodnight M.A."
-
-
-