A compiled 'man' program for System V
sources-request at panda.UUCP
sources-request at panda.UUCP
Thu Dec 26 13:13:48 AEST 1985
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 at 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 at 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 at 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 at 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."
More information about the Mod.sources
mailing list