mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-06-10 03:29:29 +00:00
makewhatis version 1.0 (later to be incorporated in the manpack archive)
This commit is contained in:
parent
c89ef9549f
commit
39f4efc5b8
14
usr.bin/man/README
Normal file
14
usr.bin/man/README
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--------------------------------------------
|
||||||
|
Name: makewhatis
|
||||||
|
Version: 1.0
|
||||||
|
Author: Devin Reade <glyn@cs.ualberta.ca>
|
||||||
|
Computer: Apple IIgs
|
||||||
|
Requires: Gno v2.x
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Description: Generates the whatis database for apropos(1) and whatis(1)
|
||||||
|
See the man page for a detailed description.
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
Copy makewhatis to /usr/sbin and makewhatis.1 to $(USRMAN)/man1.
|
||||||
|
Alternately, you can type "dmake install" from this directory.
|
232
usr.bin/man/fillbuffer.c
Normal file
232
usr.bin/man/fillbuffer.c
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
#ifdef __CCFRONT__
|
||||||
|
#include <14:pragma.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "makewhatis.h"
|
||||||
|
|
||||||
|
char buffer[BUFFERSIZE];
|
||||||
|
static char buffer2[BUFFERSIZE];
|
||||||
|
|
||||||
|
/* void fillbuffer (char *filename);
|
||||||
|
*
|
||||||
|
* Pre: <filename> is the name of the man page or temporary file
|
||||||
|
* containing text. It may have nroff formatting information
|
||||||
|
* or screen control codes, but must not be either a compressed
|
||||||
|
* file nor an AWGS word processor file.
|
||||||
|
*
|
||||||
|
* Post: <buffer> will contain all the text, minus formatting and control
|
||||||
|
* code, starting from the word "NAME" and ending with either ".SH".
|
||||||
|
* "SYNOPSIS", or "DESCRIPTION", whichever comes first.
|
||||||
|
*
|
||||||
|
* If an error occurs, <buffer> will be an empty string (ie:
|
||||||
|
* buffer[0] == '\0')
|
||||||
|
*/
|
||||||
|
|
||||||
|
void fillbuffer (char *filename) {
|
||||||
|
FILE *fp; /* FILE pointer for filename */
|
||||||
|
int count; /* how many chars were read into buffer2 */
|
||||||
|
char *p1; /* points to current char in buffer2 */
|
||||||
|
char *p2; /* points to last char (of interest) in buffer2 */
|
||||||
|
char *p3; /* points to current char in buffer */
|
||||||
|
short found; /* some flags */
|
||||||
|
short in_comment;
|
||||||
|
short in_format_BR;
|
||||||
|
short in_format_f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open the file
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fp = fopen(filename,"rb")) == NULL) {
|
||||||
|
buffer[0] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make p1 point to spot in buffer2 where the first "NAME" occurs.
|
||||||
|
* Note that if "NAME" is within a comment line (nroff source), it
|
||||||
|
* will still be picked up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
|
||||||
|
if (count == 0) {
|
||||||
|
/*
|
||||||
|
* eof or error, and we haven't found "NAME" yet ... return
|
||||||
|
* an empty string
|
||||||
|
*/
|
||||||
|
buffer[0] = '\0';
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer2[count] = '\0';
|
||||||
|
p1 = strstr(buffer2,"NAME");
|
||||||
|
if (p1 != NULL) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make p1 point to spot in buffer2 where there occurs the first
|
||||||
|
* character following '-' which in turn follows "NAME".
|
||||||
|
* Note that if "NAME" or '-' are within a comment line
|
||||||
|
* (nroff source), it will still be picked up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
p2 = strchr(p1,'-');
|
||||||
|
if (p2 != NULL) {
|
||||||
|
p2++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
|
||||||
|
if (count == 0) {
|
||||||
|
/*
|
||||||
|
* eof or error, and we haven't found '-' yet ... return
|
||||||
|
* an empty string
|
||||||
|
*/
|
||||||
|
buffer[0] = '\0';
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer2[count] = '\0';
|
||||||
|
p1 = buffer2;
|
||||||
|
}
|
||||||
|
p1 = p2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now copy selected chars to buffer until the next subheading is found
|
||||||
|
*/
|
||||||
|
|
||||||
|
p3 = buffer;
|
||||||
|
found = 0; /* set this when we find one of the above strings */
|
||||||
|
in_format_BR = 0; /* in the middle of a .BR format */
|
||||||
|
in_format_f = 0; /* in the middle of a \fI format */
|
||||||
|
in_comment = 0; /* in the middle of a .\" comment */
|
||||||
|
for(;;) {
|
||||||
|
|
||||||
|
/* mark the "end" of buffer2 with p2 */
|
||||||
|
if ( ((p2 = strstr(p1,".SH")) != NULL) ||
|
||||||
|
((p2 = strstr(p1,"SYNOPSIS")) != NULL) ||
|
||||||
|
((p2 = strstr(p1,"DESCRIPTION")) != NULL)
|
||||||
|
) {
|
||||||
|
found = 1;
|
||||||
|
} else {
|
||||||
|
p2 = buffer + count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is not our first iteration, dump any formatting information
|
||||||
|
* or comments left over from the last interation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (in_comment) {
|
||||||
|
while((p1<p2) && (*p1 != '\r')) p1++;
|
||||||
|
in_comment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_format_BR) {
|
||||||
|
while ((p1<p2) && !isspace(*p1)) p1++;
|
||||||
|
in_format_BR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_format_f) {
|
||||||
|
p1 = p1 + 3 - in_format_f;
|
||||||
|
in_format_f = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this time, p1 points to the start of the description, p2
|
||||||
|
* to either the end of the description or the end of buffer2,
|
||||||
|
* and p3 into the spot in buffer where the next character should
|
||||||
|
* be put.
|
||||||
|
*
|
||||||
|
* Copy *p1 to *p3 while p1<p2 (not at end of buffer or description),
|
||||||
|
* skipping comments, formatting info, and control chars
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (; p1<p2; p1++) {
|
||||||
|
|
||||||
|
/* skip .\" comments */
|
||||||
|
if (strncmp(p1,"\r.\\\"",4) == 0) {
|
||||||
|
while ((p1<p2) && (*p1!='\r')) p1++;
|
||||||
|
if (p1==p2) in_comment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip .BR-type formatting */
|
||||||
|
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
|
||||||
|
while ((p1<p2) && !isspace(*p1)) p1++;
|
||||||
|
if (p1==p2) in_format_BR = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip \fI-type formatting */
|
||||||
|
if ((p1<p2) && (*p1=='\\') && (*(p1+1)=='f')) {
|
||||||
|
if ((p1 + 3) < p2) {
|
||||||
|
p1 += 3;
|
||||||
|
} else {
|
||||||
|
in_format_f = p2 - p1;
|
||||||
|
p1 = p2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* at this point, *p1 is either a control char or something that
|
||||||
|
* we want in buffer, assuming that p1<p2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((p1<p2) && !iscntrl(*p1)) *p3++ = *p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) { /* we've got the entire description */
|
||||||
|
*p3 = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're part way through the description; read another block
|
||||||
|
* into buffer2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
|
||||||
|
if (count == 0) {
|
||||||
|
/* eof or error; terminate buffer and return */
|
||||||
|
*p3 = '\0';
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p1 = buffer2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close the file
|
||||||
|
*/
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TEST_FILLBUFFER
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s <man_page_file_name>\n\n",argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fillbuffer(argv[1]);
|
||||||
|
|
||||||
|
if (strlen(buffer) == 0) {
|
||||||
|
printf("buffer empty\n");
|
||||||
|
} else {
|
||||||
|
printf("main: buffer is %u chars long\n%s\n",strlen(buffer),buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
47
usr.bin/man/makefile.mk
Normal file
47
usr.bin/man/makefile.mk
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#
|
||||||
|
# Makefile for dmake(1)
|
||||||
|
#
|
||||||
|
|
||||||
|
# Location for executable. It should be /usr/sbin
|
||||||
|
|
||||||
|
BINDIR = /usr/sbin
|
||||||
|
|
||||||
|
# Location for man pages.
|
||||||
|
|
||||||
|
MANDIR = /usr/man
|
||||||
|
|
||||||
|
#
|
||||||
|
# Nothing past this point should have to be changed
|
||||||
|
#
|
||||||
|
|
||||||
|
CFLAGS = -w -O -v
|
||||||
|
OBJS = makewhatis.o fillbuffer.o process.o
|
||||||
|
|
||||||
|
makewhatis: $(OBJS)
|
||||||
|
$(CC) $(OBJS) -o makewhatis
|
||||||
|
|
||||||
|
makewhatis.o: makewhatis.c makewhatis.h
|
||||||
|
$(CC) -c $(CFLAGS) makewhatis.c
|
||||||
|
|
||||||
|
fillbuffer.o: fillbuffer.c makewhatis.h
|
||||||
|
$(CC) -c $(CFLAGS) fillbuffer.c
|
||||||
|
|
||||||
|
process.o: process.c makewhatis.h
|
||||||
|
$(CC) -c $(CFLAGS) process.c
|
||||||
|
|
||||||
|
install:
|
||||||
|
/bin/cp makewhatis $(BINDIR)
|
||||||
|
/bin/cp makewhatis.1 $(MANDIR)/man1
|
||||||
|
|
||||||
|
clean:
|
||||||
|
/bin/cp -p rm $(OBJS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# These are just for debugging purposes
|
||||||
|
#
|
||||||
|
|
||||||
|
fillbuffer: fillbuffer.c makewhatis.h
|
||||||
|
$(CC) $(CFLAGS) -DTEST_FILLBUFFER -o fillbuffer fillbuffer.c
|
||||||
|
|
||||||
|
process: process.o fillbuffer.o
|
||||||
|
$(CC) $(CFLAGS) process.o fillbuffer.o -o process
|
190
usr.bin/man/makewhatis.8
Normal file
190
usr.bin/man/makewhatis.8
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
.TH MAKEWHATIS 1 "Commands and Applications" "15 May 1994" "Version 1.0"
|
||||||
|
.SH NAME
|
||||||
|
.B makewhatis
|
||||||
|
\- generate the whatis database file
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B makewhatis
|
||||||
|
[
|
||||||
|
.I -c
|
||||||
|
|
|
||||||
|
.I -C
|
||||||
|
] [
|
||||||
|
.I -ovV
|
||||||
|
] [
|
||||||
|
.I "-f outfile"
|
||||||
|
] [
|
||||||
|
.I "-l logfile"
|
||||||
|
] [
|
||||||
|
.I "-p path"
|
||||||
|
]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B makewhatis
|
||||||
|
generates the whatis database for
|
||||||
|
.BR whatis "(1) and " apropos "(1)."
|
||||||
|
This database is a text file containing line oriented records. Each record
|
||||||
|
contains a man page name, the section number, and the brief description.
|
||||||
|
.LP
|
||||||
|
By default,
|
||||||
|
.B makewhatis
|
||||||
|
makes use of one of the environment variables \fIMANPATH\fR, \fIUSRMAN\fR,
|
||||||
|
or \fIMANDIR\fR, in the listed order of preference. It will use this
|
||||||
|
environment variable to determine for which manual pages the whatis
|
||||||
|
database should be built. If the environment variable contains more than
|
||||||
|
one path (delimited by spaces), then whatis databases will be generated
|
||||||
|
in all of the specified paths.
|
||||||
|
.LP
|
||||||
|
The routines used are compatible with man pages in
|
||||||
|
.BR nroff ,
|
||||||
|
.BR aroff ,
|
||||||
|
.BR compress ", or"
|
||||||
|
.BR freeze
|
||||||
|
format, as well as text versions of manual pages in the man/catX hierarchy.
|
||||||
|
.B Makewhatis
|
||||||
|
assumes that the suffixes \fI.Z\fR and \fI.F\fR are are appended to the
|
||||||
|
chapter number on file names when those files are in
|
||||||
|
.BR compress " or " freeze
|
||||||
|
format, respectively. (For example, a compressed file would be expected
|
||||||
|
to have a file name similar to
|
||||||
|
.I foo.3.Z
|
||||||
|
or \fIbar.3v.Z\fR.)
|
||||||
|
Any files using the
|
||||||
|
.I ".l"
|
||||||
|
(ell) suffix are ignored. All suffix tests are case insensitive.
|
||||||
|
.LP
|
||||||
|
By default,
|
||||||
|
.B makewhatis
|
||||||
|
will only use files in the man/manX hierarchy in the creation of the
|
||||||
|
database. However, since many Gno programmers are providing only text
|
||||||
|
versions of their man pages, invoking
|
||||||
|
.B makewhatis
|
||||||
|
with the
|
||||||
|
.I -c
|
||||||
|
flag will add descriptions for all files in the man/catX hierarchy that
|
||||||
|
don't have a counterpart in the man/manX hierarchy. This conditional
|
||||||
|
eliminates the parsing of files in man/catX generated by
|
||||||
|
.BR catman (1).
|
||||||
|
.LP
|
||||||
|
Note that the lines in the whatis database file are created in the order
|
||||||
|
that the man pages are found. It is suggested that the database be sorted
|
||||||
|
after
|
||||||
|
.B makewhatis
|
||||||
|
is finished. See
|
||||||
|
.BR sort (1).
|
||||||
|
.SH OPTIONS
|
||||||
|
.I -c
|
||||||
|
will check man/catX sub-directories as well as man/manX
|
||||||
|
.LP
|
||||||
|
.I -C
|
||||||
|
will check
|
||||||
|
.BR only
|
||||||
|
man/catX sub-directories, not man/manX sub-directories.
|
||||||
|
.LP
|
||||||
|
.I "-f outfile"
|
||||||
|
causes the
|
||||||
|
.B makewhatis
|
||||||
|
status output to be placed in \fIoutfile\fR.
|
||||||
|
.LP
|
||||||
|
.I "-l logfile"
|
||||||
|
will cause any error messages to be printed to \fIlogfile\fR.
|
||||||
|
.LP
|
||||||
|
.I "-o dbfile"
|
||||||
|
will make
|
||||||
|
.B makewhatis
|
||||||
|
use
|
||||||
|
.I dbfile
|
||||||
|
as the name for the generated whatis databases.
|
||||||
|
.LP
|
||||||
|
.I "-p path"
|
||||||
|
overrides the environment variables
|
||||||
|
.I MANPATH
|
||||||
|
et al for determining for which manual page hierarchies the databases must
|
||||||
|
be generated.
|
||||||
|
.LP
|
||||||
|
.I -v
|
||||||
|
creates verbose status messages during execution.
|
||||||
|
.LP
|
||||||
|
.I -V
|
||||||
|
will show version and usage information, then exit.
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
\fIMANPATH\fR, \fIUSRMAN\fR, \fIMANDIR\fR:
|
||||||
|
.br
|
||||||
|
Unless the
|
||||||
|
.I -p
|
||||||
|
flag is used,
|
||||||
|
.B makewhatis
|
||||||
|
will use the first that it finds of these environment variables for
|
||||||
|
determining where database files should be generated. While
|
||||||
|
.B makewhatis
|
||||||
|
will correctly handle
|
||||||
|
.I ~
|
||||||
|
and
|
||||||
|
.I .
|
||||||
|
being part of these paths, it will not correctly handle \fI..\fR.
|
||||||
|
.SH CAVEATS
|
||||||
|
Because
|
||||||
|
.B makewhatis
|
||||||
|
looks for the string
|
||||||
|
.I NAME
|
||||||
|
and one of \fI.SH\fR, \fISYNOPSIS\fR, or
|
||||||
|
.I DESCRIPTION
|
||||||
|
when processing files, it can be confused by missing fields or
|
||||||
|
some methods of formatting. For example, if in a man/catX page
|
||||||
|
.I NAME
|
||||||
|
is boldfaced by repeated backspace characters as in \fIN^HNA^HAM^HME^HE\fR,
|
||||||
|
then the generated description for that particular man page is unpredictable,
|
||||||
|
though usually blank. For any diehards who like placing such information
|
||||||
|
in their hand-coded man/catX pages, using a string similar to
|
||||||
|
.I "NAME^H^H^H^HNAME"
|
||||||
|
will create a proper description in the database file.
|
||||||
|
.LP
|
||||||
|
Similarily,
|
||||||
|
.B makewhatis
|
||||||
|
expects the subheading
|
||||||
|
.I NAME
|
||||||
|
to be in the format:
|
||||||
|
.nf
|
||||||
|
NAME
|
||||||
|
<command> - <brief description>
|
||||||
|
.fi
|
||||||
|
If this is not so (ignoring whitespace), then the output is unpredictable.
|
||||||
|
.LP
|
||||||
|
Where unpredictable output has been mentioned above, this means that
|
||||||
|
the description in the database file will either be blank or random
|
||||||
|
text from the man page. It
|
||||||
|
.I "does not"
|
||||||
|
mean that system integrity or that the remainder of the database file
|
||||||
|
has been affected.
|
||||||
|
.SH BUGS
|
||||||
|
If a man page describes multiple items and has a NAME subheading such as
|
||||||
|
.nf
|
||||||
|
|
||||||
|
NAME
|
||||||
|
item1, item2, item3 - This is the description.
|
||||||
|
|
||||||
|
.fi
|
||||||
|
Then
|
||||||
|
.B makewhatis
|
||||||
|
should create a database record that reads:
|
||||||
|
.nf
|
||||||
|
|
||||||
|
item1 (3), item2 (3), item3 (3) - This is the description.
|
||||||
|
|
||||||
|
.fi
|
||||||
|
Instead, if item2.l and item3.l are links to item1.3, the created record reads
|
||||||
|
.nf
|
||||||
|
|
||||||
|
item1 (3) - This is the description.
|
||||||
|
|
||||||
|
.fi
|
||||||
|
.SH FILES
|
||||||
|
.nf
|
||||||
|
/usr/sbin/makewhatis -- whatis database generator
|
||||||
|
man/whatis -- the whatis database
|
||||||
|
.fi
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR apropos (1),
|
||||||
|
.BR catman (1),
|
||||||
|
.BR man (1),
|
||||||
|
.BR whatis (1),
|
||||||
|
.SH AUTHOR
|
||||||
|
Written by Devin Reade <glyn@cs.ualberta.ca> for the Apple IIgs and Gno.
|
307
usr.bin/man/makewhatis.c
Normal file
307
usr.bin/man/makewhatis.c
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
#ifdef __CCFRONT__
|
||||||
|
#include <14:pragma.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
#include "makewhatis.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Options:
|
||||||
|
*
|
||||||
|
* -c check cat* subdirectories as well
|
||||||
|
* -C check _only_ cat* subdirectories, not man* subdirectories.
|
||||||
|
* -f outfile force whatis status output to <outfile>
|
||||||
|
* -l logfile log errors to <logfile>
|
||||||
|
* -o dbfile force whatis database output to <dbfile>
|
||||||
|
* -p path use the <path> rather than $MANPATH, $USRMAN, or $MANDIR
|
||||||
|
* -s sort the whatis database by manual page name
|
||||||
|
* -v verbose
|
||||||
|
* -V show version and usage info and exit
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *man_subdir[] = {
|
||||||
|
"man1",
|
||||||
|
"man2",
|
||||||
|
"man3",
|
||||||
|
"man4",
|
||||||
|
"man5",
|
||||||
|
"man6",
|
||||||
|
"man7",
|
||||||
|
"man8",
|
||||||
|
"mann",
|
||||||
|
"manl",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* For the various command line flags */
|
||||||
|
|
||||||
|
short c_flag = 0;
|
||||||
|
short C_flag = 0;
|
||||||
|
short o_flag = 0;
|
||||||
|
short p_flag = 0;
|
||||||
|
short v_flag = 0;
|
||||||
|
short errflag = 0; /* This is set if there is a usage error or -V flag */
|
||||||
|
|
||||||
|
static char filebuffer[FILENAME_MAX]; /* used when traversing cat* pages */
|
||||||
|
static char progdir[FILENAME_MAX]; /* the directory where makewhatis started */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we include cat* since some Gno utility man pages aren't written in
|
||||||
|
* either nroff or aroff source ... go figure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *cat_subdir[] = {
|
||||||
|
"cat1",
|
||||||
|
"cat2",
|
||||||
|
"cat3",
|
||||||
|
"cat4",
|
||||||
|
"cat5",
|
||||||
|
"cat6",
|
||||||
|
"cat7",
|
||||||
|
"cat8",
|
||||||
|
"catn",
|
||||||
|
"catl",
|
||||||
|
NULL /* _must_ be NULL terminated! */
|
||||||
|
};
|
||||||
|
|
||||||
|
FILE *output_fp;
|
||||||
|
FILE *error_fp;
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
|
||||||
|
char *manpath; /* the location of the man pages */
|
||||||
|
char *path; /* the current path; taken from manpath */
|
||||||
|
char *p=NULL; /* a temporary pointer */
|
||||||
|
struct dirent *file; /* the current file we have open */
|
||||||
|
char tmp_file[L_tmpnam]; /* a scratch file */
|
||||||
|
FILE *tmp_fp; /* pointer to tmp_file */
|
||||||
|
FILE *whatis_fp; /* pointer to the current whatis database */
|
||||||
|
DIR *subdir; /* the current man subdirectory -- eg: /usr/man/man3 */
|
||||||
|
char *dbfile; /* non-default name of the whatis database */
|
||||||
|
char *dirsep; /* the directory separator, either "/" or ":" */
|
||||||
|
int i;
|
||||||
|
extern int optind;
|
||||||
|
extern char *optarg;
|
||||||
|
|
||||||
|
/* make sure Gno is running */
|
||||||
|
if (needsgno()==0) {
|
||||||
|
fprintf(stderr,"Requires Gno/ME\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the defaults
|
||||||
|
*/
|
||||||
|
|
||||||
|
output_fp = stdout;
|
||||||
|
error_fp = stderr;
|
||||||
|
if (getwd(progdir) == NULL) {
|
||||||
|
perror("getwd() failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse the command line
|
||||||
|
*/
|
||||||
|
|
||||||
|
while((i = getopt(argc,argv,"cCf:l:o:p:vV")) != EOF)
|
||||||
|
switch(i) {
|
||||||
|
case 'c':
|
||||||
|
if (C_flag) errflag++;
|
||||||
|
else c_flag++;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
if (c_flag) errflag++;
|
||||||
|
else C_flag++;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
output_fp = fopen (optarg,"w");
|
||||||
|
if (output_fp == NULL) {
|
||||||
|
fprintf(stderr,"Could not open output file %s; using stdout.\n",
|
||||||
|
optarg);
|
||||||
|
output_fp = stdout;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
error_fp = fopen (optarg,"w");
|
||||||
|
if (error_fp == NULL) {
|
||||||
|
fprintf(stderr,"Could not open log file %s; using stderr.\n",
|
||||||
|
optarg);
|
||||||
|
error_fp = stderr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
o_flag++;
|
||||||
|
dbfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
p_flag++;
|
||||||
|
p = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
v_flag++;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s -- Create the %s database.\n\tVersion %s by Devin Reade\n\n",
|
||||||
|
argv[0],WHATIS,VERSIONSTRING);
|
||||||
|
errflag++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errflag++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (errflag) {
|
||||||
|
fprintf(error_fp,
|
||||||
|
"Usage: %s [-c|-C] [-ovV] [-f outfile] [-l logfile] [-p path]\n\n\
|
||||||
|
-c\t\tCheck catX subdirectories as well\n\
|
||||||
|
-C\t\tCheck _only_ catX subdirectories, not manX subdirectories.\n\
|
||||||
|
-f outfile\tForce whatis output to <outfile>.\n\
|
||||||
|
-l logfile\tLog errors to <logfile>.\n\
|
||||||
|
-o dbfile\tforce whatis database output to <dbfile>.\n\
|
||||||
|
-p path\t\tUse the <path> rather than $MANPATH, $USRMAN, or $MANDIR.\n\
|
||||||
|
-v\t\tVerbose.\n\
|
||||||
|
-V\t\tShow version and usage information, then exit.\n",argv[0],WHATIS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the location of the man pages; p is already set if -p flag used
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (p == NULL) p = getenv("MANPATH");
|
||||||
|
if (p == NULL) p = getenv("USRMAN");
|
||||||
|
if (p == NULL) p = getenv("MANDIR");
|
||||||
|
if (p == NULL) {
|
||||||
|
fprintf(error_fp,"Location of man pages unknown. You must either define \
|
||||||
|
environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* define the directory separator */
|
||||||
|
dirsep = (strchr(p,':')==NULL) ? "/" : ":";
|
||||||
|
|
||||||
|
/* make a copy of the location */
|
||||||
|
if ((manpath = malloc (strlen(p) + 1)) == NULL) {
|
||||||
|
if (v_flag) fprintf(error_fp,"couldn't make copy of \"%s\"",p);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strcpy(manpath,p);
|
||||||
|
|
||||||
|
/* get the name of the temporary file */
|
||||||
|
tmpnam (tmp_file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* loop over all the paths in manpath. Don't use ':' as a delimiter since
|
||||||
|
* the colon is a pathname separator under GS/OS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
path = strtok (manpath," ");
|
||||||
|
while (path != NULL) {
|
||||||
|
|
||||||
|
if (access(path,F_OK)==0) {
|
||||||
|
|
||||||
|
if (strcmp(path,".") == 0) {
|
||||||
|
chdir(progdir);
|
||||||
|
} else {
|
||||||
|
chdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the whatis database file */
|
||||||
|
if (!o_flag) dbfile = WHATIS;
|
||||||
|
whatis_fp = fopen(dbfile,"w");
|
||||||
|
if (whatis_fp == NULL) {
|
||||||
|
fprintf (error_fp,
|
||||||
|
"Could not create whatis database file %s in directory %s.\n",
|
||||||
|
dbfile,path);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* loop over the expected man* subdirectories within path
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!C_flag) for (i=0; man_subdir[i] != NULL; i++) {
|
||||||
|
subdir = opendir(man_subdir[i]);
|
||||||
|
if (subdir != NULL) {
|
||||||
|
|
||||||
|
/* print status */
|
||||||
|
if (v_flag) fprintf(output_fp,
|
||||||
|
"Now working on directory %s\t%s ...\n",path,man_subdir[i]);
|
||||||
|
|
||||||
|
/* no need to error check because of opendir() */
|
||||||
|
chdir(man_subdir[i]);
|
||||||
|
|
||||||
|
/* loop over files within subdirectory */
|
||||||
|
while ((file = readdir(subdir)) != NULL) {
|
||||||
|
process (file->d_name,tmp_file,whatis_fp);
|
||||||
|
}
|
||||||
|
closedir(subdir);
|
||||||
|
} else {
|
||||||
|
if (v_flag) fprintf(output_fp,
|
||||||
|
"Could not access files in %s\t%s ...\n",path,man_subdir[i]);
|
||||||
|
}
|
||||||
|
chdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* loop over the expected cat* subdirectories within path,
|
||||||
|
* adding only those files without man* versions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (c_flag||C_flag) for (i=0; cat_subdir[i] != NULL; i++) {
|
||||||
|
subdir = opendir(cat_subdir[i]);
|
||||||
|
if (subdir != NULL) {
|
||||||
|
|
||||||
|
/* print status */
|
||||||
|
if (v_flag) fprintf(output_fp,
|
||||||
|
"Now working on directory %s\t%s ...\n",path,cat_subdir[i]);
|
||||||
|
|
||||||
|
/* no need to error check because of opendir() */
|
||||||
|
chdir(cat_subdir[i]);
|
||||||
|
|
||||||
|
/* make filebuffer contain path to matching man* subdirectory */
|
||||||
|
strcpy(filebuffer,path);
|
||||||
|
strcat(filebuffer,dirsep);
|
||||||
|
strcat(filebuffer,man_subdir[i]);
|
||||||
|
strcat(filebuffer,dirsep);
|
||||||
|
p = filebuffer + strlen(filebuffer); /* p points to '\0' */
|
||||||
|
|
||||||
|
/* loop over files that don't have a man* counterpart */
|
||||||
|
while ((file = readdir(subdir)) != NULL) {
|
||||||
|
strcpy(p,file->d_name);
|
||||||
|
if (access(filebuffer,F_OK)!=0)
|
||||||
|
process (file->d_name,tmp_file,whatis_fp);
|
||||||
|
}
|
||||||
|
closedir(subdir);
|
||||||
|
} else {
|
||||||
|
if (v_flag) fprintf(output_fp,
|
||||||
|
"Could not access files in %s\t%s ...\n",path,cat_subdir[i]);
|
||||||
|
}
|
||||||
|
chdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the database */
|
||||||
|
fclose(whatis_fp);
|
||||||
|
|
||||||
|
}
|
||||||
|
/* get the next path in manpath */
|
||||||
|
path = strtok (NULL," ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* clean up and exit */
|
||||||
|
unlink(tmp_file);
|
||||||
|
if (output_fp != stdout) fclose(output_fp);
|
||||||
|
if (error_fp != stderr) fclose(error_fp);
|
||||||
|
return 0;
|
||||||
|
}
|
25
usr.bin/man/makewhatis.h
Normal file
25
usr.bin/man/makewhatis.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#define VERSIONSTRING "1.0"
|
||||||
|
|
||||||
|
/* The size of the IO buffers */
|
||||||
|
#define BUFFERSIZE 1024
|
||||||
|
|
||||||
|
/* The default name for the whatis database */
|
||||||
|
#define WHATIS "whatis"
|
||||||
|
|
||||||
|
/* The number of characters per tab in the whatis database */
|
||||||
|
#define TABLENGTH 8
|
||||||
|
|
||||||
|
extern int chdir (const char *);
|
||||||
|
extern int system (const char *);
|
||||||
|
|
||||||
|
void fillbuffer (char *filename);
|
||||||
|
void process (char *filename, char *tmp_file, FILE *whatis_fp);
|
||||||
|
|
||||||
|
extern short c_flag;
|
||||||
|
extern short C_flag;
|
||||||
|
extern short f_flag;
|
||||||
|
extern short l_flag;
|
||||||
|
extern short O_flag;
|
||||||
|
extern short p_flag;
|
||||||
|
extern short v_flag;
|
||||||
|
extern short errflag;
|
166
usr.bin/man/process.c
Normal file
166
usr.bin/man/process.c
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
#ifdef __CCFRONT__
|
||||||
|
#include <14:pragma.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gsos.h>
|
||||||
|
#include <orca.h>
|
||||||
|
|
||||||
|
#include "makewhatis.h"
|
||||||
|
|
||||||
|
#ifdef TEST_PROCESS
|
||||||
|
short v_flag = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern GSString255Ptr __C2GSMALLOC (char *s);
|
||||||
|
extern char buffer[];
|
||||||
|
extern FILE *output_fp;
|
||||||
|
extern FILE *error_fp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void process (char *filename, char *tmp_file, FILE *whatis_fp);
|
||||||
|
*
|
||||||
|
* Pre: <filename> is the name of the file to add to the database.
|
||||||
|
* <tmp_file> is the name for the temporary file. It has not been opened.
|
||||||
|
* <whatis_fp> is a file pointer to the open whatis database file.
|
||||||
|
*
|
||||||
|
* Post: The name, section number, and description from the man page is
|
||||||
|
* appended to <whatis_fp>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void process (char *filename, char *tmp_file, FILE *whatis_fp) {
|
||||||
|
|
||||||
|
FileInfoRecGS info_record; /* used to get the file type */
|
||||||
|
char *suffix; /* points to the start of the file suffix */
|
||||||
|
static char command_buf[255]; /* used to call system(2) */
|
||||||
|
char *p1; /* a scratch pointer */
|
||||||
|
int namelength; /* length of 'name (section)' */
|
||||||
|
char *name; /* points to the file basename */
|
||||||
|
int sufflen; /* length of the filename suffix */
|
||||||
|
|
||||||
|
if (v_flag) fprintf(output_fp,"Working on file %s ...\n",filename);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the file basename and suffix
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((name = malloc (strlen(filename)+1)) == NULL) {
|
||||||
|
if (v_flag)
|
||||||
|
fprintf(error_fp,"malloc failed when processing %s -- file skipped\n",
|
||||||
|
filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy(name,filename);
|
||||||
|
if ((suffix = strchr(name,'.')) == NULL) {
|
||||||
|
if (v_flag)
|
||||||
|
fprintf(error_fp,"%s has no suffix -- file skipped\n",
|
||||||
|
filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*suffix = '\0';
|
||||||
|
suffix++;
|
||||||
|
sufflen = strlen(suffix);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* find out the file type
|
||||||
|
*/
|
||||||
|
|
||||||
|
info_record.pCount = 5;
|
||||||
|
info_record.pathname = __C2GSMALLOC(filename);
|
||||||
|
GetFileInfoGS(&info_record);
|
||||||
|
if (toolerror()) {
|
||||||
|
if (v_flag)
|
||||||
|
fprintf(error_fp,"malloc failed when processing %s -- file skipped\n",
|
||||||
|
filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process the file according to type: nroff, aroff, freeze, and compress.
|
||||||
|
* The digested result is placed in buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((info_record.fileType == 0x50u) && (info_record.auxType == 0x8010u)) {
|
||||||
|
|
||||||
|
/* is it an Appleworks GS word processor document? Use aroff */
|
||||||
|
sprintf(command_buf,"aroff -b %s >%s",filename,tmp_file);
|
||||||
|
system(command_buf);
|
||||||
|
fillbuffer(tmp_file);
|
||||||
|
|
||||||
|
} else if ( (toupper(*(suffix+sufflen-1))=='Z') &&
|
||||||
|
(*(suffix+sufflen-2)=='.')) {
|
||||||
|
|
||||||
|
/* Compressed man page; uncompress it */
|
||||||
|
sprintf(command_buf,"compress -dc %s >%s",filename,tmp_file);
|
||||||
|
system(command_buf);
|
||||||
|
fillbuffer(tmp_file);
|
||||||
|
|
||||||
|
/* fix suffix for printout */
|
||||||
|
sufflen -= 2;
|
||||||
|
*(suffix + sufflen) = '\0';
|
||||||
|
|
||||||
|
} else if ( (toupper(*(suffix+sufflen-1))=='F') &&
|
||||||
|
(*(suffix+sufflen-2)=='.')) {
|
||||||
|
|
||||||
|
/* Frozen man page; melt it */
|
||||||
|
sprintf(command_buf,"freeze -dc %s >%s",filename,tmp_file);
|
||||||
|
system(command_buf);
|
||||||
|
fillbuffer(tmp_file);
|
||||||
|
|
||||||
|
/* fix suffix for printout */
|
||||||
|
sufflen -= 2;
|
||||||
|
*(suffix + sufflen) = '\0';
|
||||||
|
|
||||||
|
} else if ((toupper(*suffix)=='L') && (*(suffix+1)=='\0')) {
|
||||||
|
|
||||||
|
/* It's a link to another man page; do nothing. */
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Assume that it's a text file */
|
||||||
|
fillbuffer(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, buffer contains the line that we need to print to
|
||||||
|
* whatis_fd. Strip off any leading spaces, then give it a nice
|
||||||
|
* formatting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
p1 = buffer;
|
||||||
|
while (isspace(*p1)) p1++;
|
||||||
|
namelength = strlen(name) + strlen(suffix) + 4;
|
||||||
|
|
||||||
|
if (namelength > (TABLENGTH * 3)) {
|
||||||
|
fprintf(whatis_fp,"%s (%s) - %s\n", name, suffix, p1);
|
||||||
|
} else if (namelength > (TABLENGTH * 2)) {
|
||||||
|
fprintf(whatis_fp,"%s (%s)\t- %s\n", name, suffix, p1);
|
||||||
|
} else if (namelength > TABLENGTH ) {
|
||||||
|
fprintf(whatis_fp,"%s (%s)\t\t- %s\n", name, suffix, p1);
|
||||||
|
} else {
|
||||||
|
fprintf(whatis_fp,"%s (%s)\t\t\t- %s\n", name, suffix, p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST_PROCESS
|
||||||
|
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s <man_page_file_name>\n",argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
process (argv[1], ":tmp:garbage", stdout);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user